/// <summary> /// Sets the form's contents in such a way that the specified highscores are displayed. /// </summary> /// <param name="highscores">A dictionary mapping from player name to highscores.</param> /// <param name="level">The level whose highscores are being displayed.</param> public void SetContents(Dictionary <string, Highscore> highscores, SokobanLevel level) { pnlHighscores.ColumnCount = 3; ctLevelPicture.ClientSize = new Size(ctLevelPicture.ClientSize.Width, (int)(ctLevelPicture.ClientSize.Width * level.Height / level.Width)); _level = level.Clone(); _level.EnsureSpace(1); List <string> playerNames = new List <string>(); foreach (string s in highscores.Keys) { Highscore h = highscores[s]; int i = 0; while ((i < playerNames.Count) && (h.CompareTo(highscores[playerNames[i]]) < 0)) { i++; } playerNames.Insert(i, s); } for (int i = 0; i < playerNames.Count; i++) { Label lblPlayerName = new Label(); lblPlayerName.Font = new Font(Font, FontStyle.Bold); lblPlayerName.Text = playerNames[i]; lblPlayerName.AutoSize = true; lblPlayerName.Margin = new Padding(5); pnlHighscores.Controls.Add(lblPlayerName, 1, i); Highscore h = highscores[playerNames[i]]; Label lblScore = new Label(); lblScore.Text = Program.Tr.Highscores.Highscores.Fmt(Program.Tr.Language.GetNumberSystem(), h.BestPushScore.Moves, h.BestPushScore.Pushes); lblScore.AutoSize = true; lblScore.Margin = new Padding(5); pnlHighscores.Controls.Add(lblScore, 2, i); } pnlHighscores.Controls.Add(btnOK, 2, playerNames.Count); pnlHighscores.Controls.Add(ctLevelPicture, 0, 0); pnlHighscores.SetRowSpan(ctLevelPicture, playerNames.Count + 1); while (pnlHighscores.ColumnStyles.Count < 3) { pnlHighscores.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize)); } while (pnlHighscores.RowStyles.Count < playerNames.Count + 1) { pnlHighscores.RowStyles.Add(new RowStyle(SizeType.AutoSize)); } }
private void saveLevel(object sender, EventArgs e) { SokobanLevel level = ctMainArea.Level.Clone(); level.EnsureSpace(0); // LevelList.EditAccept() will trigger the LevelActivating event, which in // turn will ask the user if they want to discard their changes to the level. // Since we don't want this, we have to set the Modified flag for the MainArea // to false before calling LevelList.EditAccept(). ctMainArea.Modified = false; lstLevels.EditAccept(level); }
/// <summary> /// Loads a level file from the level list. /// </summary> public void LoadLevelPack(string path) { // Will contain the list of levels and comments that we have loaded. // (We only want to add them to the listbox at the end in case we // throw an exception, because then we want to keep the old file.) List <object> loadedItems = new List <object>(); // Class to read from the text file StreamReader sr = new StreamReader(path, Encoding.UTF8); // State we're in (Empty, Comment or Level) levelReaderState state = levelReaderState.Empty; // Line last read String line; // Current comment (gets appended to until we reach the end of the comment) String comment = ""; // Current level (gets appended to until we reach the end of the level) String levelEncoded = ""; do { line = sr.ReadLine(); // If this line begins with a semicolon (';'), it's a comment. // Otherwise, it is considered part of the level and must // contain only the characters #@$.*+ or space. if (line != null && line.Length > 0 && line[0] != ';') { // check for invalid characters for (int i = 0; i < line.Length; i++) { if (line[i] != ' ' && line[i] != '#' && line[i] != '@' && line[i] != '$' && line[i] != '.' && line[i] != '*' && line[i] != '+') { throw new InvalidLevelException(); } } } // Decide whether this line belongs to a level or comment levelReaderState newState = (line == null || line.Length == 0) ? levelReaderState.Empty : line[0] == ';' ? levelReaderState.Comment : levelReaderState.Level; // If we are switching from level to comment or vice versa, // or reaching the end of the file, add the level or comment // to the level list and empty the relevant variable if (newState != state && state == levelReaderState.Comment) { loadedItems.Add(comment); comment = ""; } else if (newState != state && state == levelReaderState.Level) { SokobanLevel newLevel = new SokobanLevel(levelEncoded); newLevel.EnsureSpace(0); loadedItems.Add(newLevel); levelEncoded = ""; } // Append the line we just read to the relevant variable if (newState == levelReaderState.Comment) { comment += line.Substring(1) + "\n"; } else if (newState == levelReaderState.Level) { levelEncoded += line + "\n"; } // Update the state state = newState; } while (line != null); _activeLevelIndex = null; BeginUpdate(); Items.Clear(); foreach (object item in loadedItems) { Items.Add(item); } EndUpdate(); sr.Close(); _modified = false; Program.Settings.LevelFilename = path; }