211 lines
5.8 KiB
C#
211 lines
5.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Text;
|
|
|
|
namespace CoopSweeper.GameTypes
|
|
{
|
|
class Game
|
|
{
|
|
private readonly Random _random = new Random();
|
|
private static int _checkID = 0;
|
|
|
|
public IField[,] Map { get; protected set; }
|
|
|
|
private bool IsBomb(int bombratePercent)
|
|
{
|
|
int r = _random.Next(0, 100);
|
|
return r < bombratePercent;
|
|
}
|
|
|
|
public void GenerateGame(int x, int y, int bombratePercent)
|
|
{
|
|
Map = new IField[x, y];
|
|
for (int i = 0; i < x; i++)
|
|
{
|
|
for (int j = 0; j < y; j++)
|
|
{
|
|
var field = new Field
|
|
{
|
|
ContainsBomb = IsBomb(bombratePercent)
|
|
};
|
|
Map[i, j] = field;
|
|
}
|
|
}
|
|
|
|
UpdateSorroundingBombs();
|
|
}
|
|
|
|
private void UpdateSorroundingBombs()
|
|
{
|
|
for (int i = 0; i < Map.GetLength(0); i++)
|
|
{
|
|
for (int j = 0; j < Map.GetLength(1); j++)
|
|
{
|
|
int bombCounter = 0;
|
|
foreach (var point in GetSorroundedFields(i, j))
|
|
{
|
|
if (Map[point.X, point.Y].ContainsBomb)
|
|
bombCounter++;
|
|
}
|
|
|
|
Map[i, j].SurroundingBombs = bombCounter;
|
|
}
|
|
}
|
|
}
|
|
|
|
private List<Point> GetSorroundedFields(int x, int y)
|
|
{
|
|
var points = new List<Point>();
|
|
points.Add(new Point(x - 1, y - 1));
|
|
points.Add(new Point(x, y - 1));
|
|
points.Add(new Point(x + 1, y - 1));
|
|
|
|
points.Add(new Point(x + 1, y));
|
|
points.Add(new Point(x - 1, y));
|
|
|
|
points.Add(new Point(x - 1, y + 1));
|
|
points.Add(new Point(x, y + 1));
|
|
points.Add(new Point(x + 1, y + 1));
|
|
|
|
points.RemoveAll(point =>
|
|
point.X < 0
|
|
|| point.Y < 0
|
|
|| point.X >= Map.GetLength(0)
|
|
|| point.Y >= Map.GetLength(1));
|
|
|
|
return points;
|
|
}
|
|
|
|
public void GenerateGame(int x, int y)
|
|
{
|
|
GenerateGame(x, y, 10);
|
|
}
|
|
|
|
private void CheckMap()
|
|
{
|
|
if (Map == null)
|
|
throw new ArgumentNullException("The Map isn't created yet!");
|
|
}
|
|
|
|
public delegate void GameFinishedHandler(bool isGameWon);
|
|
|
|
public event GameFinishedHandler GameFinished;
|
|
|
|
private bool CheckGameFinished()
|
|
{
|
|
for (int i = 0; i < Map.GetLength(0); i++)
|
|
{
|
|
for (int j = 0; j < Map.GetLength(1); j++)
|
|
{
|
|
var field = Map[i, j];
|
|
|
|
if (!field.ContainsBomb && field.State != FieldState.REVEALED)
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private void InternalReveal(int x, int y, bool revealSurroundings)
|
|
{
|
|
var field = Map[x, y];
|
|
if (field.CheckID == _checkID)
|
|
return;
|
|
|
|
field.CheckID = _checkID;
|
|
|
|
if (field.State != FieldState.REVEALED)
|
|
{
|
|
if (field.State == FieldState.FLAG)
|
|
return;
|
|
|
|
field.State = FieldState.REVEALED;
|
|
if (field.ContainsBomb)
|
|
FinishGame(false);
|
|
|
|
if (field.SurroundingBombs == 0)
|
|
foreach (var surField in GetSorroundedFields(x, y))
|
|
{
|
|
InternalReveal(surField.X, surField.Y, false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (revealSurroundings)
|
|
RevealSurroindings(x, y);
|
|
}
|
|
|
|
if (CheckGameFinished())
|
|
FinishGame(true);
|
|
}
|
|
|
|
private void RevealSurroindings(int x, int y)
|
|
{
|
|
int bombs = Map[x, y].SurroundingBombs;
|
|
int bombsFlagged = 0;
|
|
|
|
foreach (var point in GetSorroundedFields(x, y))
|
|
{
|
|
if (Map[point.X, point.Y].ContainsBomb && Map[point.X, point.Y].State == FieldState.FLAG)
|
|
bombsFlagged++;
|
|
}
|
|
|
|
if (bombsFlagged == bombs)
|
|
foreach (var point in GetSorroundedFields(x, y))
|
|
{
|
|
if (Map[point.X, point.Y].State != FieldState.FLAG)
|
|
InternalReveal(point.X, point.Y, false);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
private void RevealBombs()
|
|
{
|
|
|
|
for (int i = 0; i < Map.GetLength(0); i++)
|
|
{
|
|
for (int j = 0; j < Map.GetLength(1); j++)
|
|
{
|
|
if (Map[i, j].ContainsBomb)
|
|
Map[i, j].State = FieldState.REVEALED;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void FinishGame(bool isWon)
|
|
{
|
|
RevealBombs();
|
|
GameFinished?.Invoke(isWon);
|
|
}
|
|
|
|
public void Reveal(int x, int y)
|
|
{
|
|
CheckMap();
|
|
_checkID++;
|
|
InternalReveal(x, y, true);
|
|
}
|
|
|
|
public void ToggleMark(int x, int y)
|
|
{
|
|
CheckMap();
|
|
var field = Map[x, y];
|
|
|
|
switch (field.State)
|
|
{
|
|
case FieldState.NONE:
|
|
field.State = FieldState.FLAG;
|
|
return;
|
|
case FieldState.FLAG:
|
|
field.State = FieldState.QUESTIONMARK;
|
|
return;
|
|
case FieldState.QUESTIONMARK:
|
|
field.State = FieldState.NONE;
|
|
return;
|
|
}
|
|
}
|
|
|
|
}
|
|
} |