using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Windows.Forms;
public static class Params
static public int gameFieldX = 10;
static public int gameFieldY = 10;
static public int numberOfMines = 50;
static public Random rnd;
static public bool firstMoveIsSafe = false;
static public string failMessage = "BOOM! Wanna start a new game? (Y/N)";
private List<Mine> mines;
bool shouldRestartGameFirstMoveSafe;
private Point2D cursorPos;
this.cursorPos = new Point2D(1, 1);
this.numberOfReveals = 0;
this.fieldValues = new int[Params.gameFieldX, Params.gameFieldY];
this.fieldProcessed = new int[Params.gameFieldX, Params.gameFieldY];
this.field = new Field();
FillFieldProcessedArrWith0();
if(this.shouldRestartGameFirstMoveSafe)
Console.SetCursorPosition(this.cursorPos.x, this.cursorPos.y);
Console.SetCursorPosition(1, 1);
if(this.shouldRestartGameFirstMoveSafe)
this.shouldRestartGameFirstMoveSafe = false;
var userInput = Console.ReadKey(true).Key;
var newX = this.cursorPos.x;
var newY = this.cursorPos.y;
case ConsoleKey.LeftArrow:
if(newX - 2 > 0) newX -= 2;
case ConsoleKey.RightArrow:
if(newX + 2 < 2 * Params.gameFieldX + 1) newX += 2;
if(newY - 2 > 0) newY -= 2;
case ConsoleKey.DownArrow:
if(newY + 2 < 2 * Params.gameFieldY + 1) newY += 2;
case ConsoleKey.Spacebar:
gameResult = this.ClickAction(newX, newY);
this.cursorPos = new Point2D(newX, newY);
Console.SetCursorPosition(newX, newY);
if(!this.shouldRestartGameFirstMoveSafe)
Console.SetCursorPosition(0, 2 * Params.gameFieldY + 2);
Console.WriteLine(Params.failMessage);
var key = Console.ReadKey(true).Key;
if(key != ConsoleKey.Y) break;
private void FillFieldProcessedArrWith0()
Console.SetCursorPosition(0, Params.gameFieldY + 2);
for(int i = 0; i < Params.gameFieldX; i++)
for(int j = 0; j < Params.gameFieldY; j++)
this.fieldProcessed[j, i] = 0;
private void PrintMines()
Console.WriteLine("Mines");
for(int i = 0; i < Params.numberOfMines; i++)
Console.WriteLine("x: {0}, y:{1}", this.mines[i].location.x /2, this.mines[i].location.y /2);
private void PrintSolution()
Console.WriteLine("Solution");
for(int i = 0; i < Params.gameFieldX; i++)
for(int j = 0; j < Params.gameFieldY; j++)
Console.Write("{0}, ", this.fieldValues[i, j]);
private void CalculateFieldNumbers()
for(int i = 0; i < Params.gameFieldX; i++)
for(int j = 0; j < Params.gameFieldY; j++)
this.fieldValues[j, i] = GetNumberOfNearbyMines(2 * j + 1, 2 * i + 1);
private int GetNumberOfNearbyMines(int x, int y)
foreach(var mine in this.mines)
var location = mine.location;
for(int k = location.x -2; k <= location.x + 2; k += 2)
for(int l = location.y - 2; l <= location.y + 2; l += 2)
private bool ClickAction(int posX, int posY, bool isClickedAuto = false)
if(this.fieldProcessed[posX / 2, posY / 2] == 0)
this.fieldProcessed[posX / 2, posY / 2] = 1;
Console.SetCursorPosition(posX, posY);
if(this.fieldValues[posX / 2, posY / 2] == -1 && !isClickedAuto)
if(this.numberOfReveals == 1)
this.shouldRestartGameFirstMoveSafe = true;
var numMines = this.fieldValues[posX / 2, posY / 2];
for(int i = posX - 2; i <= posX + 2; i += 2)
for(int j = posY - 2; j <= posY + 2; j += 2)
i <= 2 * Params.gameFieldX &&
j <= 2 * Params.gameFieldY)
this.ClickAction(i, j, true);
private void MarkMineAction()
if(this.fieldProcessed[this.cursorPos.x / 2, this.cursorPos.y / 2] == 0)
this.fieldProcessed[this.cursorPos.x / 2, this.cursorPos.y / 2] = 1;
private void GenerateMines()
this.mines = new List<Mine>();
for(int i = 0; i < Params.numberOfMines; i++)
this.mines.Add(new Mine(this.mines));
var endYIndex = 2 * Params.gameFieldY + 1;
var endXIndex = 2 * Params.gameFieldX + 1;
for(int i = 0; i < endYIndex; i++)
Console.SetCursorPosition(0, i);
Console.WriteLine(GetStringRowLength('-'));
for(int j = 0; j < endXIndex; j += 2)
Console.SetCursorPosition(j, i);
private void ClearField()
for(int i = 0; i < 2 * Params.gameFieldY + 3; i++)
Console.SetCursorPosition(0, i);
Console.WriteLine(GetStringRowLength(' '));
private string GetStringRowLength(char ch)
var strBuilder = new StringBuilder();
for(int j = 0; j < 2 * Params.gameFieldX; j++)
return strBuilder.ToString();
public Point2D(int _x, int _y)
public bool Equals(Point2D other)
return ((other.x == this.x) && (other.y == this.y));
return new Point2D(this.x, this.y);
public Mine(List<Mine> existingMines)
this.location = GetNewMineLocation(existingMines);
private Point2D GetNewMineLocation(List<Mine> existingMines)
x = RandomNumberOdd(1, 2 * Params.gameFieldX);
y = RandomNumberOdd(1, 2 * Params.gameFieldY);
foreach(var mine in existingMines)
if(mine.location.x == x &&
return new Point2D(x, y);
private int RandomNumberOdd(int min, int max)
int ans = Params.rnd.Next(min, max);
if (ans % 2 == 1) return ans;
public static void Main(string[] args)