Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- namespace SimpleGameMap
- {
- internal struct Record
- {
- public int Width;
- public int Height;
- public int TreasureCount;
- public TimeSpan Time;
- }
- internal class Game
- {
- private const char Wall = '#';
- private const char Floor = '.';
- private const char Treasure = 'T';
- private const char Player = '@';
- private const char BorderTopLeft = '+';
- private const char BorderTopRight = '+';
- private const char BorderBottomLeft = '+';
- private const char BorderBottomRight = '+';
- private const char BorderHorizontal = '-';
- private const char BorderVertical = '|';
- private char[,] map;
- private int playerRow;
- private int playerColumn;
- private int currentScore;
- private int totalTreasures;
- private readonly int mapHeight;
- private readonly int mapWidth;
- private readonly int treasureCount;
- private DateTime startTime;
- public TimeSpan PlayTime { get; private set; }
- private int Rows => map.GetLength(0);
- private int Columns => map.GetLength(1);
- private const int InfoLines = 3;
- private int TotalDrawLines => Rows + 2 + InfoLines;
- private readonly Random random = new Random();
- public Game(int height, int width, int treasureCount)
- {
- mapHeight = height;
- mapWidth = width;
- this.treasureCount = treasureCount;
- InitializeMap();
- SpawnPlayer();
- PlaceTreasures();
- currentScore = 0;
- }
- public bool Run()
- {
- Console.CursorVisible = false;
- Console.Clear();
- startTime = DateTime.Now;
- bool isRunning = true;
- bool victory = false;
- while (isRunning == true)
- {
- DrawMap();
- ConsoleKeyInfo keyInfo = Console.ReadKey(true);
- if (keyInfo.Key == ConsoleKey.Escape)
- {
- var menuResult = ShowPauseMenu();
- if (menuResult == PauseMenuResult.ExitToMainMenu)
- {
- isRunning = false;
- }
- }
- else
- {
- ProcessPlayerInput(keyInfo);
- if (currentScore == totalTreasures)
- {
- victory = true;
- isRunning = false;
- }
- }
- }
- PlayTime = DateTime.Now - startTime;
- if (victory == true)
- {
- ShowVictory();
- return true;
- }
- else
- {
- ShowGameInterrupted();
- Console.CursorVisible = true;
- return false;
- }
- }
- private void InitializeMap()
- {
- map = new char[mapHeight, mapWidth];
- for (int row = 0; row < mapHeight; row++)
- {
- for (int column = 0; column < mapWidth; column++)
- {
- map[row, column] = Wall;
- }
- }
- GenerateMaze();
- }
- private void GenerateMaze()
- {
- int startRow = random.Next(1, mapHeight - 1);
- int startColumn = random.Next(1, mapWidth - 1);
- map[startRow, startColumn] = Floor;
- var frontierCells = new List<(int row, int column)>();
- AddFrontierCells(startRow, startColumn, frontierCells);
- while (frontierCells.Count > 0)
- {
- int randomIndex = random.Next(frontierCells.Count);
- var (currentRow, currentColumn) = frontierCells[randomIndex];
- frontierCells.RemoveAt(randomIndex);
- int passageNeighbourCount = 0;
- int[] rowOffsets = { -1, 1, 0, 0 };
- int[] columnOffsets = { 0, 0, -1, 1 };
- foreach (var directionIndex in new[] { 0, 1, 2, 3 })
- {
- int neighbourRow = currentRow + rowOffsets[directionIndex];
- int neighbourColumn = currentColumn + columnOffsets[directionIndex];
- if (neighbourRow >= 0 && neighbourRow < mapHeight &&
- neighbourColumn >= 0 && neighbourColumn < mapWidth &&
- map[neighbourRow, neighbourColumn] == Floor)
- {
- passageNeighbourCount++;
- }
- }
- if (passageNeighbourCount == 1)
- {
- map[currentRow, currentColumn] = Floor;
- AddFrontierCells(currentRow, currentColumn, frontierCells);
- }
- }
- }
- private void AddFrontierCells(int row, int column, List<(int, int)> frontierCells)
- {
- int[] rowOffsets = { -1, 1, 0, 0 };
- int[] columnOffsets = { 0, 0, -1, 1 };
- for (int direction = 0; direction < 4; direction++)
- {
- int neighbourRow = row + rowOffsets[direction];
- int neighbourColumn = column + columnOffsets[direction];
- if (neighbourRow >= 0 && neighbourRow < mapHeight &&
- neighbourColumn >= 0 && neighbourColumn < mapWidth &&
- map[neighbourRow, neighbourColumn] == Wall)
- {
- if (frontierCells.Contains((neighbourRow, neighbourColumn)) == false)
- {
- frontierCells.Add((neighbourRow, neighbourColumn));
- }
- }
- }
- }
- private List<(int row, int column)> GetFreeCells(int excludeRow = -1, int excludeColumn = -1)
- {
- var freeCells = new List<(int, int)>();
- for (int row = 0; row < mapHeight; row++)
- {
- for (int column = 0; column < mapWidth; column++)
- {
- if (map[row, column] != Wall && (row == excludeRow && column == excludeColumn) == false)
- {
- freeCells.Add((row, column));
- }
- }
- }
- return freeCells;
- }
- private void SpawnPlayer()
- {
- var freeCells = GetFreeCells();
- if (freeCells.Count == 0)
- {
- playerRow = 1;
- playerColumn = 1;
- return;
- }
- int randomIndex = random.Next(freeCells.Count);
- (playerRow, playerColumn) = freeCells[randomIndex];
- }
- private void PlaceTreasures()
- {
- var freeCells = GetFreeCells(playerRow, playerColumn);
- int treasuresToPlace = treasureCount;
- if (treasuresToPlace > freeCells.Count)
- {
- treasuresToPlace = freeCells.Count;
- }
- for (int firstIndex = 0; firstIndex < freeCells.Count; firstIndex++)
- {
- int secondIndex = random.Next(firstIndex, freeCells.Count);
- var temp = freeCells[firstIndex];
- freeCells[firstIndex] = freeCells[secondIndex];
- freeCells[secondIndex] = temp;
- }
- for (int treasureIndex = 0; treasureIndex < treasuresToPlace; treasureIndex++)
- {
- var (treasureRow, treasureColumn) = freeCells[treasureIndex];
- map[treasureRow, treasureColumn] = Treasure;
- }
- totalTreasures = treasuresToPlace;
- }
- private void ClearLines(int lineCount, int startLine = 0)
- {
- int windowWidth = Console.WindowWidth;
- for (int lineIndex = 0; lineIndex < lineCount; lineIndex++)
- {
- Console.SetCursorPosition(0, startLine + lineIndex);
- Console.Write(new string(' ', windowWidth));
- }
- }
- private void DrawMap()
- {
- int mapWidthWithBorders = Columns + 2;
- int startColumn = (Console.WindowWidth - mapWidthWithBorders) / 2;
- if (startColumn < 0)
- {
- startColumn = 0;
- }
- ClearLines(TotalDrawLines);
- Console.SetCursorPosition(startColumn, 0);
- Console.Write(BorderTopLeft);
- Console.Write(new string(BorderHorizontal, Columns));
- Console.Write(BorderTopRight);
- for (int row = 0; row < Rows; row++)
- {
- Console.SetCursorPosition(startColumn, row + 1);
- Console.Write(BorderVertical);
- for (int column = 0; column < Columns; column++)
- {
- if (row == playerRow && column == playerColumn)
- {
- Console.Write(Player);
- }
- else
- {
- Console.Write(map[row, column]);
- }
- }
- Console.Write(BorderVertical);
- }
- int bottomLine = Rows + 1;
- Console.SetCursorPosition(startColumn, bottomLine);
- Console.Write(BorderBottomLeft);
- Console.Write(new string(BorderHorizontal, Columns));
- Console.Write(BorderBottomRight);
- int infoLine = bottomLine + 1;
- string scoreText = $"Счёт: {currentScore} Осталось сокровищ: {totalTreasures - currentScore}";
- string helpText = "Стрелки - движение, Esc - меню";
- Console.SetCursorPosition(startColumn, infoLine);
- Console.Write(scoreText.PadRight(mapWidthWithBorders));
- Console.SetCursorPosition(startColumn, infoLine + 1);
- Console.Write(helpText.PadRight(mapWidthWithBorders));
- }
- private void ProcessPlayerInput(ConsoleKeyInfo keyInfo)
- {
- int newPlayerRow = playerRow;
- int newPlayerColumn = playerColumn;
- switch (keyInfo.Key)
- {
- case ConsoleKey.UpArrow:
- newPlayerRow--;
- break;
- case ConsoleKey.DownArrow:
- newPlayerRow++;
- break;
- case ConsoleKey.LeftArrow:
- newPlayerColumn--;
- break;
- case ConsoleKey.RightArrow:
- newPlayerColumn++;
- break;
- default:
- return;
- }
- if (newPlayerRow >= 0 && newPlayerRow < Rows &&
- newPlayerColumn >= 0 && newPlayerColumn < Columns &&
- map[newPlayerRow, newPlayerColumn] != Wall)
- {
- if (map[newPlayerRow, newPlayerColumn] == Treasure)
- {
- currentScore++;
- map[newPlayerRow, newPlayerColumn] = Floor;
- }
- playerRow = newPlayerRow;
- playerColumn = newPlayerColumn;
- }
- }
- private PauseMenuResult ShowPauseMenu()
- {
- int menuWidth = 30;
- int menuHeight = 8;
- int startColumn = (Console.WindowWidth - menuWidth) / 2;
- int startRow = (Console.WindowHeight - menuHeight) / 2;
- Console.Clear();
- DrawFrame(startColumn, startRow, menuWidth, menuHeight);
- string title = "МЕНЮ";
- Console.SetCursorPosition(startColumn + (menuWidth - title.Length) / 2, startRow + 1);
- Console.Write(title);
- string continueText = "1. Продолжить";
- string exitToMainText = "2. Выйти в главное меню";
- string escHint = "Esc - вернуться в игру";
- Console.SetCursorPosition(startColumn + (menuWidth - continueText.Length) / 2, startRow + 3);
- Console.Write(continueText);
- Console.SetCursorPosition(startColumn + (menuWidth - exitToMainText.Length) / 2, startRow + 4);
- Console.Write(exitToMainText);
- Console.SetCursorPosition(startColumn + (menuWidth - escHint.Length) / 2, startRow + 6);
- Console.Write(escHint);
- bool waiting = true;
- PauseMenuResult result = PauseMenuResult.Continue;
- while (waiting == true)
- {
- ConsoleKeyInfo key = Console.ReadKey(true);
- if (key.Key == ConsoleKey.D1 || key.Key == ConsoleKey.NumPad1 || key.Key == ConsoleKey.Escape)
- {
- result = PauseMenuResult.Continue;
- waiting = false;
- }
- else if (key.Key == ConsoleKey.D2 || key.Key == ConsoleKey.NumPad2)
- {
- result = PauseMenuResult.ExitToMainMenu;
- waiting = false;
- }
- }
- Console.Clear();
- return result;
- }
- private void ShowVictory()
- {
- Console.Clear();
- int menuWidth = 40;
- int menuHeight = 10;
- int startColumn = (Console.WindowWidth - menuWidth) / 2;
- int startRow = (Console.WindowHeight - menuHeight) / 2;
- DrawFrame(startColumn, startRow, menuWidth, menuHeight);
- string title = "ПОБЕДА!";
- Console.SetCursorPosition(startColumn + (menuWidth - title.Length) / 2, startRow + 1);
- Console.Write(title);
- string info1 = $"Размер карты: {mapWidth} x {mapHeight}";
- string info2 = $"Сокровищ собрано: {currentScore} из {totalTreasures}";
- string info3 = $"Время: {PlayTime:mm\\:ss}";
- Console.SetCursorPosition(startColumn + (menuWidth - info1.Length) / 2, startRow + 3);
- Console.Write(info1);
- Console.SetCursorPosition(startColumn + (menuWidth - info2.Length) / 2, startRow + 4);
- Console.Write(info2);
- Console.SetCursorPosition(startColumn + (menuWidth - info3.Length) / 2, startRow + 5);
- Console.Write(info3);
- string continueText = "Нажмите любую клавишу для продолжения...";
- Console.SetCursorPosition(startColumn + (menuWidth - continueText.Length) / 2, startRow + 7);
- Console.Write(continueText);
- Console.ReadKey(true);
- Console.Clear();
- }
- private void ShowGameInterrupted()
- {
- Console.Clear();
- int menuWidth = 40;
- int menuHeight = 8;
- int startColumn = (Console.WindowWidth - menuWidth) / 2;
- int startRow = (Console.WindowHeight - menuHeight) / 2;
- DrawFrame(startColumn, startRow, menuWidth, menuHeight);
- string title = "ИГРА ПРЕРВАНА";
- Console.SetCursorPosition(startColumn + (menuWidth - title.Length) / 2, startRow + 1);
- Console.Write(title);
- string scoreText = $"Ваш счёт: {currentScore}";
- Console.SetCursorPosition(startColumn + (menuWidth - scoreText.Length) / 2, startRow + 3);
- Console.Write(scoreText);
- string continueText = "Нажмите любую клавишу для возврата...";
- Console.SetCursorPosition(startColumn + (menuWidth - continueText.Length) / 2, startRow + 5);
- Console.Write(continueText);
- Console.ReadKey(true);
- }
- private void DrawFrame(int left, int top, int width, int height)
- {
- Console.SetCursorPosition(left, top);
- Console.Write('┌' + new string('─', width - 2) + '┐');
- for (int lineIndex = 1; lineIndex < height - 1; lineIndex++)
- {
- Console.SetCursorPosition(left, top + lineIndex);
- Console.Write('│' + new string(' ', width - 2) + '│');
- }
- Console.SetCursorPosition(left, top + height - 1);
- Console.Write('└' + new string('─', width - 2) + '┘');
- }
- private enum PauseMenuResult
- {
- Continue,
- ExitToMainMenu
- }
- }
- internal static class Program
- {
- private static List<Record> records = new List<Record>();
- private static void Main()
- {
- Console.OutputEncoding = System.Text.Encoding.UTF8;
- bool exitProgram = false;
- while (exitProgram == false)
- {
- Console.Clear();
- int menuWidth = 30;
- int menuHeight = 7;
- int startColumn = (Console.WindowWidth - menuWidth) / 2;
- int startRow = (Console.WindowHeight - menuHeight) / 2;
- DrawFrame(startColumn, startRow, menuWidth, menuHeight);
- string title = "ГЛАВНОЕ МЕНЮ";
- Console.SetCursorPosition(startColumn + (menuWidth - title.Length) / 2, startRow + 1);
- Console.Write(title);
- string newGameText = "1. Новая игра";
- string recordsText = "2. История побед";
- string exitText = "3. Выход";
- Console.SetCursorPosition(startColumn + (menuWidth - newGameText.Length) / 2, startRow + 3);
- Console.Write(newGameText);
- Console.SetCursorPosition(startColumn + (menuWidth - recordsText.Length) / 2, startRow + 4);
- Console.Write(recordsText);
- Console.SetCursorPosition(startColumn + (menuWidth - exitText.Length) / 2, startRow + 5);
- Console.Write(exitText);
- ConsoleKeyInfo key = Console.ReadKey(true);
- switch (key.KeyChar)
- {
- case '1':
- StartNewGame();
- break;
- case '2':
- ShowRecords();
- break;
- case '3':
- exitProgram = true;
- break;
- }
- Console.Clear();
- }
- }
- private static int GetIntFromUser(string prompt, int min, int max)
- {
- int result = 0;
- bool valid = false;
- while (valid == false)
- {
- Console.Clear();
- int menuWidth = 50;
- int menuHeight = 7;
- int startColumn = (Console.WindowWidth - menuWidth) / 2;
- int startRow = (Console.WindowHeight - menuHeight) / 2;
- DrawFrame(startColumn, startRow, menuWidth, menuHeight);
- string title = "ВВОД ПАРАМЕТРА";
- Console.SetCursorPosition(startColumn + (menuWidth - title.Length) / 2, startRow + 1);
- Console.Write(title);
- string fullPrompt = $"{prompt} (от {min} до {max}):";
- Console.SetCursorPosition(startColumn + (menuWidth - fullPrompt.Length) / 2, startRow + 3);
- Console.Write(fullPrompt);
- Console.SetCursorPosition(startColumn + 2, startRow + 5);
- Console.Write(new string(' ', menuWidth - 4));
- Console.SetCursorPosition(startColumn + 2, startRow + 5);
- Console.CursorVisible = true;
- string input = Console.ReadLine();
- Console.CursorVisible = false;
- if (int.TryParse(input, out result) == true && result >= min && result <= max)
- {
- valid = true;
- }
- else
- {
- Console.SetCursorPosition(startColumn + 2, startRow + 6);
- Console.Write("Ошибка! Нажмите любую клавишу...".PadRight(menuWidth - 4));
- Console.ReadKey(true);
- }
- }
- return result;
- }
- private static void StartNewGame()
- {
- int width = GetIntFromUser("Введите ширину карты", 5, Console.WindowWidth - 2);
- int height = GetIntFromUser("Введите высоту карты", 5, Console.WindowHeight - 5);
- int maxTreasures = (height - 2) * (width - 2) / 2;
- int treasureCount = GetIntFromUser("Введите количество сокровищ", 1, maxTreasures);
- Game game = new Game(height, width, treasureCount);
- bool victory = game.Run();
- if (victory == true)
- {
- Record rec = new Record
- {
- Width = width,
- Height = height,
- TreasureCount = treasureCount,
- Time = game.PlayTime
- };
- records.Add(rec);
- ShowRecords();
- }
- }
- private static void ShowRecords()
- {
- Console.Clear();
- int menuWidth = 50;
- int menuHeight = Math.Max(10, records.Count + 5);
- int startColumn = (Console.WindowWidth - menuWidth) / 2;
- int startRow = (Console.WindowHeight - menuHeight) / 2;
- DrawFrame(startColumn, startRow, menuWidth, menuHeight);
- string title = "ИСТОРИЯ ПОБЕД";
- Console.SetCursorPosition(startColumn + (menuWidth - title.Length) / 2, startRow + 1);
- Console.Write(title);
- if (records.Count == 0)
- {
- string noRecords = "Пока нет записей";
- Console.SetCursorPosition(startColumn + (menuWidth - noRecords.Length) / 2, startRow + 3);
- Console.Write(noRecords);
- }
- else
- {
- string header = "Ширина Высота Сокровища Время";
- Console.SetCursorPosition(startColumn + (menuWidth - header.Length) / 2, startRow + 3);
- Console.Write(header);
- var sortedRecords = records.OrderBy(record => record.Time).ToList();
- for (int recordIndex = 0; recordIndex < sortedRecords.Count; recordIndex++)
- {
- var currentRecord = sortedRecords[recordIndex];
- string line = $"{currentRecord.Width,7} {currentRecord.Height,6} {currentRecord.TreasureCount,9} {currentRecord.Time:mm\\:ss}";
- Console.SetCursorPosition(startColumn + (menuWidth - line.Length) / 2, startRow + 4 + recordIndex);
- Console.Write(line);
- }
- }
- string backText = "Нажмите любую клавишу для возврата...";
- Console.SetCursorPosition(startColumn + (menuWidth - backText.Length) / 2, startRow + menuHeight - 2);
- Console.Write(backText);
- Console.ReadKey(true);
- }
- private static void DrawFrame(int left, int top, int width, int height)
- {
- Console.SetCursorPosition(left, top);
- Console.Write('┌' + new string('─', width - 2) + '┐');
- for (int lineIndex = 1; lineIndex < height - 1; lineIndex++)
- {
- Console.SetCursorPosition(left, top + lineIndex);
- Console.Write('│' + new string(' ', width - 2) + '│');
- }
- Console.SetCursorPosition(left, top + height - 1);
- Console.Write('└' + new string('─', width - 2) + '┘');
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment