Files
minesweeper-coop/CoopSweeper/GameTypes/Game.cs
2018-05-25 11:38:24 +02:00

182 lines
4.9 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)
{
var field = Map[x, y];
if (field.CheckID == _checkID)
return;
field.CheckID = _checkID;
if (field.State != FieldState.REVEALED)
{
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);
}
}
if (CheckGameFinished())
FinishGame(true);
}
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);
}
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;
}
}
}
}