Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Text;
- namespace SimpleGameMap
- {
- internal static class Program
- {
- private struct Record
- {
- public int Width;
- public int Height;
- public int TreasureCount;
- public TimeSpan Time;
- public int Difficulty;
- public int VisibilityMode;
- }
- private const char Wall = '#';
- private const char Floor = '.';
- private const char Treasure = 'T';
- private const char Player = '@';
- private const char Enemy = 'E';
- 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 const char InfoBorderTopLeft = '┌';
- private const char InfoBorderTopRight = '┐';
- private const char InfoBorderBottomLeft = '└';
- private const char InfoBorderBottomRight = '┘';
- private const char InfoBorderHorizontal = '─';
- private const char InfoBorderVertical = '│';
- private static char[,] map;
- private static int playerRow;
- private static int playerColumn;
- private static int currentScore;
- private static int totalTreasures;
- private static int mapHeight;
- private static int mapWidth;
- private static int treasureCount;
- private static DateTime startTime;
- private static TimeSpan playTime;
- private static int difficulty = 2;
- private static int visibilityMode = 1;
- private const int FogRadius = 6;
- private const int FlashlightRadius = 8;
- private enum Facing { Up, Down, Left, Right }
- private static Facing facing = Facing.Up;
- private static List<(int row, int column)> enemies = new List<(int row, int column)>();
- private static int enemyCount = 0;
- private static int enemyMoveEvery = 2;
- private static int stepCounter = 0;
- private static readonly Random random = new Random();
- private static readonly List<Record> records = new List<Record>();
- private static int mapStartColumn;
- private static int mapStartRow;
- private static int hudLeft;
- private static int hudTop;
- private static int hudWidth;
- private static int previousPlayerRow;
- private static int previousPlayerColumn;
- private static Facing previousFacing;
- static void Main()
- {
- Console.OutputEncoding = Encoding.UTF8;
- Console.CursorVisible = false;
- bool exitProgram = false;
- while (exitProgram == false)
- {
- Console.Clear();
- int menuWidth = 30;
- int menuHeight = 7;
- int startColumn = Math.Max(0, (Console.WindowWidth - menuWidth) / 2);
- int startRow = Math.Max(0, (Console.WindowHeight - menuHeight) / 2);
- DrawFrame(startColumn, startRow, menuWidth, menuHeight);
- ConsoleColor originalColor = Console.ForegroundColor;
- Console.ForegroundColor = ConsoleColor.Cyan;
- string title = "ГЛАВНОЕ МЕНЮ";
- Console.SetCursorPosition(startColumn + (menuWidth - title.Length) / 2, startRow + 1);
- Console.Write(title);
- Console.ForegroundColor = originalColor;
- 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 keyInfo = Console.ReadKey(true);
- switch (keyInfo.KeyChar)
- {
- case '1':
- StartNewGame();
- break;
- case '2':
- ShowRecords();
- break;
- case '3':
- exitProgram = true;
- break;
- }
- }
- Console.Clear();
- Console.CursorVisible = true;
- }
- private static void StartNewGame()
- {
- difficulty = GetIntFromUser("Введите сложность", 1, 3);
- ApplyDifficultyParams();
- visibilityMode = GetVisibilityModeFromUser();
- facing = Facing.Up;
- int requestedWidth = GetIntFromUser("Введите ширину карты", 5, Math.Max(5, Console.WindowWidth - 2));
- int requestedHeight = GetIntFromUser("Введите высоту карты", 5, Math.Max(5, Console.WindowHeight - 6));
- int maxTreasures = (requestedHeight - 2) * (requestedWidth - 2) / 2;
- if (maxTreasures < 1)
- {
- maxTreasures = 1;
- }
- int requestedTreasures = GetIntFromUser("Введите количество сокровищ", 1, maxTreasures);
- mapWidth = requestedWidth;
- mapHeight = requestedHeight;
- treasureCount = requestedTreasures;
- bool generated = GenerateMapWithAttempts(25);
- if (generated == false)
- {
- ShowMessageBox("Ошибка", "Не удалось сгенерировать подходящую карту.\nПопробуйте меньший размер или меньше сокровищ.");
- return;
- }
- currentScore = 0;
- stepCounter = 0;
- bool victory = RunGame();
- if (victory == true)
- {
- Record record = new Record
- {
- Width = mapWidth,
- Height = mapHeight,
- TreasureCount = totalTreasures,
- Time = playTime,
- Difficulty = difficulty,
- VisibilityMode = visibilityMode
- };
- records.Add(record);
- ShowRecords();
- }
- }
- private static int GetVisibilityModeFromUser()
- {
- bool isSelected = false;
- int selectedMode = 1;
- while (isSelected == false)
- {
- Console.Clear();
- string title = "РЕЖИМ ВИДИМОСТИ";
- string line1 = "1. Без тумана (видно всё)";
- string line2 = "2. Туман (радиус " + FogRadius + ")";
- string line3 = "3. Фонарик (конус + радиус " + FlashlightRadius + ")";
- string hint = "Введите 1/2/3 и нажмите Enter:";
- int maxLineLength = title.Length;
- if (line1.Length > maxLineLength)
- {
- maxLineLength = line1.Length;
- }
- if (line2.Length > maxLineLength)
- {
- maxLineLength = line2.Length;
- }
- if (line3.Length > maxLineLength)
- {
- maxLineLength = line3.Length;
- }
- if (hint.Length > maxLineLength)
- {
- maxLineLength = hint.Length;
- }
- int frameWidth = Math.Min(Console.WindowWidth, maxLineLength + 6);
- int frameHeight = Math.Min(Console.WindowHeight, 10);
- int frameLeft = Math.Max(0, (Console.WindowWidth - frameWidth) / 2);
- int frameTop = Math.Max(0, (Console.WindowHeight - frameHeight) / 2);
- DrawFrame(frameLeft, frameTop, frameWidth, frameHeight);
- ConsoleColor originalColor = Console.ForegroundColor;
- Console.ForegroundColor = ConsoleColor.Cyan;
- Console.SetCursorPosition(frameLeft + (frameWidth - title.Length) / 2, frameTop + 1);
- Console.Write(title);
- Console.ForegroundColor = originalColor;
- Console.SetCursorPosition(frameLeft + 2, frameTop + 3);
- Console.Write(line1);
- Console.SetCursorPosition(frameLeft + 2, frameTop + 4);
- Console.Write(line2);
- Console.SetCursorPosition(frameLeft + 2, frameTop + 5);
- Console.Write(line3);
- Console.SetCursorPosition(frameLeft + 2, frameTop + 7);
- Console.Write(hint);
- Console.SetCursorPosition(frameLeft + 2, frameTop + 8);
- Console.CursorVisible = true;
- string input = Console.ReadLine();
- Console.CursorVisible = false;
- int parsedMode;
- bool parsedOk = int.TryParse(input, out parsedMode);
- if (parsedOk == true && parsedMode >= 1 && parsedMode <= 3)
- {
- selectedMode = parsedMode;
- isSelected = true;
- }
- else
- {
- Console.ForegroundColor = ConsoleColor.Red;
- Console.SetCursorPosition(frameLeft + 2, frameTop + 8);
- Console.Write("Ошибка: введите 1, 2 или 3.".PadRight(Math.Max(0, frameWidth - 4)));
- Console.ForegroundColor = originalColor;
- Console.ReadKey(true);
- }
- }
- return selectedMode;
- }
- private static void ApplyDifficultyParams()
- {
- if (difficulty == 1)
- {
- enemyCount = 1;
- enemyMoveEvery = 3;
- }
- else if (difficulty == 2)
- {
- enemyCount = 2;
- enemyMoveEvery = 2;
- }
- else
- {
- enemyCount = 3;
- enemyMoveEvery = 1;
- }
- }
- private static bool GenerateMapWithAttempts(int maxAttempts)
- {
- int attemptIndex = 0;
- while (attemptIndex < maxAttempts)
- {
- InitializeMap();
- SpawnPlayer();
- bool[,] reachableMap = BuildReachableMapFromPlayer();
- int reachableCount = CountReachableNonWall(reachableMap);
- if (reachableCount >= 1 + treasureCount)
- {
- PlaceTreasures();
- SpawnEnemies();
- return true;
- }
- attemptIndex++;
- }
- InitializeMap();
- SpawnPlayer();
- PlaceTreasures();
- SpawnEnemies();
- return totalTreasures > 0;
- }
- private static bool RunGame()
- {
- Console.CursorVisible = false;
- Console.Clear();
- startTime = DateTime.Now;
- ComputeOffsets();
- DrawStaticFrameOnce();
- DrawHudFrameOnce();
- UpdateHudText();
- previousPlayerRow = playerRow;
- previousPlayerColumn = playerColumn;
- previousFacing = facing;
- DrawOverlaysInArea(0, 0, mapHeight - 1, mapWidth - 1);
- bool isRunning = true;
- bool victory = false;
- while (isRunning == true)
- {
- EnsureWindowFitsOrPauseAndRedrawIfNeeded();
- ConsoleKeyInfo keyInfo = Console.ReadKey(true);
- if (keyInfo.Key == ConsoleKey.Escape)
- {
- PauseMenuResult pauseResult = ShowPauseMenu();
- if (pauseResult == PauseMenuResult.ExitToMainMenu)
- {
- isRunning = false;
- }
- else
- {
- RedrawAllBecauseConsoleClearedByMenu();
- }
- continue;
- }
- bool moved;
- bool facingChanged;
- ProcessPlayerInput(keyInfo, out moved, out facingChanged);
- if (moved == false && facingChanged == false)
- {
- continue;
- }
- List<(int row, int column)> enemiesBeforeMove = CopyEnemiesList();
- if (moved == true)
- {
- stepCounter++;
- if (enemyCount > 0 && enemyMoveEvery > 0 && (stepCounter % enemyMoveEvery == 0))
- {
- MoveEnemies();
- }
- }
- if (IsEnemyOnPlayer() == true)
- {
- victory = false;
- isRunning = false;
- }
- else if (currentScore == totalTreasures && totalTreasures > 0)
- {
- victory = true;
- isRunning = false;
- }
- UpdateScreenAfterChanges(previousPlayerRow, previousPlayerColumn, previousFacing, enemiesBeforeMove);
- previousPlayerRow = playerRow;
- previousPlayerColumn = playerColumn;
- previousFacing = facing;
- }
- playTime = DateTime.Now - startTime;
- if (victory == true)
- {
- ShowVictory();
- Console.CursorVisible = true;
- return true;
- }
- ShowGameInterrupted();
- Console.CursorVisible = true;
- return false;
- }
- private static List<(int row, int column)> CopyEnemiesList()
- {
- List<(int row, int column)> copied = new List<(int row, int column)>(enemies.Count);
- int enemyIndex = 0;
- while (enemyIndex < enemies.Count)
- {
- copied.Add(enemies[enemyIndex]);
- enemyIndex++;
- }
- return copied;
- }
- private static void RedrawAllBecauseConsoleClearedByMenu()
- {
- Console.Clear();
- ComputeOffsets();
- DrawStaticFrameOnce();
- DrawHudFrameOnce();
- UpdateHudText();
- DrawOverlaysInArea(0, 0, mapHeight - 1, mapWidth - 1);
- }
- private static void EnsureWindowFitsOrPauseAndRedrawIfNeeded()
- {
- int neededWidth = mapWidth + 4;
- int neededHeight = mapHeight + 8;
- if (Console.WindowWidth < neededWidth || Console.WindowHeight < neededHeight)
- {
- Console.Clear();
- Console.CursorVisible = false;
- Console.WriteLine("Окно слишком маленькое для текущей карты.");
- Console.WriteLine("Нужно минимум: " + neededWidth + "x" + neededHeight);
- Console.WriteLine("Сейчас: " + Console.WindowWidth + "x" + Console.WindowHeight);
- Console.WriteLine();
- Console.WriteLine("Увеличьте окно и нажмите любую клавишу...");
- Console.ReadKey(true);
- RedrawAllBecauseConsoleClearedByMenu();
- }
- }
- private static void UpdateScreenAfterChanges(
- int oldPlayerRow,
- int oldPlayerColumn,
- Facing oldFacing,
- List<(int row, int column)> oldEnemies)
- {
- UpdateHudText();
- if (visibilityMode == 1)
- {
- RedrawSingleCell(oldPlayerRow, oldPlayerColumn);
- RedrawSingleCell(playerRow, playerColumn);
- int oldEnemyIndex = 0;
- while (oldEnemyIndex < oldEnemies.Count)
- {
- RedrawSingleCell(oldEnemies[oldEnemyIndex].row, oldEnemies[oldEnemyIndex].column);
- oldEnemyIndex++;
- }
- int newEnemyIndex = 0;
- while (newEnemyIndex < enemies.Count)
- {
- RedrawSingleCell(enemies[newEnemyIndex].row, enemies[newEnemyIndex].column);
- newEnemyIndex++;
- }
- return;
- }
- int visibleRange = (visibilityMode == 2) ? FogRadius : FlashlightRadius;
- int areaTopRow = Math.Min(oldPlayerRow, playerRow) - (visibleRange + 1);
- int areaBottomRow = Math.Max(oldPlayerRow, playerRow) + (visibleRange + 1);
- int areaLeftColumn = Math.Min(oldPlayerColumn, playerColumn) - (visibleRange + 1);
- int areaRightColumn = Math.Max(oldPlayerColumn, playerColumn) + (visibleRange + 1);
- ClampArea(ref areaTopRow, ref areaLeftColumn, ref areaBottomRow, ref areaRightColumn);
- RedrawBaseInArea(areaTopRow, areaLeftColumn, areaBottomRow, areaRightColumn);
- DrawOverlaysInArea(areaTopRow, areaLeftColumn, areaBottomRow, areaRightColumn);
- }
- private static void ClampArea(ref int topRow, ref int leftColumn, ref int bottomRow, ref int rightColumn)
- {
- if (topRow < 0)
- {
- topRow = 0;
- }
- if (leftColumn < 0)
- {
- leftColumn = 0;
- }
- if (bottomRow >= mapHeight)
- {
- bottomRow = mapHeight - 1;
- }
- if (rightColumn >= mapWidth)
- {
- rightColumn = mapWidth - 1;
- }
- }
- private static void ComputeOffsets()
- {
- int mapTotalWidth = mapWidth + 2;
- mapStartColumn = Math.Max(0, (Console.WindowWidth - mapTotalWidth) / 2);
- mapStartRow = 0;
- hudWidth = Math.Min(70, Console.WindowWidth - 2);
- if (hudWidth < 34)
- {
- hudWidth = 34;
- }
- hudLeft = mapStartColumn + (mapTotalWidth - hudWidth) / 2;
- if (hudLeft < 0)
- {
- hudLeft = 0;
- }
- hudTop = mapStartRow + mapHeight + 2;
- }
- private static void DrawStaticFrameOnce()
- {
- Console.SetCursorPosition(mapStartColumn, mapStartRow);
- Console.Write(BorderTopLeft);
- Console.Write(new string(BorderHorizontal, mapWidth));
- Console.Write(BorderTopRight);
- int rowIndex = 0;
- while (rowIndex < mapHeight)
- {
- Console.SetCursorPosition(mapStartColumn, mapStartRow + 1 + rowIndex);
- Console.Write(BorderVertical);
- int columnIndex = 0;
- while (columnIndex < mapWidth)
- {
- DrawBaseCell(rowIndex, columnIndex);
- columnIndex++;
- }
- Console.Write(BorderVertical);
- rowIndex++;
- }
- int bottomLine = mapStartRow + mapHeight + 1;
- Console.SetCursorPosition(mapStartColumn, bottomLine);
- Console.Write(BorderBottomLeft);
- Console.Write(new string(BorderHorizontal, mapWidth));
- Console.Write(BorderBottomRight);
- }
- private static void DrawHudFrameOnce()
- {
- Console.SetCursorPosition(hudLeft, hudTop);
- Console.Write(InfoBorderTopLeft);
- Console.Write(new string(InfoBorderHorizontal, hudWidth - 2));
- Console.Write(InfoBorderTopRight);
- Console.SetCursorPosition(hudLeft, hudTop + 1);
- Console.Write(InfoBorderVertical);
- Console.Write(new string(' ', hudWidth - 2));
- Console.Write(InfoBorderVertical);
- Console.SetCursorPosition(hudLeft, hudTop + 2);
- Console.Write(InfoBorderVertical);
- Console.Write(new string(' ', hudWidth - 2));
- Console.Write(InfoBorderVertical);
- Console.SetCursorPosition(hudLeft, hudTop + 3);
- Console.Write(InfoBorderBottomLeft);
- Console.Write(new string(InfoBorderHorizontal, hudWidth - 2));
- Console.Write(InfoBorderBottomRight);
- }
- private static void UpdateHudText()
- {
- int innerWidth = hudWidth - 2;
- string scoreText = "Счёт: " + currentScore + " Осталось: " + Math.Max(0, totalTreasures - currentScore);
- string infoText = "Сложность: " + difficulty + " Враги: " + enemies.Count + " Видимость: " + GetVisibilityName();
- string helpText = "↑↓←→/WASD - ход, Esc - меню";
- Console.SetCursorPosition(hudLeft + 1, hudTop + 1);
- Console.Write(CenterText(scoreText, innerWidth));
- Console.SetCursorPosition(hudLeft + 1, hudTop + 2);
- Console.Write(CenterText(infoText + " " + helpText, innerWidth));
- }
- private static void RedrawBaseInArea(int topRow, int leftColumn, int bottomRow, int rightColumn)
- {
- int rowIndex = topRow;
- while (rowIndex <= bottomRow)
- {
- int columnIndex = leftColumn;
- while (columnIndex <= rightColumn)
- {
- Console.SetCursorPosition(mapStartColumn + 1 + columnIndex, mapStartRow + 1 + rowIndex);
- DrawBaseCell(rowIndex, columnIndex);
- columnIndex++;
- }
- rowIndex++;
- }
- }
- private static void DrawOverlaysInArea(int topRow, int leftColumn, int bottomRow, int rightColumn)
- {
- int enemyIndex = 0;
- while (enemyIndex < enemies.Count)
- {
- int enemyRow = enemies[enemyIndex].row;
- int enemyColumn = enemies[enemyIndex].column;
- bool inside =
- enemyRow >= topRow && enemyRow <= bottomRow &&
- enemyColumn >= leftColumn && enemyColumn <= rightColumn;
- if (inside == true && IsVisible(enemyRow, enemyColumn) == true)
- {
- Console.SetCursorPosition(mapStartColumn + 1 + enemyColumn, mapStartRow + 1 + enemyRow);
- Console.ForegroundColor = ConsoleColor.Red;
- Console.BackgroundColor = ConsoleColor.Black;
- Console.Write(Enemy);
- Console.ResetColor();
- }
- enemyIndex++;
- }
- bool playerInside =
- playerRow >= topRow && playerRow <= bottomRow &&
- playerColumn >= leftColumn && playerColumn <= rightColumn;
- if (playerInside == true)
- {
- Console.SetCursorPosition(mapStartColumn + 1 + playerColumn, mapStartRow + 1 + playerRow);
- Console.ForegroundColor = ConsoleColor.Green;
- Console.BackgroundColor = ConsoleColor.Black;
- Console.Write(Player);
- Console.ResetColor();
- }
- }
- private static void RedrawSingleCell(int row, int column)
- {
- if (row < 0 || row >= mapHeight || column < 0 || column >= mapWidth)
- {
- return;
- }
- Console.SetCursorPosition(mapStartColumn + 1 + column, mapStartRow + 1 + row);
- DrawBaseCell(row, column);
- if (row == playerRow && column == playerColumn)
- {
- Console.SetCursorPosition(mapStartColumn + 1 + column, mapStartRow + 1 + row);
- Console.ForegroundColor = ConsoleColor.Green;
- Console.BackgroundColor = ConsoleColor.Black;
- Console.Write(Player);
- Console.ResetColor();
- return;
- }
- if (IsEnemyAt(row, column) == true)
- {
- Console.SetCursorPosition(mapStartColumn + 1 + column, mapStartRow + 1 + row);
- Console.ForegroundColor = ConsoleColor.Red;
- Console.BackgroundColor = ConsoleColor.Black;
- Console.Write(Enemy);
- Console.ResetColor();
- }
- }
- private static void DrawBaseCell(int row, int column)
- {
- if (IsVisible(row, column) == false)
- {
- Console.ForegroundColor = ConsoleColor.Black;
- Console.BackgroundColor = ConsoleColor.Black;
- Console.Write(' ');
- Console.ResetColor();
- return;
- }
- if (map[row, column] == Wall)
- {
- Console.ForegroundColor = ConsoleColor.Black;
- Console.BackgroundColor = ConsoleColor.White;
- Console.Write(' ');
- Console.ResetColor();
- return;
- }
- if (map[row, column] == Treasure)
- {
- Console.ForegroundColor = ConsoleColor.Yellow;
- Console.BackgroundColor = ConsoleColor.Black;
- Console.Write(Treasure);
- Console.ResetColor();
- return;
- }
- Console.ForegroundColor = ConsoleColor.Gray;
- Console.BackgroundColor = ConsoleColor.Black;
- Console.Write(' ');
- Console.ResetColor();
- }
- private static string GetVisibilityName()
- {
- if (visibilityMode == 1)
- {
- return "без тумана";
- }
- if (visibilityMode == 2)
- {
- return "туман(" + FogRadius + ")";
- }
- return "фонарик(" + FlashlightRadius + ")";
- }
- private static bool IsVisible(int row, int column)
- {
- if (visibilityMode == 1)
- {
- return true;
- }
- if (row == playerRow && column == playerColumn)
- {
- return true;
- }
- int deltaRow = row - playerRow;
- int deltaColumn = column - playerColumn;
- int manhattanDistance = Math.Abs(deltaRow) + Math.Abs(deltaColumn);
- if (visibilityMode == 2)
- {
- return manhattanDistance <= FogRadius;
- }
- if (manhattanDistance > FlashlightRadius)
- {
- return false;
- }
- if (facing == Facing.Up)
- {
- return (-deltaRow) >= 0 && (-deltaRow) >= Math.Abs(deltaColumn);
- }
- if (facing == Facing.Down)
- {
- return (deltaRow) >= 0 && (deltaRow) >= Math.Abs(deltaColumn);
- }
- if (facing == Facing.Left)
- {
- return (-deltaColumn) >= 0 && (-deltaColumn) >= Math.Abs(deltaRow);
- }
- if (facing == Facing.Right)
- {
- return (deltaColumn) >= 0 && (deltaColumn) >= Math.Abs(deltaRow);
- }
- return false;
- }
- private static void InitializeMap()
- {
- map = new char[mapHeight, mapWidth];
- int rowIndex = 0;
- while (rowIndex < mapHeight)
- {
- int columnIndex = 0;
- while (columnIndex < mapWidth)
- {
- map[rowIndex, columnIndex] = Wall;
- columnIndex++;
- }
- rowIndex++;
- }
- GenerateMaze();
- if (difficulty == 1)
- {
- PunchExtraHoles(15);
- }
- else if (difficulty == 2)
- {
- PunchExtraHoles(7);
- }
- else
- {
- PunchExtraHoles(0);
- }
- }
- private static void GenerateMaze()
- {
- int startRowIndex = random.Next(1, mapHeight - 1);
- int startColumnIndex = random.Next(1, mapWidth - 1);
- map[startRowIndex, startColumnIndex] = Floor;
- List<(int row, int column)> frontierCells = new List<(int row, int column)>();
- AddFrontierCells(startRowIndex, startColumnIndex, frontierCells);
- while (frontierCells.Count > 0)
- {
- int randomIndex = random.Next(frontierCells.Count);
- (int currentRow, int currentColumn) = frontierCells[randomIndex];
- frontierCells.RemoveAt(randomIndex);
- int passageNeighbourCount = 0;
- int[] rowOffsets = { -1, 1, 0, 0 };
- int[] columnOffsets = { 0, 0, -1, 1 };
- int directionIndex = 0;
- while (directionIndex < 4)
- {
- int neighbourRow = currentRow + rowOffsets[directionIndex];
- int neighbourColumn = currentColumn + columnOffsets[directionIndex];
- bool inBounds =
- neighbourRow >= 0 && neighbourRow < mapHeight &&
- neighbourColumn >= 0 && neighbourColumn < mapWidth;
- if (inBounds == true && map[neighbourRow, neighbourColumn] == Floor)
- {
- passageNeighbourCount++;
- }
- directionIndex++;
- }
- if (passageNeighbourCount == 1)
- {
- map[currentRow, currentColumn] = Floor;
- AddFrontierCells(currentRow, currentColumn, frontierCells);
- }
- }
- }
- private static void AddFrontierCells(int row, int column, List<(int row, int column)> frontierCells)
- {
- int[] rowOffsets = { -1, 1, 0, 0 };
- int[] columnOffsets = { 0, 0, -1, 1 };
- int directionIndex = 0;
- while (directionIndex < 4)
- {
- int neighbourRow = row + rowOffsets[directionIndex];
- int neighbourColumn = column + columnOffsets[directionIndex];
- bool inBounds =
- neighbourRow >= 0 && neighbourRow < mapHeight &&
- neighbourColumn >= 0 && neighbourColumn < mapWidth;
- if (inBounds == true && map[neighbourRow, neighbourColumn] == Wall)
- {
- bool alreadyAdded = frontierCells.Contains((neighbourRow, neighbourColumn));
- if (alreadyAdded == false)
- {
- frontierCells.Add((neighbourRow, neighbourColumn));
- }
- }
- directionIndex++;
- }
- }
- private static void PunchExtraHoles(int percent)
- {
- if (percent <= 0)
- {
- return;
- }
- int rowIndex = 1;
- while (rowIndex < mapHeight - 1)
- {
- int columnIndex = 1;
- while (columnIndex < mapWidth - 1)
- {
- if (map[rowIndex, columnIndex] == Wall)
- {
- int randomPercent = random.Next(100);
- if (randomPercent < percent)
- {
- bool hasNeighbourFloor =
- map[rowIndex - 1, columnIndex] == Floor ||
- map[rowIndex + 1, columnIndex] == Floor ||
- map[rowIndex, columnIndex - 1] == Floor ||
- map[rowIndex, columnIndex + 1] == Floor;
- if (hasNeighbourFloor == true)
- {
- map[rowIndex, columnIndex] = Floor;
- }
- }
- }
- columnIndex++;
- }
- rowIndex++;
- }
- }
- private static List<(int row, int column)> GetAllNonWallCells()
- {
- List<(int row, int column)> cells = new List<(int row, int column)>();
- int rowIndex = 0;
- while (rowIndex < mapHeight)
- {
- int columnIndex = 0;
- while (columnIndex < mapWidth)
- {
- if (map[rowIndex, columnIndex] != Wall)
- {
- cells.Add((rowIndex, columnIndex));
- }
- columnIndex++;
- }
- rowIndex++;
- }
- return cells;
- }
- private static void SpawnPlayer()
- {
- List<(int row, int column)> freeCells = GetAllNonWallCells();
- if (freeCells.Count == 0)
- {
- playerRow = 1;
- playerColumn = 1;
- map[playerRow, playerColumn] = Floor;
- return;
- }
- int randomIndex = random.Next(freeCells.Count);
- playerRow = freeCells[randomIndex].row;
- playerColumn = freeCells[randomIndex].column;
- }
- private static void RemoveAllTreasures()
- {
- int rowIndex = 0;
- while (rowIndex < mapHeight)
- {
- int columnIndex = 0;
- while (columnIndex < mapWidth)
- {
- if (map[rowIndex, columnIndex] == Treasure)
- {
- map[rowIndex, columnIndex] = Floor;
- }
- columnIndex++;
- }
- rowIndex++;
- }
- }
- private static bool[,] BuildReachableMapFromPlayer()
- {
- bool[,] reachable = new bool[mapHeight, mapWidth];
- Queue<(int row, int column)> queueCells = new Queue<(int row, int column)>();
- queueCells.Enqueue((playerRow, playerColumn));
- reachable[playerRow, playerColumn] = true;
- int[] rowOffsets = { -1, 1, 0, 0 };
- int[] columnOffsets = { 0, 0, -1, 1 };
- while (queueCells.Count > 0)
- {
- (int currentRow, int currentColumn) = queueCells.Dequeue();
- int directionIndex = 0;
- while (directionIndex < 4)
- {
- int nextRow = currentRow + rowOffsets[directionIndex];
- int nextColumn = currentColumn + columnOffsets[directionIndex];
- bool inBounds =
- nextRow >= 0 && nextRow < mapHeight &&
- nextColumn >= 0 && nextColumn < mapWidth;
- if (inBounds == true &&
- reachable[nextRow, nextColumn] == false &&
- map[nextRow, nextColumn] != Wall)
- {
- reachable[nextRow, nextColumn] = true;
- queueCells.Enqueue((nextRow, nextColumn));
- }
- directionIndex++;
- }
- }
- return reachable;
- }
- private static int CountReachableNonWall(bool[,] reachable)
- {
- int count = 0;
- int rowIndex = 0;
- while (rowIndex < mapHeight)
- {
- int columnIndex = 0;
- while (columnIndex < mapWidth)
- {
- if (reachable[rowIndex, columnIndex] == true && map[rowIndex, columnIndex] != Wall)
- {
- count++;
- }
- columnIndex++;
- }
- rowIndex++;
- }
- return count;
- }
- private static void ShuffleCells(List<(int row, int column)> cells)
- {
- int index = 0;
- while (index < cells.Count)
- {
- int swapIndex = random.Next(index, cells.Count);
- (cells[index], cells[swapIndex]) = (cells[swapIndex], cells[index]);
- index++;
- }
- }
- private static void PlaceTreasures()
- {
- RemoveAllTreasures();
- bool[,] reachable = BuildReachableMapFromPlayer();
- List<(int row, int column)> freeCells = new List<(int row, int column)>();
- int rowIndex = 0;
- while (rowIndex < mapHeight)
- {
- int columnIndex = 0;
- while (columnIndex < mapWidth)
- {
- bool canUse =
- reachable[rowIndex, columnIndex] == true &&
- map[rowIndex, columnIndex] != Wall &&
- (rowIndex == playerRow && columnIndex == playerColumn) == false;
- if (canUse == true)
- {
- freeCells.Add((rowIndex, columnIndex));
- }
- columnIndex++;
- }
- rowIndex++;
- }
- int treasuresToPlace = treasureCount;
- if (treasuresToPlace > freeCells.Count)
- {
- treasuresToPlace = freeCells.Count;
- }
- ShuffleCells(freeCells);
- int treasureIndex = 0;
- while (treasureIndex < treasuresToPlace)
- {
- int treasureRow = freeCells[treasureIndex].row;
- int treasureColumn = freeCells[treasureIndex].column;
- map[treasureRow, treasureColumn] = Treasure;
- treasureIndex++;
- }
- totalTreasures = treasuresToPlace;
- }
- private static void SpawnEnemies()
- {
- enemies.Clear();
- if (enemyCount <= 0)
- {
- return;
- }
- bool[,] reachable = BuildReachableMapFromPlayer();
- List<(int row, int column)> candidates = new List<(int row, int column)>();
- int rowIndex = 0;
- while (rowIndex < mapHeight)
- {
- int columnIndex = 0;
- while (columnIndex < mapWidth)
- {
- bool canPlace =
- reachable[rowIndex, columnIndex] == true &&
- map[rowIndex, columnIndex] != Wall &&
- (rowIndex == playerRow && columnIndex == playerColumn) == false &&
- map[rowIndex, columnIndex] != Treasure;
- if (canPlace == true)
- {
- candidates.Add((rowIndex, columnIndex));
- }
- columnIndex++;
- }
- rowIndex++;
- }
- if (candidates.Count == 0)
- {
- return;
- }
- ShuffleCells(candidates);
- int toSpawn = enemyCount;
- if (toSpawn > candidates.Count)
- {
- toSpawn = candidates.Count;
- }
- int enemyIndex = 0;
- while (enemyIndex < toSpawn)
- {
- enemies.Add(candidates[enemyIndex]);
- enemyIndex++;
- }
- }
- private static void MoveEnemies()
- {
- if (enemies.Count == 0)
- {
- return;
- }
- int[] rowOffsets = { -1, 1, 0, 0 };
- int[] columnOffsets = { 0, 0, -1, 1 };
- int enemyIndex = 0;
- while (enemyIndex < enemies.Count)
- {
- int enemyRow = enemies[enemyIndex].row;
- int enemyColumn = enemies[enemyIndex].column;
- List<(int row, int column)> possibleMoves = new List<(int row, int column)>(4);
- int directionIndex = 0;
- while (directionIndex < 4)
- {
- int nextRow = enemyRow + rowOffsets[directionIndex];
- int nextColumn = enemyColumn + columnOffsets[directionIndex];
- bool inBounds =
- nextRow >= 0 && nextRow < mapHeight &&
- nextColumn >= 0 && nextColumn < mapWidth;
- if (inBounds == true && map[nextRow, nextColumn] != Wall)
- {
- possibleMoves.Add((nextRow, nextColumn));
- }
- directionIndex++;
- }
- if (possibleMoves.Count > 0)
- {
- int decision = random.Next(100);
- (int row, int column) target;
- if (decision < 50)
- {
- target = ChooseMoveCloserToPlayer(possibleMoves);
- }
- else
- {
- target = possibleMoves[random.Next(possibleMoves.Count)];
- }
- enemies[enemyIndex] = target;
- }
- enemyIndex++;
- }
- }
- private static (int row, int column) ChooseMoveCloserToPlayer(List<(int row, int column)> moves)
- {
- int bestDistance = int.MaxValue;
- (int row, int column) bestMove = moves[0];
- int moveIndex = 0;
- while (moveIndex < moves.Count)
- {
- int distance = Math.Abs(moves[moveIndex].row - playerRow) + Math.Abs(moves[moveIndex].column - playerColumn);
- if (distance < bestDistance)
- {
- bestDistance = distance;
- bestMove = moves[moveIndex];
- }
- moveIndex++;
- }
- return bestMove;
- }
- private static bool IsEnemyOnPlayer()
- {
- int enemyIndex = 0;
- while (enemyIndex < enemies.Count)
- {
- if (enemies[enemyIndex].row == playerRow && enemies[enemyIndex].column == playerColumn)
- {
- return true;
- }
- enemyIndex++;
- }
- return false;
- }
- private static bool IsEnemyAt(int row, int column)
- {
- int enemyIndex = 0;
- while (enemyIndex < enemies.Count)
- {
- if (enemies[enemyIndex].row == row && enemies[enemyIndex].column == column)
- {
- return true;
- }
- enemyIndex++;
- }
- return false;
- }
- private static void ProcessPlayerInput(ConsoleKeyInfo keyInfo, out bool moved, out bool facingChanged)
- {
- moved = false;
- facingChanged = false;
- int newPlayerRow = playerRow;
- int newPlayerColumn = playerColumn;
- bool isDirectionKey = true;
- switch (keyInfo.Key)
- {
- case ConsoleKey.UpArrow:
- case ConsoleKey.W:
- newPlayerRow--;
- if (facing != Facing.Up) { facing = Facing.Up; facingChanged = true; }
- break;
- case ConsoleKey.DownArrow:
- case ConsoleKey.S:
- newPlayerRow++;
- if (facing != Facing.Down) { facing = Facing.Down; facingChanged = true; }
- break;
- case ConsoleKey.LeftArrow:
- case ConsoleKey.A:
- newPlayerColumn--;
- if (facing != Facing.Left) { facing = Facing.Left; facingChanged = true; }
- break;
- case ConsoleKey.RightArrow:
- case ConsoleKey.D:
- newPlayerColumn++;
- if (facing != Facing.Right) { facing = Facing.Right; facingChanged = true; }
- break;
- default:
- isDirectionKey = false;
- break;
- }
- if (isDirectionKey == false)
- {
- return;
- }
- bool inBounds =
- newPlayerRow >= 0 && newPlayerRow < mapHeight &&
- newPlayerColumn >= 0 && newPlayerColumn < mapWidth;
- if (inBounds == false)
- {
- return;
- }
- if (map[newPlayerRow, newPlayerColumn] == Wall)
- {
- return;
- }
- if (map[newPlayerRow, newPlayerColumn] == Treasure)
- {
- currentScore++;
- map[newPlayerRow, newPlayerColumn] = Floor;
- }
- playerRow = newPlayerRow;
- playerColumn = newPlayerColumn;
- moved = true;
- }
- private enum PauseMenuResult
- {
- Continue,
- ExitToMainMenu
- }
- private static PauseMenuResult ShowPauseMenu()
- {
- int menuWidth = 34;
- int menuHeight = 8;
- int startColumn = Math.Max(0, (Console.WindowWidth - menuWidth) / 2);
- int startRow = Math.Max(0, (Console.WindowHeight - menuHeight) / 2);
- Console.Clear();
- DrawFrame(startColumn, startRow, menuWidth, menuHeight);
- ConsoleColor originalColor = Console.ForegroundColor;
- Console.ForegroundColor = ConsoleColor.Cyan;
- string title = "МЕНЮ";
- Console.SetCursorPosition(startColumn + (menuWidth - title.Length) / 2, startRow + 1);
- Console.Write(title);
- Console.ForegroundColor = originalColor;
- 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 waitingForChoice = true;
- PauseMenuResult result = PauseMenuResult.Continue;
- while (waitingForChoice == true)
- {
- ConsoleKeyInfo key = Console.ReadKey(true);
- if (key.Key == ConsoleKey.D1 || key.Key == ConsoleKey.NumPad1 || key.Key == ConsoleKey.Escape)
- {
- result = PauseMenuResult.Continue;
- waitingForChoice = false;
- }
- else if (key.Key == ConsoleKey.D2 || key.Key == ConsoleKey.NumPad2)
- {
- result = PauseMenuResult.ExitToMainMenu;
- waitingForChoice = false;
- }
- }
- Console.Clear();
- return result;
- }
- private static string CenterText(string text, int width)
- {
- if (text.Length >= width)
- {
- return text.Substring(0, width);
- }
- int leftPadding = (width - text.Length) / 2;
- int rightPadding = width - text.Length - leftPadding;
- return new string(' ', leftPadding) + text + new string(' ', rightPadding);
- }
- private static void DrawFrame(int left, int top, int width, int height)
- {
- if (width < 2) width = 2;
- if (height < 2) height = 2;
- Console.SetCursorPosition(left, top);
- Console.Write('┌' + new string('─', Math.Max(0, width - 2)) + '┐');
- int lineIndex = 1;
- while (lineIndex < height - 1)
- {
- Console.SetCursorPosition(left, top + lineIndex);
- Console.Write('│' + new string(' ', Math.Max(0, width - 2)) + '│');
- lineIndex++;
- }
- Console.SetCursorPosition(left, top + height - 1);
- Console.Write('└' + new string('─', Math.Max(0, width - 2)) + '┘');
- }
- private static void ShowVictory()
- {
- Console.Clear();
- int menuWidth = 50;
- int menuHeight = 12;
- int startColumn = Math.Max(0, (Console.WindowWidth - menuWidth) / 2);
- int startRow = Math.Max(0, (Console.WindowHeight - menuHeight) / 2);
- DrawFrame(startColumn, startRow, menuWidth, menuHeight);
- ConsoleColor originalColor = Console.ForegroundColor;
- Console.ForegroundColor = ConsoleColor.Green;
- string title = "ПОБЕДА!";
- Console.SetCursorPosition(startColumn + (menuWidth - title.Length) / 2, startRow + 1);
- Console.Write(title);
- Console.ForegroundColor = originalColor;
- string info1 = "Размер карты: " + mapWidth + " x " + mapHeight;
- string info2 = "Сокровищ собрано: " + currentScore + " из " + totalTreasures;
- string info3 = "Сложность: " + difficulty;
- string info4 = "Видимость: " + GetVisibilityName();
- string info5 = "Время: " + playTime.ToString(@"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);
- Console.SetCursorPosition(startColumn + (menuWidth - info4.Length) / 2, startRow + 6);
- Console.Write(info4);
- Console.SetCursorPosition(startColumn + (menuWidth - info5.Length) / 2, startRow + 7);
- Console.Write(info5);
- string continueText = "Нажмите любую клавишу для продолжения...";
- Console.SetCursorPosition(startColumn + (menuWidth - continueText.Length) / 2, startRow + 9);
- Console.Write(continueText);
- Console.ReadKey(true);
- Console.Clear();
- }
- private static void ShowGameInterrupted()
- {
- Console.Clear();
- int menuWidth = 50;
- int menuHeight = 10;
- int startColumn = Math.Max(0, (Console.WindowWidth - menuWidth) / 2);
- int startRow = Math.Max(0, (Console.WindowHeight - menuHeight) / 2);
- DrawFrame(startColumn, startRow, menuWidth, menuHeight);
- ConsoleColor originalColor = Console.ForegroundColor;
- Console.ForegroundColor = ConsoleColor.Red;
- string title = (IsEnemyOnPlayer() == true) ? "ВАС ПОЙМАЛ ВРАГ" : "ИГРА ПРЕРВАНА";
- Console.SetCursorPosition(startColumn + (menuWidth - title.Length) / 2, startRow + 1);
- Console.Write(title);
- Console.ForegroundColor = originalColor;
- string scoreText = "Ваш счёт: " + currentScore + " из " + totalTreasures;
- string timeText = "Время: " + playTime.ToString(@"mm\:ss");
- string continueText = "Нажмите любую клавишу для возврата...";
- Console.SetCursorPosition(startColumn + (menuWidth - scoreText.Length) / 2, startRow + 3);
- Console.Write(scoreText);
- Console.SetCursorPosition(startColumn + (menuWidth - timeText.Length) / 2, startRow + 4);
- Console.Write(timeText);
- Console.SetCursorPosition(startColumn + (menuWidth - continueText.Length) / 2, startRow + 6);
- Console.Write(continueText);
- Console.ReadKey(true);
- Console.Clear();
- }
- private static void ShowMessageBox(string title, string message)
- {
- Console.Clear();
- List<string> messageLines = SplitLines(message);
- int maxLineLength = title.Length;
- int lineIndex = 0;
- while (lineIndex < messageLines.Count)
- {
- if (messageLines[lineIndex].Length > maxLineLength)
- {
- maxLineLength = messageLines[lineIndex].Length;
- }
- lineIndex++;
- }
- int frameWidth = maxLineLength + 6;
- int frameHeight = messageLines.Count + 6;
- if (frameWidth > Console.WindowWidth)
- {
- frameWidth = Console.WindowWidth;
- }
- if (frameHeight > Console.WindowHeight)
- {
- frameHeight = Console.WindowHeight;
- }
- int frameLeft = Math.Max(0, (Console.WindowWidth - frameWidth) / 2);
- int frameTop = Math.Max(0, (Console.WindowHeight - frameHeight) / 2);
- DrawFrame(frameLeft, frameTop, frameWidth, frameHeight);
- ConsoleColor originalColor = Console.ForegroundColor;
- Console.ForegroundColor = ConsoleColor.Cyan;
- Console.SetCursorPosition(frameLeft + (frameWidth - title.Length) / 2, frameTop + 1);
- Console.Write(title);
- Console.ForegroundColor = originalColor;
- int messageIndex = 0;
- while (messageIndex < messageLines.Count)
- {
- string line = messageLines[messageIndex];
- if (line.Length > frameWidth - 4)
- {
- line = line.Substring(0, frameWidth - 4);
- }
- Console.SetCursorPosition(frameLeft + 2, frameTop + 3 + messageIndex);
- Console.Write(line.PadRight(frameWidth - 4));
- messageIndex++;
- }
- Console.SetCursorPosition(frameLeft + 2, frameTop + frameHeight - 2);
- Console.Write("Нажмите любую клавишу...");
- Console.ReadKey(true);
- Console.Clear();
- }
- private static List<string> SplitLines(string text)
- {
- List<string> lines = new List<string>();
- StringBuilder current = new StringBuilder();
- int index = 0;
- while (index < text.Length)
- {
- char symbol = text[index];
- if (symbol == '\r')
- {
- }
- else if (symbol == '\n')
- {
- lines.Add(current.ToString());
- current.Clear();
- }
- else
- {
- current.Append(symbol);
- }
- index++;
- }
- lines.Add(current.ToString());
- return lines;
- }
- private static void ShowRecords()
- {
- Console.Clear();
- int menuWidth = 76;
- int menuHeight = Math.Max(12, records.Count + 6);
- int startColumn = Math.Max(0, (Console.WindowWidth - menuWidth) / 2);
- int startRow = Math.Max(0, (Console.WindowHeight - menuHeight) / 2);
- DrawFrame(startColumn, startRow, menuWidth, menuHeight);
- ConsoleColor originalColor = Console.ForegroundColor;
- Console.ForegroundColor = ConsoleColor.Cyan;
- string title = "ИСТОРИЯ ПОБЕД";
- Console.SetCursorPosition(startColumn + (menuWidth - title.Length) / 2, startRow + 1);
- Console.Write(title);
- Console.ForegroundColor = originalColor;
- if (records.Count == 0)
- {
- string noRecordsText = "Пока нет записей";
- Console.SetCursorPosition(startColumn + (menuWidth - noRecordsText.Length) / 2, startRow + 3);
- Console.Write(noRecordsText);
- }
- else
- {
- string header = "Ширина Высота Сокровища Сложн. Видимость Время";
- Console.SetCursorPosition(startColumn + (menuWidth - header.Length) / 2, startRow + 3);
- Console.Write(header);
- List<Record> sorted = new List<Record>(records.Count);
- int copyIndex = 0;
- while (copyIndex < records.Count)
- {
- sorted.Add(records[copyIndex]);
- copyIndex++;
- }
- SortRecordsByTimeThenDifficulty(sorted);
- int recordIndex = 0;
- while (recordIndex < sorted.Count && (startRow + 4 + recordIndex) < (startRow + menuHeight - 2))
- {
- Record record = sorted[recordIndex];
- string visibilityText;
- if (record.VisibilityMode == 1)
- {
- visibilityText = "без тумана";
- }
- else if (record.VisibilityMode == 2)
- {
- visibilityText = "туман(" + FogRadius + ")";
- }
- else
- {
- visibilityText = "фонарик(" + FlashlightRadius + ")";
- }
- string line =
- string.Format("{0,7} {1,6} {2,9} {3,6} {4,-14} {5}",
- record.Width,
- record.Height,
- record.TreasureCount,
- record.Difficulty,
- visibilityText,
- record.Time.ToString(@"mm\:ss"));
- Console.SetCursorPosition(startColumn + 2, startRow + 4 + recordIndex);
- Console.Write(line.PadRight(menuWidth - 4));
- recordIndex++;
- }
- }
- string backText = "Нажмите любую клавишу для возврата...";
- Console.SetCursorPosition(startColumn + (menuWidth - backText.Length) / 2, startRow + menuHeight - 2);
- Console.Write(backText);
- Console.ReadKey(true);
- Console.Clear();
- }
- private static void SortRecordsByTimeThenDifficulty(List<Record> recordList)
- {
- int firstIndex = 0;
- while (firstIndex < recordList.Count - 1)
- {
- int bestIndex = firstIndex;
- int secondIndex = firstIndex + 1;
- while (secondIndex < recordList.Count)
- {
- bool better =
- recordList[secondIndex].Time < recordList[bestIndex].Time ||
- (recordList[secondIndex].Time == recordList[bestIndex].Time &&
- recordList[secondIndex].Difficulty < recordList[bestIndex].Difficulty);
- if (better == true)
- {
- bestIndex = secondIndex;
- }
- secondIndex++;
- }
- if (bestIndex != firstIndex)
- {
- Record temp = recordList[firstIndex];
- recordList[firstIndex] = recordList[bestIndex];
- recordList[bestIndex] = temp;
- }
- firstIndex++;
- }
- }
- private static int GetIntFromUser(string prompt, int min, int max)
- {
- int result = 0;
- bool valid = false;
- while (valid == false)
- {
- Console.Clear();
- string title = "ВВОД ПАРАМЕТРА";
- string promptFull = prompt + " (от " + min + " до " + max + "):";
- int maxLength = title.Length;
- if (promptFull.Length > maxLength) maxLength = promptFull.Length;
- int menuWidth = Math.Min(Console.WindowWidth, maxLength + 6);
- if (menuWidth < 20) menuWidth = 20;
- int menuHeight = 8;
- int startColumn = Math.Max(0, (Console.WindowWidth - menuWidth) / 2);
- int startRow = Math.Max(0, (Console.WindowHeight - menuHeight) / 2);
- DrawFrame(startColumn, startRow, menuWidth, menuHeight);
- ConsoleColor originalColor = Console.ForegroundColor;
- Console.ForegroundColor = ConsoleColor.Cyan;
- Console.SetCursorPosition(startColumn + (menuWidth - title.Length) / 2, startRow + 1);
- Console.Write(title);
- Console.ForegroundColor = originalColor;
- Console.SetCursorPosition(startColumn + (menuWidth - promptFull.Length) / 2, startRow + 3);
- Console.Write(promptFull);
- 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;
- string errorMessage = null;
- if (string.IsNullOrWhiteSpace(input) == true)
- {
- errorMessage = "Ошибка: ввод не может быть пустым.";
- }
- else
- {
- int parsedValue;
- bool parseOk = int.TryParse(input, out parsedValue);
- if (parseOk == false)
- {
- errorMessage = "Ошибка: введено не число.";
- }
- else if (parsedValue < min || parsedValue > max)
- {
- errorMessage = "Ошибка: число должно быть от " + min + " до " + max + ".";
- }
- else
- {
- result = parsedValue;
- valid = true;
- }
- }
- if (errorMessage != null)
- {
- Console.ForegroundColor = ConsoleColor.Red;
- Console.SetCursorPosition(startColumn + 2, startRow + 6);
- string display = errorMessage;
- if (display.Length > menuWidth - 4)
- {
- display = display.Substring(0, menuWidth - 4);
- }
- Console.Write(display.PadRight(menuWidth - 4));
- Console.ForegroundColor = originalColor;
- Console.ReadKey(true);
- }
- }
- return result;
- }
- }
- }
Add Comment
Please, Sign In to add comment