예제 #1
0
        public List <List <Glyph> > Render(bool showMines = false)
        {
            var boardLines = new List <List <Glyph> >();

            //construct the top and bottom legends and borders
            var yLegendPad          = Height > 9 ? "   " : "  "; //when the height reaches double digits more padding is needed
            var xLegendLine         = Utils.StringToLine(yLegendPad + "  ");
            var xLegendBorderCenter = new List <Glyph>();
            var xLegendBorderTop    = Utils.StringToLine(yLegendPad + "┌──┐", ConsoleColor.Blue);
            var xLegendBorderBottom = Utils.StringToLine(yLegendPad + "└──┘", ConsoleColor.Blue);

            for (int i = 0; i < Width; i++)
            {
                //generate horizontal A/B/C etc legend markers and border, changing colour if player is on this column
                xLegendLine.AddRange(Utils.StringToLine(Utils.GetXLegendValue(i) + " ", _Player.PositionX == i ? ConsoleColor.Red : ConsoleColor.White));
                xLegendBorderCenter.AddRange(Utils.StringToLine("──", ConsoleColor.Blue));
            }

            //2 gets us into the ┌──┐ space
            xLegendBorderTop.InsertRange(yLegendPad.Length + 2, xLegendBorderCenter);
            xLegendBorderBottom.InsertRange(yLegendPad.Length + 2, xLegendBorderCenter);

            //add the top legend lines
            boardLines.Add(xLegendLine);
            boardLines.Add(xLegendBorderTop);

            //generate mine field lines remembering that we loop the rows first since we're printing glyphs left to right one line at a time
            for (int y = Height - 1; y >= 0; y--)
            {
                int    lineNum   = y + 1;
                string legendPad = Height > 9 && lineNum <= 9 ? " " : ""; //correct padding depending on if this is a double digit row

                //create a new line starting with the the legend, switching colours if the player is on this row
                var line = new List <Glyph>()
                {
                    new Glyph(legendPad + lineNum.ToString(), _Player.PositionY == y ? ConsoleColor.Red : ConsoleColor.White),
                    new Glyph(' '),
                    new Glyph('│', ConsoleColor.Blue),
                    new Glyph(' '),
                };

                //loop the columns
                for (int x = 0; x < Width; x++)
                {
                    //display the player icon or mine field square as necessary
                    if (_Player.PositionX == x && _Player.PositionY == y)
                    {
                        line.Add(new Glyph(_Output.EmojiSupport ? "⛵️" : "|>"));
                    }
                    else
                    {
                        //show a mine location only if required (e.g. game is over)
                        var square = GetSquare(x, y);
                        if (square == Enums.SquareStatus.Mine && !showMines)
                        {
                            square = Enums.SquareStatus.Safe;
                        }

                        line.Add(new Glyph(_Output.ConvertGameSquareToGlyphValue(square)));
                    }
                }

                //finish the line with the legend
                line.Add(new Glyph(' '));
                line.Add(new Glyph('│', ConsoleColor.Blue));
                line.Add(new Glyph(' '));
                line.Add(new Glyph(lineNum.ToString(), _Player.PositionY == y ? ConsoleColor.Red : ConsoleColor.White));

                boardLines.Add(line);
            }

            //add the bottom legend to the board
            boardLines.Add(xLegendBorderBottom);
            boardLines.Add(xLegendLine);

            return(boardLines);
        }
예제 #2
0
        public void RenderToOutput()
        {
            var gameLines = new List <List <Glyph> >();

            var gameTitle = $"{_Output.ConvertGameSquareToGlyphValue(Enums.SquareStatus.Mine)} Welcome to {_GameTitle} {_Output.ConvertGameSquareToGlyphValue(Enums.SquareStatus.Mine)}";
            var padding   = (_Output.WindowWidth - gameTitle.Length) / 2;

            //insert the main heading
            gameLines.Insert(0, new List <Glyph>());
            gameLines.Insert(1, Utils.StringToLine(new StringBuilder().Append(' ', padding).Append(gameTitle).ToString(), ConsoleColor.Red));
            gameLines.Insert(2, Utils.StringToLine(new StringBuilder().Append(' ', padding - 1).Append('═', gameTitle.Length + 2).ToString(), ConsoleColor.Red));
            gameLines.Insert(3, new List <Glyph>());

            //generate the board
            var boardLines = _Board.Render(State == Enums.GameState.Loser || State == Enums.GameState.Winner);

            //generate the status/info lines to sit beside the board
            var info = new List <string>()
            {
                "Navigate from West to East using the arrow keys",
                "Watch out for the mines!",
                "",
                State == Enums.GameState.DifficultySelect ? "Select difficulty: [E]asy / [M]edium / [H]ard"
                    : State == Enums.GameState.StartPositionSelect ? "Enter start row number and press ENTER:"
                    : State == Enums.GameState.Loser || State == Enums.GameState.Winner ? "Press R to reset, ESC to quit"
                    : "",
                "",
                State == Enums.GameState.StartPositionSelect ? _DesiredStartPosition : "",
                State == Enums.GameState.Loser ? "GAME OVER"
                    : State == Enums.GameState.Winner ? $"CONGRATULATIONS, YOU MADE IT!"
                    : State == Enums.GameState.FreeMovement ? $"Position: {Utils.GetXLegendValue(_Player.PositionX)}{_Player.PositionY + 1}" : "",
                State != Enums.GameState.Loser && State != Enums.GameState.Winner ? $"Lives remaining: {LivesRemaining}" : "",
                State != Enums.GameState.DifficultySelect ? $"Moves made: {MoveCounter}" : ""
            };

            //board should be positioned to the right of the screen so the lhs has space for status and instructions
            var boardWidth = boardLines.First().Count;

            padding = (_Output.WindowWidth - boardWidth) - 10; //10 cols of safety margin

            //create the default padding used for board lines without any info/status text
            var defaultPadder = new StringBuilder().Append(' ', padding).ToString();
            var infoStartLine = (boardLines.Count - info.Count) / 2; //positions the info/status block roughly in the middle of the board height

            //merge our status/info lines with the board lines
            for (int i = 0; i < boardLines.Count - 1; i++)
            {
                var linePrepend = defaultPadder;

                //check we're in an appropriate place in the board lines array and build the status/info padded string
                if (i >= infoStartLine && i - infoStartLine < info.Count)
                {
                    linePrepend = BuildBoardLinePrependString(info[i - infoStartLine], padding);
                }

                //insert the status/info line into the list of chars for this board line
                boardLines[i].InsertRange(0, Utils.StringToLine(linePrepend));
            }

            //add the board into the overall output array
            gameLines.AddRange(boardLines);


            //clear the display and print out each line of the game
            _Output.Clear();

            foreach (var line in gameLines)
            {
                foreach (var chr in line)
                {
                    _Output.RenderSingle(chr);
                }

                _Output.Flush();
            }

            _Output.SetGameDefaultColors();
        }