public static void SetDefault(bool resetColours) { ///Shrnutí ///Tato metoda nastaví výchozí nastavení. Pokud se jedná o první spuštění, tak se nastaví i výchozí barvy PositionedText secondLine = new PositionedText("Game settings:", ConsoleColor.Black, (Console.WindowWidth - 14) / 2, 4); PositionedText thirdLine = new PositionedText("Use arrow keys to operate and enter to confirm", ConsoleColor.Black, (Console.WindowWidth - 46) / 2, 5); Border GameMenuBigBorder = new Border(0, 1, Console.WindowHeight - 1, Console.WindowWidth, ConsoleColor.Black, ConsoleColor.Gray, false); Border GameMenuSmallBorder = new Border(Console.WindowWidth / 2 - 37, 2, 31, 74, ConsoleColor.Black, ConsoleColor.White, false); Labels = new List <IGraphic>() { secondLine, thirdLine, GameMenuBigBorder, GameMenuSmallBorder }; //Nejprve se vytvoří grafické objekty a uloží se do fieldu Labels if (resetColours) //Pokud se jedná o první spuštění, tak se vytvoří field Colours, kam se uloží výchozí nastavení { Colours = new GameSetting[7]; Colours[0] = new GameSetting("Covered tiles colour", 10, true, false, 17); //Barva neotočených políček: Zelená Colours[1] = new GameSetting("Covered tiles secondary colour", 2, true, false, 19); //Druhá barva neotočených políček: Tmavá zelená Colours[2] = new GameSetting("Uncovered tiles colour", 9, true, false, 21); //Barva otočených políček: Modrá Colours[3] = new GameSetting("Uncovered tiles secondary colour", 1, true, false, 23); //Druhá barva otočených políček: Tmavě modrá Colours[4] = new GameSetting("Flag colour", 12, true, false, 25); //Barva vlaječek: Červená Colours[5] = new GameSetting("Highlighted tile colour", 13, true, false, 27); //Barva vybraného políčka Fialová (Magenta) Colours[6] = new GameSetting("Text colour", 14, false, true, 29); //Barva textu: Šedá Program.DefaultTextColour = (ConsoleColor)Colours[6].SettingValue.Number; //Šedá barva se nahraje také do fieldu Program.DefaultTextColour, čili všechny texty budou mít šedou barvu Program.TakenColours.Clear(); //Restartuje se field Program.TakenColours a nahrají se do něj výchozí barvy foreach (GameSetting gameSetting in Colours) //Projede se celý Array { Program.TakenColours.Add((ConsoleColor)gameSetting.SettingValue.Number); //A zapíše se vybraná barva } } Console.BackgroundColor = ConsoleColor.Black; Console.Clear(); //Na závěr se vymaže Console PrintGraphics(true); //A vytisknou se nově vytvořené grafiky }
} //Obtížnost z Enumu obtížností (Easy = 1; Medium = 2; Hard = 3) public GameMenu(string name, Difficulties difficulty) //Konstruktor menu přijme název a obtížnost, z obtížnosti se vypočítají počty políček a min { if (((Console.LargestWindowWidth - 5) > Console.WindowWidth) || ((Console.LargestWindowHeight - 3) > Console.WindowHeight)) //Pokud není hra na celou obrazovku počká se dokud to uživatel nenapraví, jinak by se mohly grafiky špatně vytisknout { Program.WaitForFix(); } Difficulty = difficulty; Name = new PositionedText(name, ConsoleColor.Black, (Console.WindowWidth - name.Length) / 2, 3); //Jméno se převede ze Stringu do PositionedTextu int mines = 5 * (int)Math.Pow((int)difficulty, 2) * ((int)difficulty + 1); //Počet min se vypočítá z obtížnosti (obtížnost^3 + obtížnost^2) GameSettings = new GameSetting[3]; //Vytvoří se Array GameSettingů GameSettings[0] = new GameSetting("Number of horizontal tiles", (int)difficulty * 10, false, false, 10); //Počet políček v obou směrech se rovná GameSettings[1] = new GameSetting("Number of vertical tiles", (int)difficulty * 10, false, false, 12); //10*obtížnost GameSettings[2] = new GameSetting("Number of mines", mines, false, false, 14); //Miny byly již vypočítány, vše ale musí dostat svoji grafickou podobu přes GameSetting ChosenLine = 0; //Výchozím vybraným řádkem je první (nultý) řádek }
} //Boolean, který určuje zda se jedná o nastavení barvy textu public GameSetting(string text, int defaultValue, bool colourable, bool textColour, int line) //Konstruktor obdrží název nastavení, jeho výchozí hodnotu, booleany týkající se barev a pozici { text += ": "; //K názvu se přidá dvojtečka a mezera ConsoleColor background; if (colourable) { background = (ConsoleColor)defaultValue; } else { background = ConsoleColor.Black; } Colour = colourable; TextColour = textColour; Setting = new PositionedText(text, background, ((Console.WindowWidth - (text.Length + 8)) / 2), line); //Název a hodnota se převedou do grafické podoby SettingValue = new PositionedNumber(defaultValue, background, ((Console.WindowWidth + text.Length - 8) / 2), line); }
private static void SaveHighscore() { ///Shrnutí ///Tato metoda uloží Highscore do tabulky se zvolenou přezdívkou PositionedText nickname = new PositionedText("Enter your Nickname: ", ConsoleColor.Black, (Console.WindowWidth - 40) / 2, 21); //Grafika vyzve hráče, aby zapsal přezdívku, pod kterou bude skóre v tabulce uloženo nickname.Print(true, Reprint); do { Console.SetCursorPosition(Console.WindowWidth / 2 + 1, 21); //Umistí kurzor na pozici, kam se bude brzy psát název Console.Write(new string(' ', 50)); //Vymaže následujících 50 charů, aby hráč mohl psát na volné místo Console.SetCursorPosition(Console.WindowWidth / 2 + 1, 21); //Znovu umistí kurzor na pozici Console.CursorVisible = true; //Zviditelní kurzor, aby bylo jasné, že se očekává zadávání textu Console.ForegroundColor = ConsoleColor.White; //Nastaví se barva textu na bílou bvarvou Nickname = Console.ReadLine(); //Přečte zadaný text a uloží jej do fieldu Nickname if (Nickname.Contains(" ") || Nickname.Length > 20 || Nickname == "") //Pokud je přezdívka příliš dlouhá nebo příliš krátká a nebo obsahuje tři mezery (kterými se odděluje přezdívka od skóre), tak je uživateli zobrazeno, že přezdívka je neplatná a pokusí se jii zadat znovu { (new PositionedText("Invalid or too long nickname!", ConsoleColor.Black, Console.WindowWidth / 2 - 9, 23)).Print(false, Reprint); Nickname = ""; } } while (Nickname == ""); //Tato metoda trvá dokud není zadána validní přezdívka Console.CursorVisible = false; //Znovu se skryje text, protože už se žádný text zadávat nebude try //Pokusíme se upravit seznam nejlepší výkonů { int[] gameParameters = GameControls.PlayedGame.GetParameters(); //Získáme parametry dohrané hry string entry = $"{Nickname} {Score} {gameParameters[0]}×{gameParameters[1]} minefield with {gameParameters[2]} mines in {GameControls.CompletionTime}"; //Ty se společně s Přezdívkou a skóre zapíší do stringu, který se bude zapisovat do tabulky List <string> currentLeaderboard = new List <string>(File.ReadAllLines(Path)); //Nejprve se získá současný seznam currentLeaderboard.Insert(Position - 1, entry); //Na správnou pozici se vloží tento string if (currentLeaderboard.Count == 11) //Pokud přesáhne počet zapsaných výkonů 10 { currentLeaderboard = currentLeaderboard.GetRange(0, 10); //Tak se odstraní poslední výkon } File.WriteAllLines(Path, currentLeaderboard); //Nový seznam se zapíše zpátky do souboru Program.ShowLeaderboards(); //Po zapsání do tabulky zobrazíme hráči nově vypadající tabulku nejlepších výkonů } catch (Exception e) //Pokud dojde k chybě, informujeme uživatele { Console.WriteLine($"The file {Path} couldn't be changed. Please check your acces-rights"); Console.WriteLine("Your score couldn't be saved"); Console.WriteLine(e.Message); } return; }
} //Seznam názvů uložených souborů, které se dají do typu PositionedText public static bool PauseGameMenu() { ///Shrnutí ///Základní metoda PauseMenu, která vrátí boolean podle toho, zda hráč chce pokračovat ve hře nebo zda chce hru ukončit if (((Console.LargestWindowWidth - 5) > Console.WindowWidth) || ((Console.LargestWindowHeight - 3) > Console.WindowHeight)) //Nejprve se ověří, zda je hra na celou obrazovku, protože jinak by se mohly vytvořit grafiky na chybných pozicích { Program.WaitForFix(); //Počká se tedy, než hráč dá hru na celou obrazovku } Console.BackgroundColor = ConsoleColor.Black; Console.Clear(); //Obrazovka se smaže CurrentTime = GameControls.CompletionTime; //Načte se uběhlý čas ze hry Border PauseBigBorder = new Border(0, 1, Console.WindowHeight - 1, Console.WindowWidth, ConsoleColor.Black, ConsoleColor.Gray, false); Border PauseSmallBorder = new Border(Console.WindowWidth / 2 - 30, 18, 9, 60, ConsoleColor.Black, ConsoleColor.Gray, false); PositionedText PausedGame = new PositionedText("Game is paused", ConsoleColor.Black, Console.WindowWidth / 2 - 7, 20); PositionedText Unpause = new PositionedText("Continue", ConsoleColor.Black, Console.WindowWidth / 2 - 27, 24); PositionedText SaveGame = new PositionedText("Save game", ConsoleColor.Black, Console.WindowWidth / 2 - 16, 24); PositionedText LoadGame = new PositionedText("Load game", ConsoleColor.Black, Console.WindowWidth / 2 - 4, 24); PositionedText BackToMenu = new PositionedText("Back to Menu", ConsoleColor.Black, Console.WindowWidth / 2 + 8, 24); PositionedText Quit = new PositionedText("Quit", ConsoleColor.Black, Console.WindowWidth / 2 + 23, 24); string time = "Current time: " + CurrentTime.ToString(); PositionedText Time = new PositionedText(time, ConsoleColor.Black, (Console.WindowWidth - time.Length) / 2, 22); //Vytvoří se všechny grafiky Labels = new IGraphic[4]; Labels[0] = PauseBigBorder; Labels[1] = PauseSmallBorder; Labels[2] = PausedGame; Labels[3] = Time; SwitchableLabels = new PositionedText[5]; SwitchableLabels[0] = Unpause; SwitchableLabels[1] = SaveGame; SwitchableLabels[2] = LoadGame; SwitchableLabels[3] = BackToMenu; SwitchableLabels[4] = Quit; //A grafiky se uloží do svých arrayů. Tlačítka do SwitchableLabels, zbytek do Labels ChosenLabel = 0; //Nastaví se vybrané tlačítko na nulu (Continue – Pokračovat) for (int x = 0; x < 4; x++) //Vytisknou se grafické objekty { Labels[x].Print(x < 2, Reprint); //Oba obdélníky se vytisnou se silnými svislými liniemi. Pokud při tištění není hra nastavena na celou obrazovku, počká se na opravu od uživatele, vymaže se Console a toto menu se vytiskne znovu } ConsoleKey keypressed = 0; //Nyní budeme opět číst klávesu while (true) //Začíná nekonečný while cyklus, který se dá opustit pouze tím, že hráč vrátí true (pokračovat ve hře), false (vrátit se do menu) nebo ukončí program { for (int x = 0; x < 5; x++) //Před stisknutím klávesy se vytisknou všechna tlačítka { SwitchableLabels[x].Print(x == ChosenLabel, Reprint); //Pokud je tlačítko na vybrané pozici, tak se vytiskne bílou barvou (zvýrazněně). Pokud při tištění není hra nastavena na celou obrazovku, počká se na opravu od uživatele, vymaže se Console a toto menu se vytiskne znovu } keypressed = Console.ReadKey(true).Key; //Nyní se přečte klávesa od uživatele switch (keypressed) { case ConsoleKey.RightArrow: //Pokud uživatel zmáčkne šipku doprava tak se pokusíme posunout o jedno doprava (tedy zvýšit číslo o jedna) if (ChosenLabel != 4) //Stane se tak pokud již nejsme na maximální hodnotě 4 (tedy Quit – Ukončit) { ChosenLabel++; } break; case ConsoleKey.LeftArrow: //Pokud uživatel zmáčkne šipku doleva tak se pokusíme posunout o jedno doleva (tedy snížit číslo o jedna) if (ChosenLabel != 0) //Stane se tak pokud již nejsme na svém minimu 0 (tedy Continue – pokračovat) { ChosenLabel--; } break; case ConsoleKey.Escape: //Pokud uživatel zmáčkne Escape, tak se okamžitě vrátí do hry (Escapem pauzu zapne i ukončí) return(true); case ConsoleKey.Enter: //Enterem hráč potvrdí svoji volbu switch (ChosenLabel) { case 0: //Pokud je vybráno tlačítko Continue (Pokračovat), tak se vrátí true a pokračuje se ve hře return(true); case 1: //Pokud je vybráno tlačítko Save game (Uložit hru), tak se hra uloží pomocí metody SaveTheGame() SaveTheGame(); Console.BackgroundColor = ConsoleColor.Black; //Když se hráč vrátí zpěrt Console.Clear(); //Vymaží se grafiky ukládání for (int x = 0; x < 4; x++) //A znovu se vytisknou grafické objekty kromě tlačítek (tlačítka se vytisknou poté na začátku další fáze while cyklu) { Labels[x].Print(x < 2, Reprint); //Oba obdélníky se vytisnou se silnými svislými liniemi. Pokud při tištění není hra nastavena na celou obrazovku, počká se na opravu od uživatele, vymaže se Console a toto menu se vytiskne znovu } break; case 2: //Pokud je vybráno tlačítko Load game (Načíst hru), tak se zavolá metoda LoadTheGame(), která vrací bool. Tento bool určuje zda hráč skutečně hru načetl nebo si to v průběhu rozmyslel/nebyly žádné hry k načtení if (LoadTheGame()) //Pokud se hra úspěšně načetla { Console.BackgroundColor = ConsoleColor.Black; //Smaže se současné vytisklé menu Console.Clear(); return(true); //Vrátí se true, protože chceme pokračovat ve hře. Nicméně metoda LoadTheGame() ji změnila právě na hru ze souborui } else //Pokud hra nebyla úspěšně načtena { Console.BackgroundColor = ConsoleColor.Black; Console.Clear(); //Smaží se grafiky načítání hry for (int x = 0; x < 4; x++) //A znovu se vytisknou grafické objekty kromě tlačítek (tlačítka se vytisknou poté na začátku další fáze while cyklu) { Labels[x].Print(x < 2, Reprint); //Oba obdélníky se vytisnou se silnými svislými liniemi. Pokud při tištění není hra nastavena na celou obrazovku, počká se na opravu od uživatele, vymaže se Console a toto menu se vytiskne znovu } break; } case 3: //Pokud je vybráno tlačítko Back to menu { Console.BackgroundColor = ConsoleColor.Black; Console.Clear(); //Smaže se současné menu return(false); //Vrátí se false, což v GameControls nastaví GameAbported na true a vrátí nás do prvního menu } case 4: //Pokud je vybráno tlačítko Quit Environment.Exit(0); //Program se ukončí s číselným kódem 0 break; } break; case ConsoleKey.R: //Pokud uživatel zmáčkne R zavolá se metoda Reprint try { Reprint(); //Pokusí se vymazat menu a vytisknout jej znovu } catch (ArgumentOutOfRangeException) //Pokud nastane situace, že něco by se mělo tisknout mimo obrazovku { Program.WaitForFix(); //Vyzve uživatele, aby zvětšil hru na celou obrazovku a nepustí ho dál dokud tak neučiní Reprint(); //Znovu se pokusí vymazat menu a vytisknout jej znovu } break; } } }
///Shrnutí ///Ve statické třídě Program jsou uloženy některé důležité globální hodnoty a metody. Například barva textu nebo metoda, která požaduje opravu velikosti okna neo metoda, která zobrazuje tabulku nejlepších výsledků. static void Main() {///Shrnutí ///Základní metoda Main() nejprve donutí uživatele zvětšit okno na celou obrazovku a následně zobrazí první menu, které má tři tlačítka ///Play Minesweeper: Otevřít menu, kterým se vytváří nastavení hry ///Show Highscores: Zobrazit tabulku nejlepších výsledků ///Quit: Ukončit program Console.BackgroundColor = ConsoleColor.Black; //Restartuje barvu pozadí v konzoli na černou Console.ForegroundColor = ConsoleColor.Yellow; //Nastaví barvu textu v konzoli na žlutou TakenColours = new List <ConsoleColor>(); //Ve fieldu TakenColors se vytvoří nový prázdný seznam, do kterého budou později přidávány a odebírany barvy. Pokud je nějaká barva v seznamu, není možné nějaké nastavení na tuto barvu změnit, aby nemohly mít dva artikly stejnou barvu. Console.CursorVisible = false; //Skryje kurzor, neboť působí rušivě Console.WriteLine("Please fullscreen"); //Objeví se zpráva uživateli, aby zvětšil okno na celou obrazovku Console.WriteLine("Alt+Enter is highly recommended"); //Uživateli je doporučeno, aby okno zvětšil stiskutím kláves Alt+Enter, a ne pouze maximilizováním okna. Console.WriteLine("It is not recommended to Alt+Tab during the game or to un-fullscreen the game"); //Na závěr je uživateli doporučeno, aby hru neschovával na lištu stisknutím kláves Alt+Tab nebo zmenšoval okno while (((Console.LargestWindowWidth - 5) > Console.WindowWidth) || ((Console.LargestWindowHeight - 3) > Console.WindowHeight)) { } //Prázdný while cyklus čekající na zvětšení okna donutí uživatele zvětšit hru na celou obrazovku. while (Console.KeyAvailable) { Console.ReadKey(true); //Tento while cyklus odstraní ze streamu kláves všechny stisknuté klávesy. Dokud není stream kláves prázdný čte klávesy a nechává je být. } Console.CursorVisible = false; //Znovu skryje kurzor, který se může při zvětšení okna znovu objevit DefaultTextColour = ConsoleColor.Yellow; //Výchozí barva textu se nastaví na žlutou, která je stále velmi dobře čitelná na černém podkladu. Bílá barva se bude používat na zvýrazňování vybraného tlačítka. FirstStart = true; //Field FirstStart, který indikuje zda uživatel zapíná nastavení hry poprvé, se nastaví na true PositionedText PlayGame = new PositionedText("Play Minesweeper", ConsoleColor.Black, Console.WindowWidth / 2 - 8, 10); //Vytvoří se tlačítko, kterým se zapíná hra PositionedText ShowHighscores = new PositionedText("See Highscores", ConsoleColor.Black, Console.WindowWidth / 2 - 7, 12); //Vytvoří se tlačítko, kterým se zobrazují nejlepší výsledky PositionedText Quit = new PositionedText("Quit", ConsoleColor.Black, Console.WindowWidth / 2 - 2, 14); //Vytvoří se tlačítko, kterým se dá hra ukončit Border MainMenuSmallBorder = new Border(Console.WindowWidth / 2 - 10, 8, 10, 20, ConsoleColor.Black, ConsoleColor.White, false); //Vytvoří se obdélník, který ohraničuje všechna tři tlačítka Border MainMenuBigBorder = new Border(0, 1, Console.WindowHeight - 1, Console.WindowWidth, ConsoleColor.Black, ConsoleColor.Gray, false); //Vytvoří se velký obdélník, který ohraničuje celou obrazovku ChosenLabel = 0; //Field ChosenLabel, který označuje vybrané tlačítko se nastaví na 0 Labels = new List <IGraphic> { PlayGame, ShowHighscores, Quit, MainMenuSmallBorder, MainMenuBigBorder }; //Field Labels je seznam všech grafických artiklů — tlačítek a obdélníků ConsoleKey keypressed = 0; //Stisknuté tlačítko je nastaveno na nulu a bude se číst od uživatele Console.Clear(); //Vyčistí obrazovku a připraví ji na vytisknutí prvního menu for (int x = 3; x < 5; x++) { Labels[x].Print(x == 4, Reprint); //Vytiskne první menu. Obdelník na pozici 4, tedy velký obdélník ohraničující celou obrazovku se vytiskne jako solid – jeho svislé čáry mají tloušťku dvou charů. Pokud při tištění není hra nastavena na celou obrazovku, počká se na opravu od uživatele, vymaže se Console a vytiskne se toto menu znovu od začátku } while (true) //Následuje nekonečný while cyklus, který se dá ukončit pouze vypnutím programu přes tlačítko Quit { for (int x = 0; x < 3; x++) { Labels[x].Print(x == ChosenLabel, Reprint); //Nejprve se znovu vytisknou všechna tlačítka. Pokud se pozice tlačítka shoduje s intem ve fieldu ChosenLabel vytiskne se zvýrazněně, tedy bílou barvou. Pokud při tištění není hra nastavena na celou obrazovku, počká se na opravu od uživatele, vymaže se Console a vytiskne se toto menu znovu od začátku } keypressed = Console.ReadKey(true).Key; //Přečte klávesu, kterou stiskne uživatel switch (keypressed) { case ConsoleKey.UpArrow: //Pokud uživatel stiskne šipku nahoru if (ChosenLabel != 0) //A ChosenLabel už není na svém minimu tedy na nule { ChosenLabel--; //Sníží se ChosenLabel o jedna, tedy se zvýrazní a vybere tlačítko o jedna výše } break; case ConsoleKey.DownArrow: //Pokud uživatel stiskne šipku dolů if (ChosenLabel != 2) //A ChosenLabel už není na svém maximu tedy na dvojce { ChosenLabel++; //Zvýší se ChosenLabel o jedna, tedy se zvýrazní a vybere tlačítko o jedna níže } break; case ConsoleKey.Enter: //Pokud uživatel zmáčkne Enter, tak se potvrdí aktuální výběr switch (ChosenLabel) //Co se bude dít dál rozhodne to, které tlačítko je vybráno { case 0: //Pokud je ChosenLabel 0, tedy vybraným tlačítkem je Play Minesweeper DiffSwitcher.StartMenu(FirstStart); //Přejde se do statické třídy DiffSwitcher, která vytiskne menu s nastaveními hry a umožní je měnit, pokud se jedná o první start, nastaví se výchozí hodnoty. Jinak se zůstávají předchozí hodnoty FirstStart = false; //Když se uživatel vrátí z herního menu zpátky do prvního menu, tak se nastaví field FirstStart na false Console.BackgroundColor = ConsoleColor.Black; //Následně se obrazovka vyčistí od předchozího menu Console.Clear(); for (int x = 0; x < 5; x++) //A znovu se vytisknou všechny grafické artikly { Labels[x].Print(x == 4, Reprint); //Artikl s pozicí 4, kterým je velký obdélník okolo celé obrazovky, se vytiskne s širokými svislými liniemi. Pokud při tištění není hra nastavena na celou obrazovku, počká se na opravu od uživatele, vymaže se Console a vytiskne se toto menu znovu od začátku } break; case 1: //Pokud je ChosenLabel 1, tedy vybraným tlačítkem je ShowLeaderboards ShowLeaderboards(); //Zavolá místní statickou metodu ShowLeaderboards, která zobrazuje nejlepší výsledky for (int x = 0; x < 5; x++) //Poté, co si je uživatel prohlídne a vrátí se zpátky do menu se vytisknou všechny grafické artikly { Labels[x].Print(x == 4, Reprint); //Artikl s pozicí 4, kterým je velký obdélník okolo celé obrazovky, se vytiskne s širokými svislými liniemi. Pokud při tištění není hra nastavena na celou obrazovku, počká se na opravu od uživatele, vymaže se Console a vytiskne se toto menu znovu od začátku } break; case 2: //Pokud je ChosenLabel 2, tedy vybraným tlačítkem je Quit Environment.Exit(0); //Ukončí se program s výstupním kódem 0 break; } break; case ConsoleKey.R: //Pokud uživatel zmáčkne R zavolá se metoda Reprint try { Reprint(); //Pokusí se vymazat menu a vytisknout jej znovu } catch (ArgumentOutOfRangeException) //Pokud nastane situace, že něco by se mělo tisknout mimo obrazovku { WaitForFix(); //Vyzve uživatele, aby zvětšil hru na celou obrazovku a nepustí ho dál dokud tak neučiní Reprint(); //Znovu se pokusí vymazat menu a vytisknout jej znovu } break; } } }