Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Linq;
- 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 _playerY;
- private int _playerX;
- private int _score;
- private int _totalTreasures;
- private readonly int _height;
- private readonly int _width;
- private readonly int _treasureCount;
- private DateTime _startTime;
- public TimeSpan PlayTime { get; private set; }
- private int MapRows => _map.GetLength(0);
- private int MapCols => _map.GetLength(1);
- private const int InfoLines = 3;
- private int TotalDrawLines => MapRows + 2 + InfoLines;
- private readonly Random _random = new Random();
- public Game(int height, int width, int treasureCount)
- {
- _height = height;
- _width = width;
- _treasureCount = treasureCount;
- InitializeMap();
- SpawnPlayer();
- PlaceTreasures();
- _score = 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
- {
- HandleInput(keyInfo);
- if (_score == _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[_height, _width];
- for (int y = 0; y < _height; y++)
- for (int x = 0; x < _width; x++)
- _map[y, x] = Wall;
- GenerateMaze();
- }
- private void GenerateMaze()
- {
- int startY = _random.Next(1, _height - 1);
- int startX = _random.Next(1, _width - 1);
- _map[startY, startX] = Floor;
- var frontiers = new List<(int y, int x)>();
- AddFrontiers(startY, startX, frontiers);
- while (frontiers.Count > 0)
- {
- int index = _random.Next(frontiers.Count);
- var (fy, fx) = frontiers[index];
- frontiers.RemoveAt(index);
- int passageCount = 0;
- int[] dy = { -1, 1, 0, 0 };
- int[] dx = { 0, 0, -1, 1 };
- foreach (var dir in new[] { 0, 1, 2, 3 })
- {
- int ny = fy + dy[dir];
- int nx = fx + dx[dir];
- if (ny >= 0 && ny < _height && nx >= 0 && nx < _width && _map[ny, nx] == Floor)
- passageCount++;
- }
- if (passageCount == 1)
- {
- _map[fy, fx] = Floor;
- AddFrontiers(fy, fx, frontiers);
- }
- }
- }
- private void AddFrontiers(int y, int x, List<(int, int)> frontiers)
- {
- int[] dy = { -1, 1, 0, 0 };
- int[] dx = { 0, 0, -1, 1 };
- for (int d = 0; d < 4; d++)
- {
- int ny = y + dy[d];
- int nx = x + dx[d];
- if (ny >= 0 && ny < _height && nx >= 0 && nx < _width && _map[ny, nx] == Wall)
- {
- if (frontiers.Contains((ny, nx)) == false)
- frontiers.Add((ny, nx));
- }
- }
- }
- private List<(int y, int x)> GetFreeCells(int excludeY = -1, int excludeX = -1)
- {
- var free = new List<(int, int)>();
- for (int y = 0; y < _height; y++)
- for (int x = 0; x < _width; x++)
- if (_map[y, x] != Wall && (y == excludeY && x == excludeX) == false)
- free.Add((y, x));
- return free;
- }
- private void SpawnPlayer()
- {
- var free = GetFreeCells();
- if (free.Count == 0)
- {
- _playerY = 1;
- _playerX = 1;
- return;
- }
- int index = _random.Next(free.Count);
- (_playerY, _playerX) = free[index];
- }
- private void PlaceTreasures()
- {
- var free = GetFreeCells(_playerY, _playerX);
- int treasuresToPlace = _treasureCount;
- if (treasuresToPlace > free.Count)
- treasuresToPlace = free.Count;
- for (int i = 0; i < free.Count; i++)
- {
- int j = _random.Next(i, free.Count);
- var temp = free[i];
- free[i] = free[j];
- free[j] = temp;
- }
- for (int i = 0; i < treasuresToPlace; i++)
- {
- var (y, x) = free[i];
- _map[y, x] = Treasure;
- }
- _totalTreasures = treasuresToPlace;
- }
- private void ClearLines(int lineCount, int startY = 0)
- {
- int width = Console.WindowWidth;
- for (int i = 0; i < lineCount; i++)
- {
- Console.SetCursorPosition(0, startY + i);
- Console.Write(new string(' ', width));
- }
- }
- private void DrawMap()
- {
- int mapWidth = MapCols + 2;
- int startX = (Console.WindowWidth - mapWidth) / 2;
- if (startX < 0) startX = 0;
- ClearLines(TotalDrawLines);
- Console.SetCursorPosition(startX, 0);
- Console.Write(BorderTopLeft);
- Console.Write(new string(BorderHorizontal, MapCols));
- Console.Write(BorderTopRight);
- for (int y = 0; y < MapRows; y++)
- {
- Console.SetCursorPosition(startX, y + 1);
- Console.Write(BorderVertical);
- for (int x = 0; x < MapCols; x++)
- {
- if (y == _playerY && x == _playerX)
- Console.Write(Player);
- else
- Console.Write(_map[y, x]);
- }
- Console.Write(BorderVertical);
- }
- int bottomLine = MapRows + 1;
- Console.SetCursorPosition(startX, bottomLine);
- Console.Write(BorderBottomLeft);
- Console.Write(new string(BorderHorizontal, MapCols));
- Console.Write(BorderBottomRight);
- int infoLine = bottomLine + 1;
- string scoreText = $"Счёт: {_score} Осталось сокровищ: {_totalTreasures - _score}";
- string helpText = "Стрелки - движение, Esc - меню";
- Console.SetCursorPosition(startX, infoLine);
- Console.Write(scoreText.PadRight(mapWidth));
- Console.SetCursorPosition(startX, infoLine + 1);
- Console.Write(helpText.PadRight(mapWidth));
- }
- private void HandleInput(ConsoleKeyInfo keyInfo)
- {
- int newY = _playerY;
- int newX = _playerX;
- switch (keyInfo.Key)
- {
- case ConsoleKey.UpArrow: newY--; break;
- case ConsoleKey.DownArrow: newY++; break;
- case ConsoleKey.LeftArrow: newX--; break;
- case ConsoleKey.RightArrow: newX++; break;
- default: return;
- }
- if (newY >= 0 && newY < MapRows &&
- newX >= 0 && newX < MapCols &&
- _map[newY, newX] != Wall)
- {
- if (_map[newY, newX] == Treasure)
- {
- _score++;
- _map[newY, newX] = Floor;
- }
- _playerY = newY;
- _playerX = newX;
- }
- }
- private PauseMenuResult ShowPauseMenu()
- {
- int menuWidth = 30;
- int menuHeight = 8;
- int startX = (Console.WindowWidth - menuWidth) / 2;
- int startY = (Console.WindowHeight - menuHeight) / 2;
- Console.Clear();
- DrawFrame(startX, startY, menuWidth, menuHeight);
- string title = "МЕНЮ";
- Console.SetCursorPosition(startX + (menuWidth - title.Length) / 2, startY + 1);
- Console.Write(title);
- string continueText = "1. Продолжить";
- string exitToMainText = "2. Выйти в главное меню";
- string escHint = "Esc - вернуться в игру";
- Console.SetCursorPosition(startX + (menuWidth - continueText.Length) / 2, startY + 3);
- Console.Write(continueText);
- Console.SetCursorPosition(startX + (menuWidth - exitToMainText.Length) / 2, startY + 4);
- Console.Write(exitToMainText);
- Console.SetCursorPosition(startX + (menuWidth - escHint.Length) / 2, startY + 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 startX = (Console.WindowWidth - menuWidth) / 2;
- int startY = (Console.WindowHeight - menuHeight) / 2;
- DrawFrame(startX, startY, menuWidth, menuHeight);
- string title = "ПОБЕДА!";
- Console.SetCursorPosition(startX + (menuWidth - title.Length) / 2, startY + 1);
- Console.Write(title);
- string info1 = $"Размер карты: {_width} x {_height}";
- string info2 = $"Сокровищ собрано: {_score} из {_totalTreasures}";
- string info3 = $"Время: {PlayTime:mm\\:ss}";
- Console.SetCursorPosition(startX + (menuWidth - info1.Length) / 2, startY + 3);
- Console.Write(info1);
- Console.SetCursorPosition(startX + (menuWidth - info2.Length) / 2, startY + 4);
- Console.Write(info2);
- Console.SetCursorPosition(startX + (menuWidth - info3.Length) / 2, startY + 5);
- Console.Write(info3);
- string continueText = "Нажмите любую клавишу для продолжения...";
- Console.SetCursorPosition(startX + (menuWidth - continueText.Length) / 2, startY + 7);
- Console.Write(continueText);
- Console.ReadKey(true);
- Console.Clear();
- }
- private void ShowGameInterrupted()
- {
- Console.Clear();
- int menuWidth = 40;
- int menuHeight = 8;
- int startX = (Console.WindowWidth - menuWidth) / 2;
- int startY = (Console.WindowHeight - menuHeight) / 2;
- DrawFrame(startX, startY, menuWidth, menuHeight);
- string title = "ИГРА ПРЕРВАНА";
- Console.SetCursorPosition(startX + (menuWidth - title.Length) / 2, startY + 1);
- Console.Write(title);
- string scoreText = $"Ваш счёт: {_score}";
- Console.SetCursorPosition(startX + (menuWidth - scoreText.Length) / 2, startY + 3);
- Console.Write(scoreText);
- string continueText = "Нажмите любую клавишу для возврата...";
- Console.SetCursorPosition(startX + (menuWidth - continueText.Length) / 2, startY + 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 i = 1; i < height - 1; i++)
- {
- Console.SetCursorPosition(left, top + i);
- 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 startX = (Console.WindowWidth - menuWidth) / 2;
- int startY = (Console.WindowHeight - menuHeight) / 2;
- DrawFrame(startX, startY, menuWidth, menuHeight);
- string title = "ГЛАВНОЕ МЕНЮ";
- Console.SetCursorPosition(startX + (menuWidth - title.Length) / 2, startY + 1);
- Console.Write(title);
- string newGameText = "1. Новая игра";
- string recordsText = "2. История побед";
- string exitText = "3. Выход";
- Console.SetCursorPosition(startX + (menuWidth - newGameText.Length) / 2, startY + 3);
- Console.Write(newGameText);
- Console.SetCursorPosition(startX + (menuWidth - recordsText.Length) / 2, startY + 4);
- Console.Write(recordsText);
- Console.SetCursorPosition(startX + (menuWidth - exitText.Length) / 2, startY + 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 startX = (Console.WindowWidth - menuWidth) / 2;
- int startY = (Console.WindowHeight - menuHeight) / 2;
- DrawFrame(startX, startY, menuWidth, menuHeight);
- string title = "ВВОД ПАРАМЕТРА";
- Console.SetCursorPosition(startX + (menuWidth - title.Length) / 2, startY + 1);
- Console.Write(title);
- string fullPrompt = $"{prompt} (от {min} до {max}):";
- Console.SetCursorPosition(startX + (menuWidth - fullPrompt.Length) / 2, startY + 3);
- Console.Write(fullPrompt);
- Console.SetCursorPosition(startX + 2, startY + 5);
- Console.Write(new string(' ', menuWidth - 4));
- Console.SetCursorPosition(startX + 2, startY + 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(startX + 2, startY + 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 startX = (Console.WindowWidth - menuWidth) / 2;
- int startY = (Console.WindowHeight - menuHeight) / 2;
- DrawFrame(startX, startY, menuWidth, menuHeight);
- string title = "ИСТОРИЯ ПОБЕД";
- Console.SetCursorPosition(startX + (menuWidth - title.Length) / 2, startY + 1);
- Console.Write(title);
- if (_records.Count == 0)
- {
- string noRecords = "Пока нет записей";
- Console.SetCursorPosition(startX + (menuWidth - noRecords.Length) / 2, startY + 3);
- Console.Write(noRecords);
- }
- else
- {
- string header = "Ширина Высота Сокровища Время";
- Console.SetCursorPosition(startX + (menuWidth - header.Length) / 2, startY + 3);
- Console.Write(header);
- var sorted = _records.OrderBy(r => r.Time).ToList();
- for (int i = 0; i < sorted.Count; i++)
- {
- var r = sorted[i];
- string line = $"{r.Width,7} {r.Height,6} {r.TreasureCount,9} {r.Time:mm\\:ss}";
- Console.SetCursorPosition(startX + (menuWidth - line.Length) / 2, startY + 4 + i);
- Console.Write(line);
- }
- }
- string backText = "Нажмите любую клавишу для возврата...";
- Console.SetCursorPosition(startX + (menuWidth - backText.Length) / 2, startY + 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 i = 1; i < height - 1; i++)
- {
- Console.SetCursorPosition(left, top + i);
- 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