using CoopSweeper.GameTypes; using System; using System.Collections.Generic; using System.Text; namespace CoopSweeper.View { public class GameView : IView { private readonly Game _game; private IField[,] _currentMap = null; public GameView(Game game) { _game = game; } public Position Position { get; set; } public Position Cursor { get; set; } public Position MapPositon { get => new Position(Position.X + 1, Position.Y + 1); set => Position = new Position(value.X - 1, value.Y - 1); } public void Draw(bool fullRedraw) { if (fullRedraw) DrawBorder(); DrawMap(fullRedraw); } private void DrawMap(bool fullRedraw) { for (var y = 0; y < _game.Map.GetLength(1); y++) { if (_currentMap == null || fullRedraw) Console.SetCursorPosition(MapPositon.X, MapPositon.Y + y); for (var x = 0; x < _game.Map.GetLength(0); x++) { if (_currentMap != null && !fullRedraw) { var currentField = _currentMap[x, y]; var newField = _game.Map[x, y]; if (currentField == null || currentField.DisplayState != newField.DisplayState) { Console.SetCursorPosition(MapPositon.X + x, MapPositon.Y + y); DrawChar(_game.Map[x, y], x == Cursor.X && y == Cursor.Y); } } else { DrawChar(_game.Map[x, y], x == Cursor.X && y == Cursor.Y); } } } _currentMap = ArrayHelpers.Clone2D(_game.Map); } private void DrawChar(IField f, bool isCursor) { var oldBg = Console.BackgroundColor; var oldFg = Console.ForegroundColor; bool fgChanged = false; bool bgChanged = false; var c = 'E'; var state = f.DisplayState; switch (state) { case DisplayState.EMPTY: c = ' '; break; case DisplayState.NONE: bgChanged = true; fgChanged = true; Console.ForegroundColor = ConsoleColor.Black; Console.BackgroundColor = ConsoleColor.Gray; //c = '◌'; c = ' '; break; case DisplayState.QUESTIONMARK: fgChanged = true; bgChanged = true; Console.BackgroundColor = ConsoleColor.Gray; Console.ForegroundColor = ConsoleColor.DarkBlue; c = '?'; break; case DisplayState.BOMB: fgChanged = true; Console.ForegroundColor = ConsoleColor.Red; c = '☼'; break; case DisplayState.ERROR: c = 'e'; break; case DisplayState.FLAG: fgChanged = true; bgChanged = true; Console.BackgroundColor = ConsoleColor.Gray; Console.ForegroundColor = ConsoleColor.DarkRed; c = 'F'; break; case DisplayState.NUMBER1: case DisplayState.NUMBER2: case DisplayState.NUMBER3: case DisplayState.NUMBER4: case DisplayState.NUMBER5: case DisplayState.NUMBER6: case DisplayState.NUMBER7: case DisplayState.NUMBER8: fgChanged = true; switch (state) { case DisplayState.NUMBER1: Console.ForegroundColor = ConsoleColor.Green; break; case DisplayState.NUMBER2: Console.ForegroundColor = ConsoleColor.Yellow; break; case DisplayState.NUMBER3: Console.ForegroundColor = ConsoleColor.DarkYellow; break; case DisplayState.NUMBER4: Console.ForegroundColor = ConsoleColor.DarkRed; break; default: Console.ForegroundColor = ConsoleColor.Red; break; } c = ((int)state).ToString()[0]; break; } if (isCursor) { fgChanged = true; bgChanged = true; var s = Console.ForegroundColor; Console.ForegroundColor = Console.BackgroundColor; Console.BackgroundColor = s; } Console.Write(c); if (fgChanged) Console.ForegroundColor = oldFg; if (bgChanged) Console.BackgroundColor = oldBg; } private void DrawBorder() { var width = _game.Map.GetLength(0) + 2; var height = _game.Map.GetLength(1) + 2; Console.SetCursorPosition(Position.X, Position.Y); var linebuilder = new StringBuilder(); linebuilder.Append("╔"); for (var x = 0; x < width - 2; x++) linebuilder.Append("═"); linebuilder.Append("╗"); Console.Write(linebuilder); for (var y = 1; y < height - 1; y++) { Console.SetCursorPosition(Position.X, Position.Y + y); Console.Write("║"); Console.SetCursorPosition(Position.X + width - 1, Position.Y + y); Console.Write("║"); } Console.SetCursorPosition(Position.X, Position.Y + height - 1); linebuilder = new StringBuilder(); linebuilder.Append("╚"); for (var x = 0; x < width - 2; x++) linebuilder.Append("═"); linebuilder.Append("╝"); Console.Write(linebuilder); // ┌──┬──┐ ╔══╦══╗ ╒══╤══╕ ╓──╥──╖ // │ │ │ ║ ║ ║ │ │ │ ║ ║ ║ // ├──┼──┤ ╠══╬══╣ ╞══╪══╡ ╟──╫──╢ // │ │ │ ║ ║ ║ │ │ │ ║ ║ ║ // └──┴──┘ ╚══╩══╝ ╘══╧══╛ ╙──╨──╜ } public bool HandleKeyEvent(ConsoleKey key) { var oldCursorPos = Cursor; bool fullRedraw = false; bool keyHandled = true; switch (key) { case ConsoleKey.UpArrow: Cursor = new Position(Cursor.X, Math.Max(Cursor.Y - 1, 0)); break; case ConsoleKey.DownArrow: Cursor = new Position(Cursor.X, Math.Min(Cursor.Y + 1, _game.Map.GetLength(1) - 1)); break; case ConsoleKey.LeftArrow: Cursor = new Position(Math.Max(Cursor.X - 1, 0), Cursor.Y); break; case ConsoleKey.RightArrow: Cursor = new Position(Math.Min(Cursor.X + 1, _game.Map.GetLength(0) - 1), Cursor.Y); break; case ConsoleKey.Spacebar: fullRedraw = true; _game.Reveal(Cursor.X, Cursor.Y); break; case ConsoleKey.F: fullRedraw = true; _game.ToggleMark(Cursor.X, Cursor.Y); break; default: keyHandled = false; break; } if (fullRedraw) { DrawMap(false); } else if (oldCursorPos != Cursor) { Console.SetCursorPosition(oldCursorPos.X + MapPositon.X, oldCursorPos.Y + MapPositon.Y); DrawChar(_game.Map[oldCursorPos.X, oldCursorPos.Y], false); Console.SetCursorPosition(Cursor.X + MapPositon.X, Cursor.Y + MapPositon.Y); DrawChar(_game.Map[Cursor.X, Cursor.Y], true); } return keyHandled; } } }