Advertisement
NikWillOrStuff

Console Minesweeper Source Code

Jul 16th, 2015
419
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 13.46 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6.  
  7. namespace Console_Minesweeper
  8. {
  9.     class Program
  10.     {
  11.         private static String syntaxError =
  12.             "Syntax error. Example inputs: \"click 3 5\", \"3 5\", \"mark 2 7\", \"m 2 7\"";
  13.  
  14.         static void Main(string[] args)
  15.         {
  16.             Console.WriteLine("Console Minesweeper Made By NikWillOrStuff July 2015\n");
  17.             //get board generation info from user
  18.             int width = 1;
  19.             int height = 1;
  20.             Tile[,] board = new Tile[width, height];
  21.             int bombs = 0;
  22.             bool hasClicked = false;
  23.             while (true)
  24.             {
  25.                 Console.WriteLine("Type board width, board height, then amount of bombs\n(seperated by a space)");
  26.  
  27.                 String[] setup = Console.ReadLine().Split(' ');
  28.  
  29.                 try
  30.                 {
  31.                     width = int.Parse(setup[0]);
  32.                     height = int.Parse(setup[1]);
  33.                     bombs = int.Parse(setup[2]);
  34.  
  35.                     if (width < 1 || height < 1 || bombs < 0)
  36.                     {
  37.                         throw new NumberTooSmallException();
  38.                     }
  39.  
  40.                     if (width * height > 16116) //tested to be the biggest working number
  41.                     {
  42.                         throw new NumberTooBigException();
  43.                     }
  44.  
  45.                     if (bombs > (width * height) - 1)
  46.                     {
  47.                         throw new BombsAmountInvalidException();
  48.                     }
  49.  
  50.                     board = new Tile[width, height];//temp board with no bombs, until we know where the user clicks.
  51.  
  52.                     break;
  53.                 }
  54.                 catch (System.IndexOutOfRangeException)
  55.                 {
  56.                     Console.Write("Error: Missing number.");
  57.                 }
  58.                 catch (System.FormatException)
  59.                 {
  60.                     Console.Write("Error: Couldn't understand a number.");
  61.                 }
  62.                 catch (NumberTooSmallException)
  63.                 {
  64.                     Console.Write("Error: A number is too small.");
  65.                 }
  66.                 catch (NumberTooBigException)
  67.                 {
  68.                     Console.Write("Error: Your board cannot be that large.");
  69.                 }
  70.                 catch (BombsAmountInvalidException)
  71.                 {
  72.                     Console.Write("Error: There's not enough space for {0} bombs.", bombs);
  73.                 }
  74.                 Console.WriteLine(" Try again.");
  75.             }
  76.  
  77.             Print.PrintBoard(board, PlayerState.Safe);
  78.  
  79.             //game loop!
  80.             while (true)
  81.             {
  82.                 String[] input = Console.ReadLine().Split(' ');
  83.                 if (input[0].ToLower().Equals("h") || input[0].ToLower().Equals("help"))
  84.                 {
  85.                     Console.WriteLine("Availible commands: click, c, mark, m, help, h.");
  86.                     continue;
  87.                 }
  88.                 int x = 0;
  89.                 int y = 0;
  90.                 bool inputsAreNumbers = false;
  91.                 try
  92.                 {
  93.                     if (int.TryParse(input[0], out x) && int.TryParse(input[1], out y))
  94.                     {
  95.                         inputsAreNumbers = true;
  96.                     }
  97.                     else
  98.                     {
  99.                         x = int.Parse(input[1]);
  100.                         y = int.Parse(input[2]);
  101.                     }
  102.  
  103.                     if (OoB.OutOfBounds(board, x, y))
  104.                     {
  105.                         Console.WriteLine("Coordinates do not exist.");
  106.                         continue;
  107.                     }
  108.                 }
  109.                 catch (Exception e)
  110.                 {
  111.                     if (e is System.IndexOutOfRangeException || e is System.FormatException)
  112.                     {
  113.                         Console.WriteLine(syntaxError);
  114.                         continue;
  115.                     }
  116.                     else
  117.                     {
  118.                         throw;
  119.                     }
  120.                 }
  121.  
  122.                 if (input[0].ToLower().Equals("c") || input[0].ToLower().Equals("click") || inputsAreNumbers)
  123.                 {
  124.                     //if this is the first time we click something on the board,
  125.                     //place random bombs on the board, avoiding placing them where we clicked.
  126.                     //(the board has no bombs on it until we click)
  127.                     if (!hasClicked)
  128.                     {
  129.                         BoardFunctions.GenerateBombs(board, bombs, x, y);
  130.                     }
  131.  
  132.                     PlayerState result = BoardFunctions.Click(board, x, y);
  133.  
  134.                     if (result == PlayerState.Safe)
  135.                     {
  136.                         hasClicked = true;
  137.                         Print.PrintBoard(board, PlayerState.Safe);
  138.                     }
  139.                     else if (result == PlayerState.Dead)
  140.                     {
  141.                         Print.PrintBoard(board, PlayerState.Dead);
  142.                         Console.WriteLine("You clicked a bomb!\nPress enter to close.");
  143.                         Console.ReadLine();
  144.                         return;
  145.                     }
  146.                     else if (result == PlayerState.Winner)
  147.                     {
  148.                         Print.PrintBoard(board, PlayerState.Winner);
  149.                         Console.WriteLine("YOU'RE WINNER!\nPress enter to close.");
  150.                         Console.ReadLine();
  151.                         return;
  152.                     }
  153.                 }
  154.                 else if (input[0].ToLower().Equals("m") || input[0].ToLower().Equals("mark"))
  155.                 {
  156.                     BoardFunctions.Mark(board, x, y);
  157.                     Print.PrintBoard(board, PlayerState.Safe);
  158.                 }
  159.                 else
  160.                 {
  161.                     Console.WriteLine(syntaxError);
  162.                 }
  163.             }
  164.         }
  165.     }
  166.     class BoardFunctions
  167.     {
  168.         //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
  169.  
  170.         public static PlayerState Click(Tile[,] board, int x, int y)
  171.         {
  172.             switch (board[x, y].state)
  173.             {
  174.                 case TileState.Unclicked:
  175.                     if (board[x, y].bomb)
  176.                     {
  177.                         board[x, y].state = TileState.Clicked;
  178.                         return PlayerState.Dead;
  179.                     }
  180.                     Fill(board, x, y);
  181.                     break;
  182.                 case TileState.Clicked:
  183.                     if (board[x, y].bombsAround != 0)
  184.                     {
  185.                         //check how many marked tiles are around board[x, y]
  186.                         int marksAround = 0;
  187.                         for (int xOffset = -1; xOffset <= 1; xOffset++)
  188.                         {
  189.                             for (int yOffset = -1; yOffset <= 1; yOffset++)
  190.                             {
  191.                                 if (OoB.OutOfBounds(board, x + xOffset, y + yOffset))
  192.                                     continue;
  193.  
  194.                                 if (board[x + xOffset, y + yOffset].state == TileState.Marked)
  195.                                     marksAround++;
  196.                             }
  197.                         }
  198.  
  199.                         if (board[x, y].bombsAround == marksAround)
  200.                         {
  201.                             //clicks all tiles around the tile we clicked (board[x, y])
  202.                             for (int xOffset = -1; xOffset <= 1; xOffset++)
  203.                             {
  204.                                 for (int yOffset = -1; yOffset <= 1; yOffset++)
  205.                                 {
  206.                                     if (OoB.OutOfBounds(board, x + xOffset, y + yOffset) || board[x + xOffset, y + yOffset].state != TileState.Unclicked)
  207.                                         continue;
  208.  
  209.                                     Fill(board, x + xOffset, y + yOffset);
  210.                                 }
  211.                             }
  212.                         }
  213.                     }
  214.                     break;
  215.                 case TileState.Marked:
  216.                 case TileState.Questioned:
  217.                     return PlayerState.Safe;
  218.             }
  219.             //check if the player won
  220.             int width = board.GetLength(0);
  221.             int height = board.GetLength(1);
  222.             for (int xLoop = 0; xLoop < width; xLoop++)
  223.             {
  224.                 for (int yLoop = 0; yLoop < height; yLoop++)
  225.                 {
  226.                     if (board[xLoop, yLoop].state != TileState.Clicked && !board[xLoop, yLoop].bomb)
  227.                     {
  228.                         //everything needs to be clicked, except for bombs
  229.                         //if  (
  230.                         return PlayerState.Safe;
  231.                     }
  232.                 }
  233.             }
  234.             return PlayerState.Winner;
  235.         }
  236.  
  237.         public static void Mark(Tile[,] board, int x, int y)
  238.         {
  239.             switch (board[x, y].state)
  240.             {
  241.                 case TileState.Unclicked:
  242.                     board[x, y].state = TileState.Marked;
  243.                     break;
  244.                 case TileState.Marked:
  245.                     board[x, y].state = TileState.Questioned;
  246.                     break;
  247.                 case TileState.Questioned:
  248.                     board[x, y].state = TileState.Unclicked;
  249.                     break;
  250.             }
  251.         }
  252.  
  253.         public static void Fill(Tile[,] board, int x, int y)
  254.         {
  255.             if (board[x, y].state != TileState.Unclicked)
  256.                 return;
  257.  
  258.             board[x, y].state = TileState.Clicked;
  259.  
  260.             if (board[x, y].bombsAround != 0)
  261.                 return;
  262.  
  263.             //double for loop that runs the Fill() function (this function we're in) for all 8 tiles around the current tile (x, y)
  264.             for (int xOffset = -1; xOffset <= 1; xOffset++)
  265.             {
  266.                 for (int yOffset = -1; yOffset <= 1; yOffset++)
  267.                 {
  268.                     if (OoB.OutOfBounds(board, x + xOffset, y + yOffset) || xOffset == 0 && yOffset == 0)
  269.                         continue;
  270.  
  271.                     Fill(board, x + xOffset, y + yOffset);
  272.                 }
  273.             }
  274.         }
  275.         public static void GenerateBombs(Tile[,] board, int bombs, int x, int y)
  276.         {
  277.             int width = board.GetLength(0);
  278.             int height = board.GetLength(1);
  279.             Random rand = new Random();
  280.  
  281.             //this means that there isn't enough space on the board to have a blank tile.
  282.             int placed = 0;
  283.             if (bombs > (width * height) - 9)
  284.             {
  285.                 while (placed < bombs)
  286.                 {
  287.                     int randX = rand.Next(width);
  288.                     int randY = rand.Next(height);
  289.                     if (!board[randX, randY].bomb &&
  290.                         !(randX == x && randY == y))
  291.                     {
  292.                         board[randX, randY].bomb = true;
  293.                         placed++;
  294.                     }
  295.                 }
  296.             }
  297.             else
  298.             {
  299.                 while (placed < bombs)
  300.                 {
  301.                     int randX = rand.Next(width);
  302.                     int randY = rand.Next(height);
  303.                     //human readable translatoin:
  304.                     //if (!(random coords are inside a 3x3 square around clicked coords))
  305.                     if (!board[randX, randY].bomb &&
  306.                         !((randX >= x - 1 && randX <= x + 1) && (randY >= y - 1 && randY <= y + 1)))
  307.                     {
  308.                         board[randX, randY].bomb = true;
  309.                         placed++;
  310.                     }
  311.                 }
  312.             }
  313.  
  314.             FixBoard(board);
  315.  
  316.             return;
  317.         }
  318.         public static void FixBoard(Tile[,] board)
  319.         {
  320.             int width = board.GetLength(0);
  321.             int height = board.GetLength(1);
  322.             //this sets up the numbers on the board that tell the user where bombs are
  323.             for (int xx = 0; xx < width; xx++)
  324.             {
  325.                 for (int yy = 0; yy < height; yy++)
  326.                 {
  327.                     if (board[xx, yy].bomb)
  328.                         continue;
  329.                     //this counts the bombs around board[xx, yy]
  330.                     int bombsTemp = 0;
  331.                     for (int xxOffset = -1; xxOffset <= 1; xxOffset++)
  332.                     {
  333.                         for (int yyOffset = -1; yyOffset <= 1; yyOffset++)
  334.                         {
  335.                             if (OoB.OutOfBounds(board, xx + xxOffset, yy + yyOffset))
  336.                                 continue;
  337.                             if (board[xx + xxOffset, yy + yyOffset].bomb)
  338.                             {
  339.                                 bombsTemp++;
  340.                             }
  341.                         }
  342.                     }
  343.                     board[xx, yy].bombsAround = bombsTemp;
  344.                 }
  345.             }
  346.         }
  347.     }
  348.     class Print
  349.     {
  350.         // 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)
  351.         public static ConsoleColor[] colors = {
  352.             ConsoleColor.Black,     //0
  353.             ConsoleColor.Blue,      //1
  354.             ConsoleColor.DarkGreen, //2
  355.             ConsoleColor.Red,       //3
  356.             ConsoleColor.DarkBlue,  //4
  357.             ConsoleColor.DarkRed,   //5
  358.             ConsoleColor.DarkCyan,  //6
  359.             ConsoleColor.Black,     //7
  360.             ConsoleColor.DarkGray,};//8
  361.  
  362.         //this function prints the minesweeper board to the console.
  363.         public static void PrintBoard(Tile[,] board, PlayerState playerState)
  364.         {
  365.             int width = board.GetLength(0);
  366.             int height = board.GetLength(1);
  367.             int widthDigits = (board.GetLength(0) - 1).ToString().Length;
  368.             int heightDigits = (board.GetLength(1) - 1).ToString().Length;
  369.  
  370.             //spacer
  371.             Console.WriteLine();
  372.  
  373.             for (int y = -widthDigits; y < height; y++)
  374.             {
  375.                 for (int x = -heightDigits; x < width; x++)
  376.                 {
  377.                     if (x < 0 && y < 0)
  378.                     {
  379.                         Console.Write(" ");
  380.                     }
  381.                     //if we're on the area to the left of the board, print what height we're on
  382.                     else if (x < 0)
  383.                     {
  384.                         if (x == -1 || y.ToString("D" + heightDigits)[heightDigits - 1] == '0')
  385.                         {
  386.                             Console.Write(y.ToString("D" + heightDigits)[x + heightDigits]);
  387.                         }
  388.                         else
  389.                         {
  390.                             Console.Write(' ');
  391.                         }
  392.                     }
  393.                     //mirror of the previous else if
  394.                     else if (y < 0)
  395.                     {
  396.                         if (y == -1 || x.ToString("D" + widthDigits)[widthDigits - 1] == '0')
  397.                         {
  398.                             Console.Write(x.ToString("D" + widthDigits)[y + widthDigits]);
  399.                         }
  400.                         else
  401.                         {
  402.                             Console.Write(' ');
  403.                         }
  404.                     }
  405.                     //print the board!
  406.                     else if (y >= 0 && x >= 0)
  407.                     {
  408.                         Console.BackgroundColor = ConsoleColor.Gray;
  409.  
  410.                         if (playerState == PlayerState.Dead || playerState == PlayerState.Winner)
  411.                         {
  412.                             if (board[x, y].state == TileState.Marked || board[x, y].state == TileState.Questioned)
  413.                             {
  414.                                 if (board[x, y].bomb)
  415.                                 {
  416.                                     Console.ForegroundColor = ConsoleColor.White;
  417.                                 }
  418.                                 else
  419.                                 {
  420.                                     Console.ForegroundColor = ConsoleColor.Red;
  421.                                 }
  422.                                 Console.Write("*");
  423.                                 continue;
  424.                             }
  425.                             else if (board[x, y].bomb)
  426.                             {
  427.                                 if (board[x, y].state == TileState.Clicked)
  428.                                 {
  429.                                     Console.ForegroundColor = ConsoleColor.Black;
  430.                                 }
  431.                                 else
  432.                                 {
  433.                                     Console.ForegroundColor = ConsoleColor.White;
  434.                                 }
  435.                                 Console.Write("X");
  436.                                 continue;
  437.                             }
  438.                         }
  439.                         //going through all different states of a tile
  440.                         switch (board[x, y].state)
  441.                         {
  442.                             case TileState.Unclicked:
  443.                                 Console.ForegroundColor = ConsoleColor.White;
  444.                                 Console.Write("_");
  445.                                 break;
  446.                             case TileState.Clicked:
  447.                                 if (board[x, y].bomb)
  448.                                 {
  449.                                     //this will never be excecuted, because if there's a clicked bomb on the board, the player is dead.
  450.                                     //and when the player is dead, bombs are printed in the above section.
  451.                                     Console.ForegroundColor = ConsoleColor.Black;
  452.                                     Console.Write("ERROR");
  453.                                 }
  454.                                 else if (board[x, y].bombsAround == 0)
  455.                                 {
  456.                                     Console.Write(" ");
  457.                                 }
  458.                                 else
  459.                                 {
  460.                                     Console.ForegroundColor = colors[board[x, y].bombsAround];
  461.                                     Console.Write(board[x, y].bombsAround);
  462.                                 }
  463.                                 break;
  464.                             case TileState.Marked:
  465.                                 Console.ForegroundColor = ConsoleColor.White;
  466.                                 Console.Write("*");
  467.                                 break;
  468.                             case TileState.Questioned:
  469.                                 Console.ForegroundColor = ConsoleColor.White;
  470.                                 Console.Write("?");
  471.                                 break;
  472.                         }
  473.                     }
  474.                 }
  475.                 //end of a line of text
  476.                 Console.ResetColor();
  477.                 Console.WriteLine();
  478.             }
  479.             //spacer
  480.             Console.WriteLine();
  481.         }
  482.     }
  483.     public enum PlayerState
  484.     {
  485.         Safe, Dead, Winner
  486.     }
  487.     public enum TileState
  488.     {
  489.         Unclicked, Clicked, Marked, Questioned
  490.     }
  491.  
  492.     struct Tile
  493.     {
  494.         public TileState state; //default state is Unclicked
  495.         public bool bomb;
  496.         public int bombsAround;
  497.     }
  498.  
  499.     class OoB
  500.     {
  501.         public static bool OutOfBounds(Tile[,] board, int x, int y)
  502.         {
  503.             return (x < 0 || x >= board.GetLength(0) ||
  504.                     y < 0 || y >= board.GetLength(1));
  505.         }
  506.     }
  507.  
  508.     class NumberTooSmallException : Exception
  509.     {
  510.     }
  511.     class NumberTooBigException : Exception
  512.     {
  513.     }
  514.     class BombsAmountInvalidException : Exception
  515.     {
  516.     }
  517. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement