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; /// /// Проверяет, привела ли последняя фишка (установленная командой lastPlayer в клетку (row, col)) к победе. /// /// Команда, которая только что сделала ход. /// Строка (индекс по вертикали). /// Столбец (индекс по горизонтали). /// Результат проверки (окончание игры, ничья, множество победных клеток). public static CheckResult Check(Team lastPlayer, int row, int col) { var winningCells = new HashSet<(int row, int col)>(); // Проверяем четыре направления, проходящие через (row, col) CheckLine(row, col, 0, 1, lastPlayer, winningCells); // горизонталь CheckLine(row, col, 1, 0, lastPlayer, winningCells); // вертикаль CheckLine(row, col, 1, 1, lastPlayer, winningCells); // главная диагональ CheckLine(row, col, 1, -1, lastPlayer, winningCells); // побочная диагональ bool hasWin = winningCells.Count > 0; if (hasWin) { lastResult = new CheckResult(end: true, isDraw: false, winningCells); return lastResult; } if (CheckDraw()) { lastResult = new CheckResult(end: true, isDraw: true, winningCells); return lastResult; } lastResult = new CheckResult(end: false, isDraw: false, winningCells); return lastResult; } /// /// Проверяет линию, заданную направлением (rowStep, colStep), проходящую через клетку (row, col). /// Если найдена непрерывная последовательность из фишек lastPlayer длиной >= TargetLineLength, /// все клетки этой последовательности добавляются в winningCells. /// private static void CheckLine(int row, int col, int rowStep, int colStep, Team team, HashSet<(int, int)> winningCells) { // Движение назад (против направления) int r = row, c = col; int backCount = 0; while (true) { int prevR = r - rowStep; int prevC = c - colStep; if (prevR < 0 || prevR >= Height || prevC < 0 || prevC >= Width) break; var chip = FieldArray[prevC, prevR]; // массив индексируется [x=col, y=row] if (chip == null || chip.team != team) break; backCount++; r = prevR; c = prevC; } int startR = r, startC = c; // Движение вперёд (по направлению) r = row; c = col; int forwardCount = 0; while (true) { int nextR = r + rowStep; int nextC = c + colStep; if (nextR < 0 || nextR >= Height || nextC < 0 || nextC >= Width) break; var chip = FieldArray[nextC, nextR]; if (chip == null || chip.team != team) break; forwardCount++; r = nextR; c = nextC; } int endR = r, endC = c; int totalLength = backCount + 1 + forwardCount; // +1 за саму клетку if (totalLength >= TargetLineLength) { // Добавляем все клетки от (startR, startC) до (endR, endC) с шагом (rowStep, colStep) for (int i = 0; i < totalLength; i++) { int curR = startR + i * rowStep; int curC = startC + i * colStep; winningCells.Add((curR, curC)); } } } /// /// Проверяет, заполнено ли всё поле (ничья). /// public static bool CheckDraw() { for (int col = 0; col < Width; col++) { if (Board.Instance.GetLowestEmptyRow(col) != -1) return false; } return true; } public static bool IsWinningMove(Team[,] board, int row, int col, Team player) { int height = board.GetLength(0); int width = board.GetLength(1); // Проверяем четыре направления return CheckLine(board, row, col, 0, 1, player, height, width) || CheckLine(board, row, col, 1, 0, player, height, width) || CheckLine(board, row, col, 1, 1, player, height, width) || CheckLine(board, row, col, 1, -1, player, height, width); } // Вспомогательный метод для проверки одной линии private static bool CheckLine(Team[,] board, int row, int col, int dr, int dc, Team player, int height, int width) { int count = 1; // вперёд int r = row + dr, c = col + dc; while (r >= 0 && r < height && c >= 0 && c < width && board[r, c] == player) { count++; r += dr; c += dc; } // назад r = row - dr; c = col - dc; while (r >= 0 && r < height && c >= 0 && c < width && board[r, c] == player) { count++; r -= dr; c -= dc; } return count >= 4; } // Метод для проверки, есть ли у оппонента немедленная победа в один ход public static bool HasImmediateWin(Team[,] board, Team player) { int height = board.GetLength(0); int width = board.GetLength(1); for (int col = 0; col < width; col++) { int row = GetLowestEmptyRow(board, col); if (row == -1) continue; board[row, col] = player; bool win = IsWinningMove(board, row, col, player); board[row, col] = Team.None; if (win) return true; } return false; } private static int GetLowestEmptyRow(Team[,] board, int col) { int height = board.GetLength(0); for (int r = height - 1; r >= 0; r--) if (board[r, col] == Team.None) return r; return -1; } }