Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- namespace Console_Minesweeper
- {
- class Program
- {
- private static String syntaxError =
- "Syntax error. Example inputs: \"click 3 5\", \"3 5\", \"mark 2 7\", \"m 2 7\"";
- static void Main(string[] args)
- {
- Console.WriteLine("Console Minesweeper Made By NikWillOrStuff July 2015\n");
- //get board generation info from user
- int width = 1;
- int height = 1;
- Tile[,] board = new Tile[width, height];
- int bombs = 0;
- bool hasClicked = false;
- while (true)
- {
- Console.WriteLine("Type board width, board height, then amount of bombs\n(seperated by a space)");
- String[] setup = Console.ReadLine().Split(' ');
- try
- {
- width = int.Parse(setup[0]);
- height = int.Parse(setup[1]);
- bombs = int.Parse(setup[2]);
- if (width < 1 || height < 1 || bombs < 0)
- {
- throw new NumberTooSmallException();
- }
- if (width * height > 16116) //tested to be the biggest working number
- {
- throw new NumberTooBigException();
- }
- if (bombs > (width * height) - 1)
- {
- throw new BombsAmountInvalidException();
- }
- board = new Tile[width, height];//temp board with no bombs, until we know where the user clicks.
- break;
- }
- catch (System.IndexOutOfRangeException)
- {
- Console.Write("Error: Missing number.");
- }
- catch (System.FormatException)
- {
- Console.Write("Error: Couldn't understand a number.");
- }
- catch (NumberTooSmallException)
- {
- Console.Write("Error: A number is too small.");
- }
- catch (NumberTooBigException)
- {
- Console.Write("Error: Your board cannot be that large.");
- }
- catch (BombsAmountInvalidException)
- {
- Console.Write("Error: There's not enough space for {0} bombs.", bombs);
- }
- Console.WriteLine(" Try again.");
- }
- Print.PrintBoard(board, PlayerState.Safe);
- //game loop!
- while (true)
- {
- String[] input = Console.ReadLine().Split(' ');
- if (input[0].ToLower().Equals("h") || input[0].ToLower().Equals("help"))
- {
- Console.WriteLine("Availible commands: click, c, mark, m, help, h.");
- continue;
- }
- int x = 0;
- int y = 0;
- bool inputsAreNumbers = false;
- try
- {
- if (int.TryParse(input[0], out x) && int.TryParse(input[1], out y))
- {
- inputsAreNumbers = true;
- }
- else
- {
- x = int.Parse(input[1]);
- y = int.Parse(input[2]);
- }
- if (OoB.OutOfBounds(board, x, y))
- {
- Console.WriteLine("Coordinates do not exist.");
- continue;
- }
- }
- catch (Exception e)
- {
- if (e is System.IndexOutOfRangeException || e is System.FormatException)
- {
- Console.WriteLine(syntaxError);
- continue;
- }
- else
- {
- throw;
- }
- }
- if (input[0].ToLower().Equals("c") || input[0].ToLower().Equals("click") || inputsAreNumbers)
- {
- //if this is the first time we click something on the board,
- //place random bombs on the board, avoiding placing them where we clicked.
- //(the board has no bombs on it until we click)
- if (!hasClicked)
- {
- BoardFunctions.GenerateBombs(board, bombs, x, y);
- }
- PlayerState result = BoardFunctions.Click(board, x, y);
- if (result == PlayerState.Safe)
- {
- hasClicked = true;
- Print.PrintBoard(board, PlayerState.Safe);
- }
- else if (result == PlayerState.Dead)
- {
- Print.PrintBoard(board, PlayerState.Dead);
- Console.WriteLine("You clicked a bomb!\nPress enter to close.");
- Console.ReadLine();
- return;
- }
- else if (result == PlayerState.Winner)
- {
- Print.PrintBoard(board, PlayerState.Winner);
- Console.WriteLine("YOU'RE WINNER!\nPress enter to close.");
- Console.ReadLine();
- return;
- }
- }
- else if (input[0].ToLower().Equals("m") || input[0].ToLower().Equals("mark"))
- {
- BoardFunctions.Mark(board, x, y);
- Print.PrintBoard(board, PlayerState.Safe);
- }
- else
- {
- Console.WriteLine(syntaxError);
- }
- }
- }
- }
- class BoardFunctions
- {
- //NOTE: all the functions in this class take advantage of the fact that Tile arrays are passed to these functions as a refference, not by value
- public static PlayerState Click(Tile[,] board, int x, int y)
- {
- switch (board[x, y].state)
- {
- case TileState.Unclicked:
- if (board[x, y].bomb)
- {
- board[x, y].state = TileState.Clicked;
- return PlayerState.Dead;
- }
- Fill(board, x, y);
- break;
- case TileState.Clicked:
- if (board[x, y].bombsAround != 0)
- {
- //check how many marked tiles are around board[x, y]
- int marksAround = 0;
- for (int xOffset = -1; xOffset <= 1; xOffset++)
- {
- for (int yOffset = -1; yOffset <= 1; yOffset++)
- {
- if (OoB.OutOfBounds(board, x + xOffset, y + yOffset))
- continue;
- if (board[x + xOffset, y + yOffset].state == TileState.Marked)
- marksAround++;
- }
- }
- if (board[x, y].bombsAround == marksAround)
- {
- //clicks all tiles around the tile we clicked (board[x, y])
- for (int xOffset = -1; xOffset <= 1; xOffset++)
- {
- for (int yOffset = -1; yOffset <= 1; yOffset++)
- {
- if (OoB.OutOfBounds(board, x + xOffset, y + yOffset) || board[x + xOffset, y + yOffset].state != TileState.Unclicked)
- continue;
- Fill(board, x + xOffset, y + yOffset);
- }
- }
- }
- }
- break;
- case TileState.Marked:
- case TileState.Questioned:
- return PlayerState.Safe;
- }
- //check if the player won
- int width = board.GetLength(0);
- int height = board.GetLength(1);
- for (int xLoop = 0; xLoop < width; xLoop++)
- {
- for (int yLoop = 0; yLoop < height; yLoop++)
- {
- if (board[xLoop, yLoop].state != TileState.Clicked && !board[xLoop, yLoop].bomb)
- {
- //everything needs to be clicked, except for bombs
- //if (
- return PlayerState.Safe;
- }
- }
- }
- return PlayerState.Winner;
- }
- public static void Mark(Tile[,] board, int x, int y)
- {
- switch (board[x, y].state)
- {
- case TileState.Unclicked:
- board[x, y].state = TileState.Marked;
- break;
- case TileState.Marked:
- board[x, y].state = TileState.Questioned;
- break;
- case TileState.Questioned:
- board[x, y].state = TileState.Unclicked;
- break;
- }
- }
- public static void Fill(Tile[,] board, int x, int y)
- {
- if (board[x, y].state != TileState.Unclicked)
- return;
- board[x, y].state = TileState.Clicked;
- if (board[x, y].bombsAround != 0)
- return;
- //double for loop that runs the Fill() function (this function we're in) for all 8 tiles around the current tile (x, y)
- for (int xOffset = -1; xOffset <= 1; xOffset++)
- {
- for (int yOffset = -1; yOffset <= 1; yOffset++)
- {
- if (OoB.OutOfBounds(board, x + xOffset, y + yOffset) || xOffset == 0 && yOffset == 0)
- continue;
- Fill(board, x + xOffset, y + yOffset);
- }
- }
- }
- public static void GenerateBombs(Tile[,] board, int bombs, int x, int y)
- {
- int width = board.GetLength(0);
- int height = board.GetLength(1);
- Random rand = new Random();
- //this means that there isn't enough space on the board to have a blank tile.
- int placed = 0;
- if (bombs > (width * height) - 9)
- {
- while (placed < bombs)
- {
- int randX = rand.Next(width);
- int randY = rand.Next(height);
- if (!board[randX, randY].bomb &&
- !(randX == x && randY == y))
- {
- board[randX, randY].bomb = true;
- placed++;
- }
- }
- }
- else
- {
- while (placed < bombs)
- {
- int randX = rand.Next(width);
- int randY = rand.Next(height);
- //human readable translatoin:
- //if (!(random coords are inside a 3x3 square around clicked coords))
- if (!board[randX, randY].bomb &&
- !((randX >= x - 1 && randX <= x + 1) && (randY >= y - 1 && randY <= y + 1)))
- {
- board[randX, randY].bomb = true;
- placed++;
- }
- }
- }
- FixBoard(board);
- return;
- }
- public static void FixBoard(Tile[,] board)
- {
- int width = board.GetLength(0);
- int height = board.GetLength(1);
- //this sets up the numbers on the board that tell the user where bombs are
- for (int xx = 0; xx < width; xx++)
- {
- for (int yy = 0; yy < height; yy++)
- {
- if (board[xx, yy].bomb)
- continue;
- //this counts the bombs around board[xx, yy]
- int bombsTemp = 0;
- for (int xxOffset = -1; xxOffset <= 1; xxOffset++)
- {
- for (int yyOffset = -1; yyOffset <= 1; yyOffset++)
- {
- if (OoB.OutOfBounds(board, xx + xxOffset, yy + yyOffset))
- continue;
- if (board[xx + xxOffset, yy + yyOffset].bomb)
- {
- bombsTemp++;
- }
- }
- }
- board[xx, yy].bombsAround = bombsTemp;
- }
- }
- }
- }
- class Print
- {
- // I want to print numbers with their own color, so here I set up a color array so that I can print "3" with color[3] (which is red)
- public static ConsoleColor[] colors = {
- ConsoleColor.Black, //0
- ConsoleColor.Blue, //1
- ConsoleColor.DarkGreen, //2
- ConsoleColor.Red, //3
- ConsoleColor.DarkBlue, //4
- ConsoleColor.DarkRed, //5
- ConsoleColor.DarkCyan, //6
- ConsoleColor.Black, //7
- ConsoleColor.DarkGray,};//8
- //this function prints the minesweeper board to the console.
- public static void PrintBoard(Tile[,] board, PlayerState playerState)
- {
- int width = board.GetLength(0);
- int height = board.GetLength(1);
- int widthDigits = (board.GetLength(0) - 1).ToString().Length;
- int heightDigits = (board.GetLength(1) - 1).ToString().Length;
- //spacer
- Console.WriteLine();
- for (int y = -widthDigits; y < height; y++)
- {
- for (int x = -heightDigits; x < width; x++)
- {
- if (x < 0 && y < 0)
- {
- Console.Write(" ");
- }
- //if we're on the area to the left of the board, print what height we're on
- else if (x < 0)
- {
- if (x == -1 || y.ToString("D" + heightDigits)[heightDigits - 1] == '0')
- {
- Console.Write(y.ToString("D" + heightDigits)[x + heightDigits]);
- }
- else
- {
- Console.Write(' ');
- }
- }
- //mirror of the previous else if
- else if (y < 0)
- {
- if (y == -1 || x.ToString("D" + widthDigits)[widthDigits - 1] == '0')
- {
- Console.Write(x.ToString("D" + widthDigits)[y + widthDigits]);
- }
- else
- {
- Console.Write(' ');
- }
- }
- //print the board!
- else if (y >= 0 && x >= 0)
- {
- Console.BackgroundColor = ConsoleColor.Gray;
- if (playerState == PlayerState.Dead || playerState == PlayerState.Winner)
- {
- if (board[x, y].state == TileState.Marked || board[x, y].state == TileState.Questioned)
- {
- if (board[x, y].bomb)
- {
- Console.ForegroundColor = ConsoleColor.White;
- }
- else
- {
- Console.ForegroundColor = ConsoleColor.Red;
- }
- Console.Write("*");
- continue;
- }
- else if (board[x, y].bomb)
- {
- if (board[x, y].state == TileState.Clicked)
- {
- Console.ForegroundColor = ConsoleColor.Black;
- }
- else
- {
- Console.ForegroundColor = ConsoleColor.White;
- }
- Console.Write("X");
- continue;
- }
- }
- //going through all different states of a tile
- switch (board[x, y].state)
- {
- case TileState.Unclicked:
- Console.ForegroundColor = ConsoleColor.White;
- Console.Write("_");
- break;
- case TileState.Clicked:
- if (board[x, y].bomb)
- {
- //this will never be excecuted, because if there's a clicked bomb on the board, the player is dead.
- //and when the player is dead, bombs are printed in the above section.
- Console.ForegroundColor = ConsoleColor.Black;
- Console.Write("ERROR");
- }
- else if (board[x, y].bombsAround == 0)
- {
- Console.Write(" ");
- }
- else
- {
- Console.ForegroundColor = colors[board[x, y].bombsAround];
- Console.Write(board[x, y].bombsAround);
- }
- break;
- case TileState.Marked:
- Console.ForegroundColor = ConsoleColor.White;
- Console.Write("*");
- break;
- case TileState.Questioned:
- Console.ForegroundColor = ConsoleColor.White;
- Console.Write("?");
- break;
- }
- }
- }
- //end of a line of text
- Console.ResetColor();
- Console.WriteLine();
- }
- //spacer
- Console.WriteLine();
- }
- }
- public enum PlayerState
- {
- Safe, Dead, Winner
- }
- public enum TileState
- {
- Unclicked, Clicked, Marked, Questioned
- }
- struct Tile
- {
- public TileState state; //default state is Unclicked
- public bool bomb;
- public int bombsAround;
- }
- class OoB
- {
- public static bool OutOfBounds(Tile[,] board, int x, int y)
- {
- return (x < 0 || x >= board.GetLength(0) ||
- y < 0 || y >= board.GetLength(1));
- }
- }
- class NumberTooSmallException : Exception
- {
- }
- class NumberTooBigException : Exception
- {
- }
- class BombsAmountInvalidException : Exception
- {
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement