|
@@ -3,6 +3,9 @@ using MinMaxAB;
|
|
|
|
|
|
namespace Connect4;
|
|
|
|
|
|
+/// <summary>
|
|
|
+/// Доска для игры в 4 в ряд
|
|
|
+/// </summary>
|
|
|
public class GameBoard
|
|
|
{
|
|
|
public Player[][] cells;
|
|
@@ -23,6 +26,12 @@ public class GameBoard
|
|
|
private bool cacheInvalidated = false;
|
|
|
private Player winnerCache = Player.None;
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Закинуть монетку сверху
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="player">Игрок, закинувший монетку</param>
|
|
|
+ /// <param name="column">Столбец, в который закинуть монетку</param>
|
|
|
+ /// <returns>Получилось ли поместить монетку</returns>
|
|
|
public bool PlaceCoin(Player player, int column)
|
|
|
{
|
|
|
int row = 0;
|
|
@@ -38,6 +47,11 @@ public class GameBoard
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Убрать верхнюю монетку
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="column">Столбец, из которого убрать монетку</param>
|
|
|
+ /// <returns>Удалось ли убрать монетку</returns>
|
|
|
public bool RemoveFromTop(int column)
|
|
|
{
|
|
|
int row = 0;
|
|
@@ -53,6 +67,10 @@ public class GameBoard
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Найти победители
|
|
|
+ /// </summary>
|
|
|
+ /// <returns>Игрок-победитель</returns>
|
|
|
public Player? GetWinner()
|
|
|
{
|
|
|
if (!cacheInvalidated) return winnerCache;
|
|
@@ -66,26 +84,32 @@ public class GameBoard
|
|
|
if (cells[i][j] == Player.None)
|
|
|
continue;
|
|
|
|
|
|
- bool h = i + 3 < dimensions.Columns;
|
|
|
- bool v = j + 3 < dimensions.Rows;
|
|
|
+ // Горизонталь
|
|
|
+ bool horizontal = i + 3 < dimensions.Columns;
|
|
|
|
|
|
- if (!h && !v)
|
|
|
+ // Вертикаль
|
|
|
+ bool vertical = j + 3 < dimensions.Rows;
|
|
|
+
|
|
|
+ if (!horizontal && !vertical)
|
|
|
continue;
|
|
|
|
|
|
- bool d = h && v;
|
|
|
- bool bd = v && i - 3 >= 0;
|
|
|
+ // Диагональ
|
|
|
+ bool diagonal = horizontal && vertical;
|
|
|
+ // Вторая диагональ
|
|
|
+ bool reverseDiagonal = vertical && i - 3 >= 0;
|
|
|
|
|
|
+ // Проходим по всем возможным длинам последовательности
|
|
|
for (int k = 1; k < 4; k++)
|
|
|
{
|
|
|
- h = h && cells[i][j] == cells[i + k][j];
|
|
|
- v = v && cells[i][j] == cells[i][j + k];
|
|
|
- d = d && cells[i][j] == cells[i + k][j + k];
|
|
|
- bd = bd && cells[i][j] == cells[i - k][j + k];
|
|
|
- if (!h && !v && !d && !bd)
|
|
|
+ horizontal = horizontal && cells[i][j] == cells[i + k][j];
|
|
|
+ vertical = vertical && cells[i][j] == cells[i][j + k];
|
|
|
+ diagonal = diagonal && cells[i][j] == cells[i + k][j + k];
|
|
|
+ reverseDiagonal = reverseDiagonal && cells[i][j] == cells[i - k][j + k];
|
|
|
+ if (!horizontal && !vertical && !diagonal && !reverseDiagonal)
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- if (h || v || d || bd)
|
|
|
+ if (horizontal || vertical || diagonal || reverseDiagonal)
|
|
|
{
|
|
|
winnerCache = cells[i][j];
|
|
|
return cells[i][j];
|
|
@@ -97,6 +121,10 @@ public class GameBoard
|
|
|
return Player.None;
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Проверить, есть ли пустые столбцы
|
|
|
+ /// </summary>
|
|
|
+ /// <returns>true если есть пустые столбцы</returns>
|
|
|
public bool HasEmptyColumns()
|
|
|
{
|
|
|
for (int x = 0; x < dimensions.Columns; x++)
|
|
@@ -107,6 +135,11 @@ public class GameBoard
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Найти символ, обозначающий игрока
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="player">Игрок</param>
|
|
|
+ /// <returns>Символ, обозначающий данного игрока</returns>
|
|
|
protected char PlayerChar(Player player) => player switch
|
|
|
{
|
|
|
Player.Human => 'O',
|
|
@@ -114,6 +147,10 @@ public class GameBoard
|
|
|
_ => ' ',
|
|
|
};
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Сериализовать доску
|
|
|
+ /// </summary>
|
|
|
+ /// <returns>Строка, содержащая отформатированное представление доски</returns>
|
|
|
public override string ToString()
|
|
|
{
|
|
|
string sep = $"\n{new('-', dimensions.Columns * 4)}";
|
|
@@ -139,6 +176,10 @@ public class GameBoard
|
|
|
return builder.ToString();
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Скопировать доску вместе с ее содержимым
|
|
|
+ /// </summary>
|
|
|
+ /// <returns>Копия доски с таким же содержимым</returns>
|
|
|
public GameBoard Clone()
|
|
|
{
|
|
|
var newBoard = new GameBoard(dimensions, cells.DeepCopy());
|