228 lines
7.3 KiB
C#
228 lines
7.3 KiB
C#
using System.Collections.Generic;
|
|
|
|
public enum Team
|
|
{
|
|
None,
|
|
Player1,
|
|
Player2
|
|
}
|
|
public static class FieldChecker
|
|
{
|
|
public static Chip[,] FieldArray => Board.Instance.Grid;
|
|
public static int Height => Board.Instance.Rows;
|
|
public static int Width => Board.Instance.Columns;
|
|
public static int TargetLineLength = 4;
|
|
public static CheckResult lastResult;
|
|
|
|
|
|
public static CheckResult Check(Team lastPlayer)
|
|
{
|
|
HashSet<(int row, int col)> WinningIndexes = new();
|
|
|
|
var rowsResult = checkAllRows(lastPlayer);
|
|
var colsResult = checkAllColumns(lastPlayer);
|
|
var diagonalsResult = checkAllDiagonals(lastPlayer);
|
|
|
|
bool hasWin = rowsResult.hasWin ||
|
|
colsResult.hasWin ||
|
|
diagonalsResult.hasWin;
|
|
|
|
if (hasWin)
|
|
{
|
|
WinningIndexes.UnionWith(rowsResult.winningIndexes);
|
|
WinningIndexes.UnionWith(colsResult.winningIndexes);
|
|
WinningIndexes.UnionWith(diagonalsResult.winningIndexes);
|
|
|
|
lastResult = new CheckResult(end: true,
|
|
isDraw: false,
|
|
WinningIndexes);
|
|
return lastResult;
|
|
}
|
|
else if (checkDraw())
|
|
{
|
|
lastResult = new CheckResult(end: true,
|
|
isDraw: true,
|
|
WinningIndexes);
|
|
return lastResult;
|
|
}
|
|
else
|
|
{
|
|
lastResult = new CheckResult(end: false,
|
|
isDraw: false,
|
|
WinningIndexes);
|
|
return lastResult;
|
|
}
|
|
}
|
|
private static (bool hasWin, HashSet<(int row, int col)> winningIndexes) checkAllRows(Team targetTeam)
|
|
{
|
|
var winningCells = new HashSet<(int row, int col)>();
|
|
|
|
for (int row = 0; row < Height; row++)
|
|
{
|
|
int start = -1;
|
|
for (int col = 0; col < Width; col++)
|
|
{
|
|
var chip = FieldArray[col, row];
|
|
bool isMatch = chip != null && chip.team == targetTeam;
|
|
|
|
if (isMatch && start == -1)
|
|
start = col;
|
|
|
|
if (!isMatch && start != -1)
|
|
{
|
|
int length = col - start;
|
|
if (length >= TargetLineLength)
|
|
{
|
|
for (int c = start; c < col; c++)
|
|
winningCells.Add((row, c));
|
|
}
|
|
start = -1;
|
|
}
|
|
}
|
|
// Проверка последовательности в конце строки
|
|
if (start != -1)
|
|
{
|
|
int length = Width - start;
|
|
if (length >= TargetLineLength)
|
|
{
|
|
for (int c = start; c < Width; c++)
|
|
winningCells.Add((row, c));
|
|
}
|
|
}
|
|
}
|
|
|
|
return (winningCells.Count > 0, winningCells);
|
|
}
|
|
private static (bool hasWin, HashSet<(int row, int col)> winningIndexes) checkAllColumns(Team targetTeam)
|
|
{
|
|
var winningCells = new HashSet<(int row, int col)>();
|
|
|
|
for (int col = 0; col < Width; col++)
|
|
{
|
|
int start = -1;
|
|
|
|
for (int row = 0; row < Height; row++)
|
|
{
|
|
var chip = FieldArray[col, row];
|
|
bool isMatch = chip != null && chip.team == targetTeam;
|
|
|
|
if (isMatch && start == -1)
|
|
start = row;
|
|
|
|
if (!isMatch && start != -1)
|
|
{
|
|
int length = row - start;
|
|
if (length >= TargetLineLength)
|
|
{
|
|
for (int r = start; r < row; r++)
|
|
winningCells.Add((r, col));
|
|
}
|
|
start = -1;
|
|
}
|
|
}
|
|
|
|
// Проверка последовательности в конце столбца
|
|
if (start != -1)
|
|
{
|
|
int length = Height - start;
|
|
if (length >= TargetLineLength)
|
|
{
|
|
for (int r = start; r < Height; r++)
|
|
winningCells.Add((r, col));
|
|
}
|
|
}
|
|
}
|
|
|
|
return (winningCells.Count > 0, winningCells);
|
|
}
|
|
|
|
private static (bool hasWin, HashSet<(int row, int col)> winningIndexes) checkAllDiagonals(Team targetCellState)
|
|
{
|
|
var winningCells = new HashSet<(int row, int col)>();
|
|
|
|
// Проверка главных диагоналей
|
|
for (int row = 0; row < Height; row++)
|
|
{
|
|
CheckDiagonalStartingAt(row, 0, 1, 1, targetCellState, winningCells);
|
|
}
|
|
for (int col = 1; col < Width; col++)
|
|
{
|
|
CheckDiagonalStartingAt(0, col, 1, 1, targetCellState, winningCells);
|
|
}
|
|
|
|
// Проверка побочных диагоналей
|
|
for (int row = 0; row < Height; row++)
|
|
{
|
|
CheckDiagonalStartingAt(row, Width - 1, 1, -1, targetCellState, winningCells);
|
|
}
|
|
for (int col = Width - 2; col >= 0; col--)
|
|
{
|
|
CheckDiagonalStartingAt(0, col, 1, -1, targetCellState, winningCells);
|
|
}
|
|
|
|
return (winningCells.Count > 0, winningCells);
|
|
}
|
|
|
|
private static void CheckDiagonalStartingAt(int startRow, int startCol, int rowStep, int colStep,
|
|
Team targetCellState, HashSet<(int, int)> winningCells)
|
|
{
|
|
int rows = Height;
|
|
int cols = Width;
|
|
int currentRow = startRow;
|
|
int currentCol = startCol;
|
|
int sequenceLength = 0;
|
|
int sequenceStartRow = startRow;
|
|
int sequenceStartCol = startCol;
|
|
|
|
while (currentRow >= 0 && currentRow < rows &&
|
|
currentCol >= 0 && currentCol < cols)
|
|
{
|
|
var chip = FieldArray[currentCol, currentRow];
|
|
bool isMatch = chip != null && chip.team == targetCellState;
|
|
|
|
if (isMatch)
|
|
{
|
|
sequenceLength++;
|
|
}
|
|
else
|
|
{
|
|
if (sequenceLength >= TargetLineLength)
|
|
{
|
|
for (int i = 0; i < sequenceLength; i++)
|
|
{
|
|
int r = sequenceStartRow + i * rowStep;
|
|
int c = sequenceStartCol + i * colStep;
|
|
winningCells.Add((r, c));
|
|
}
|
|
}
|
|
sequenceLength = 0;
|
|
sequenceStartRow = currentRow + rowStep;
|
|
sequenceStartCol = currentCol + colStep;
|
|
}
|
|
|
|
currentRow += rowStep;
|
|
currentCol += colStep;
|
|
}
|
|
|
|
// Проверка последовательности в конце диагонали
|
|
if (sequenceLength >= TargetLineLength)
|
|
{
|
|
for (int i = 0; i < sequenceLength; i++)
|
|
{
|
|
int r = sequenceStartRow + i * rowStep;
|
|
int c = sequenceStartCol + i * colStep;
|
|
winningCells.Add((r, c));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
public static bool checkDraw()
|
|
{
|
|
for (int col = 0; col < Width; col++)
|
|
{
|
|
if (Board.Instance.GetLowestEmptyRow(col) != -1) return false;
|
|
}
|
|
return true;
|
|
}
|
|
} |