Оптимизация проверок поля
This commit is contained in:
parent
b2ee79a408
commit
ffa123e8c1
@ -6,7 +6,9 @@ public static class StateRouter
|
||||
private static GameManager gm => GameManager.instance;
|
||||
public static void RouteAfterTurn()
|
||||
{
|
||||
var checkResult = FieldChecker.Check(GameManager.instance.currentPlayer);
|
||||
//var checkResult = FieldChecker.Check(GameManager.instance.currentPlayer);
|
||||
CheckResult checkResult = null;
|
||||
|
||||
gm.lastResult = checkResult;//это неправильно. Нужно при проверке записывать в поле.
|
||||
TurnEndingResult turnResult = EndOfTurnHandler.Evaluate(checkResult, gm.gameMode, gm.currentPlayer);
|
||||
|
||||
|
||||
@ -83,14 +83,13 @@ public class Board : MonoBehaviour
|
||||
|
||||
public Team[,] GridToTeam()
|
||||
{
|
||||
Team[,] res = new Team[Columns, Rows];
|
||||
for (int col = 0; col < Columns; col++)
|
||||
Team[,] res = new Team[Rows, Columns];
|
||||
for (int row = 0; row < Rows; row++)
|
||||
{
|
||||
for (int row = 0; row < Rows; row++)
|
||||
for (int col = 0; col < Columns; col++)
|
||||
{
|
||||
var chip = Grid[col, row];
|
||||
if (chip == null) res[col, row] = Team.None;
|
||||
else res[col, row] = chip.team;
|
||||
res[row, col] = chip == null ? Team.None : chip.team;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
|
||||
@ -32,13 +32,13 @@ public class Bot : BasePlayer, IGamePlayer
|
||||
private float randomMoveTimer;
|
||||
private float randomMoveInterval = 0.3f;
|
||||
|
||||
public event System.Action OnChipDropped;
|
||||
private int droppedRow, droppedColumn;
|
||||
|
||||
public event System.Action<int, int> OnChipDropped;
|
||||
|
||||
private int SelectedColumn => availableColumns[selectedColumnIndex];
|
||||
public bool ControlsEnabled { get; set; } = true;
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public void PrepareChip()
|
||||
{
|
||||
SetState(PlayerState.Preparing);
|
||||
@ -76,9 +76,6 @@ public class Bot : BasePlayer, IGamePlayer
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region State Updates
|
||||
|
||||
private void UpdatePreparing()
|
||||
{
|
||||
@ -124,15 +121,10 @@ public class Bot : BasePlayer, IGamePlayer
|
||||
if (currentChip.MoveToAccelerated(dropTargetPosition))
|
||||
{
|
||||
SetState(PlayerState.Sleep);
|
||||
OnChipDropped?.Invoke();
|
||||
Debug.Log("Chip dropped");
|
||||
OnChipDropped?.Invoke(droppedColumn, droppedRow);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Bot Logic
|
||||
|
||||
private void StartThinking()
|
||||
{
|
||||
SetState(PlayerState.Thinking);
|
||||
@ -210,6 +202,7 @@ public class Bot : BasePlayer, IGamePlayer
|
||||
|
||||
if (selectedColumnIndex == targetIndex)
|
||||
{
|
||||
|
||||
PerformDrop();
|
||||
return;
|
||||
}
|
||||
@ -222,14 +215,14 @@ public class Bot : BasePlayer, IGamePlayer
|
||||
private void PerformDrop()
|
||||
{
|
||||
dropTargetPosition = board.GetTargetPosition(SelectedColumn);
|
||||
|
||||
droppedColumn = SelectedColumn;
|
||||
droppedRow = board.GetLowestEmptyRow(SelectedColumn);
|
||||
|
||||
board.DropChip(currentChip, SelectedColumn);
|
||||
SetState(PlayerState.Dropping);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Random Movement
|
||||
|
||||
private void TryRandomMovement()
|
||||
{
|
||||
if (availableColumns == null || availableColumns.Length <= 1) return;
|
||||
@ -251,10 +244,6 @@ public class Bot : BasePlayer, IGamePlayer
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helpers
|
||||
|
||||
private void CacheAvailableColumns()
|
||||
{
|
||||
availableColumns = board.GetNonFullColumns();
|
||||
@ -281,10 +270,6 @@ public class Bot : BasePlayer, IGamePlayer
|
||||
stickedTargetPosition = new Vector2(newX, stickedTargetPosition.y);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Nested Types
|
||||
|
||||
private enum PlayerState
|
||||
{
|
||||
Sleep,
|
||||
@ -293,6 +278,4 @@ public class Bot : BasePlayer, IGamePlayer
|
||||
Moving,
|
||||
Dropping
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@ -2,10 +2,11 @@
|
||||
|
||||
public enum Team
|
||||
{
|
||||
None,
|
||||
None,
|
||||
Player1,
|
||||
Player2
|
||||
}
|
||||
|
||||
public static class FieldChecker
|
||||
{
|
||||
public static Chip[,] FieldArray => Board.Instance.Grid;
|
||||
@ -14,215 +15,170 @@ public static class FieldChecker
|
||||
public static int TargetLineLength = 4;
|
||||
public static CheckResult lastResult;
|
||||
|
||||
|
||||
public static CheckResult Check(Team lastPlayer)
|
||||
/// <summary>
|
||||
/// Проверяет, привела ли последняя фишка (установленная командой lastPlayer в клетку (row, col)) к победе.
|
||||
/// </summary>
|
||||
/// <param name="lastPlayer">Команда, которая только что сделала ход.</param>
|
||||
/// <param name="row">Строка (индекс по вертикали).</param>
|
||||
/// <param name="col">Столбец (индекс по горизонтали).</param>
|
||||
/// <returns>Результат проверки (окончание игры, ничья, множество победных клеток).</returns>
|
||||
public static CheckResult Check(Team lastPlayer, int row, int col)
|
||||
{
|
||||
HashSet<(int row, int col)> WinningIndexes = new();
|
||||
var winningCells = new HashSet<(int row, int col)>();
|
||||
|
||||
var rowsResult = checkAllRows(lastPlayer);
|
||||
var colsResult = checkAllColumns(lastPlayer);
|
||||
var diagonalsResult = checkAllDiagonals(lastPlayer);
|
||||
// Проверяем четыре направления, проходящие через (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 = rowsResult.hasWin ||
|
||||
colsResult.hasWin ||
|
||||
diagonalsResult.hasWin;
|
||||
bool hasWin = winningCells.Count > 0;
|
||||
|
||||
if (hasWin)
|
||||
{
|
||||
WinningIndexes.UnionWith(rowsResult.winningIndexes);
|
||||
WinningIndexes.UnionWith(colsResult.winningIndexes);
|
||||
WinningIndexes.UnionWith(diagonalsResult.winningIndexes);
|
||||
|
||||
lastResult = new CheckResult(end: true,
|
||||
isDraw: false,
|
||||
WinningIndexes);
|
||||
lastResult = new CheckResult(end: true, isDraw: false, winningCells);
|
||||
return lastResult;
|
||||
}
|
||||
else if (checkDraw())
|
||||
|
||||
if (CheckDraw())
|
||||
{
|
||||
lastResult = new CheckResult(end: true,
|
||||
isDraw: true,
|
||||
WinningIndexes);
|
||||
return lastResult;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastResult = new CheckResult(end: false,
|
||||
isDraw: false,
|
||||
WinningIndexes);
|
||||
lastResult = new CheckResult(end: true, isDraw: true, winningCells);
|
||||
return lastResult;
|
||||
}
|
||||
|
||||
lastResult = new CheckResult(end: false, isDraw: false, winningCells);
|
||||
return lastResult;
|
||||
}
|
||||
private static (bool hasWin, HashSet<(int row, int col)> winningIndexes) checkAllRows(Team targetTeam)
|
||||
|
||||
/// <summary>
|
||||
/// Проверяет линию, заданную направлением (rowStep, colStep), проходящую через клетку (row, col).
|
||||
/// Если найдена непрерывная последовательность из фишек lastPlayer длиной >= TargetLineLength,
|
||||
/// все клетки этой последовательности добавляются в winningCells.
|
||||
/// </summary>
|
||||
private static void CheckLine(int row, int col, int rowStep, int colStep, Team team, HashSet<(int, int)> winningCells)
|
||||
{
|
||||
var winningCells = new HashSet<(int row, int col)>();
|
||||
|
||||
for (int row = 0; row < Height; row++)
|
||||
// Движение назад (против направления)
|
||||
int r = row, c = col;
|
||||
int backCount = 0;
|
||||
while (true)
|
||||
{
|
||||
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));
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
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++)
|
||||
// Движение вперёд (по направлению)
|
||||
r = row;
|
||||
c = col;
|
||||
int forwardCount = 0;
|
||||
while (true)
|
||||
{
|
||||
int start = -1;
|
||||
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;
|
||||
|
||||
for (int row = 0; row < Height; row++)
|
||||
int totalLength = backCount + 1 + forwardCount; // +1 за саму клетку
|
||||
if (totalLength >= TargetLineLength)
|
||||
{
|
||||
// Добавляем все клетки от (startR, startC) до (endR, endC) с шагом (rowStep, colStep)
|
||||
for (int i = 0; i < totalLength; i++)
|
||||
{
|
||||
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));
|
||||
int curR = startR + i * rowStep;
|
||||
int curC = startC + i * colStep;
|
||||
winningCells.Add((curR, curC));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static bool checkDraw()
|
||||
/// <summary>
|
||||
/// Проверяет, заполнено ли всё поле (ничья).
|
||||
/// </summary>
|
||||
public static bool CheckDraw()
|
||||
{
|
||||
for (int col = 0; col < Width; col++)
|
||||
{
|
||||
if (Board.Instance.GetLowestEmptyRow(col) != -1) return false;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,7 +24,9 @@ public class Player : BasePlayer, IGamePlayer
|
||||
private Vector2 stickedTargetPosition;
|
||||
private Vector2 dropTargetPosition;
|
||||
|
||||
public event Action OnChipDropped;
|
||||
private int droppedRow, droppedColumn;
|
||||
|
||||
public event Action<int,int> OnChipDropped;
|
||||
|
||||
private int SelectedColumn => availableColumns[selectedColumnIndex];
|
||||
|
||||
@ -121,8 +123,7 @@ public class Player : BasePlayer, IGamePlayer
|
||||
if (currentChip.MoveToAccelerated(dropTargetPosition))
|
||||
{
|
||||
SetState(PlayerState.Sleep);
|
||||
OnChipDropped?.Invoke();
|
||||
Debug.Log("Chip dropped");
|
||||
OnChipDropped?.Invoke(droppedColumn, droppedRow);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -151,6 +152,10 @@ public class Player : BasePlayer, IGamePlayer
|
||||
if (!IsActionPressed()) return;
|
||||
|
||||
dropTargetPosition = board.GetTargetPosition(SelectedColumn);
|
||||
|
||||
droppedColumn = SelectedColumn;
|
||||
droppedRow = board.GetLowestEmptyRow(SelectedColumn);
|
||||
|
||||
board.DropChip(currentChip, SelectedColumn);
|
||||
SetState(PlayerState.Dropping);
|
||||
}
|
||||
|
||||
@ -121,7 +121,7 @@ public class Solver
|
||||
board[row, col] = BotPiece;
|
||||
|
||||
// если сразу победа — отлично
|
||||
if (WinningMoveAt(board, row, col, BotPiece))
|
||||
if (FieldChecker.IsWinningMove(board, row, col, BotPiece))
|
||||
{
|
||||
board[row, col] = Team.None;
|
||||
result.Add((col, WIN_SCORE * depth));
|
||||
@ -146,14 +146,14 @@ public class Solver
|
||||
|
||||
// если этот ход уже выигрывает нам игру — не считаем его "ведущим к проигрышу",
|
||||
// соперник просто не получит ход
|
||||
if (WinningMoveAt(board, row, botCol, BotPiece))
|
||||
if (FieldChecker.IsWinningMove(board, row, botCol, BotPiece))
|
||||
{
|
||||
board[row, botCol] = Team.None;
|
||||
return false;
|
||||
}
|
||||
|
||||
// может ли оппонент выиграть в 1 ход?
|
||||
bool res = HasImmediateWin(board, HumanPiece);
|
||||
bool res = FieldChecker.HasImmediateWin(board, HumanPiece);
|
||||
|
||||
// откат
|
||||
board[row, botCol] = Team.None;
|
||||
@ -190,7 +190,7 @@ public class Solver
|
||||
Team[,] board, int depth, int alpha, int beta,
|
||||
bool maximizingPlayer, int lastRow, int lastCol, Team lastPlayer)
|
||||
{
|
||||
if (lastRow >= 0 && WinningMoveAt(board, lastRow, lastCol, lastPlayer))
|
||||
if (lastRow >= 0 && FieldChecker.IsWinningMove(board, lastRow, lastCol, lastPlayer))
|
||||
{
|
||||
int s = (lastPlayer == BotPiece ? +WIN_SCORE : -WIN_SCORE) * Math.Max(1, depth);
|
||||
return (-1, s);
|
||||
@ -265,7 +265,7 @@ public class Solver
|
||||
score -= CountPotentialLinesPlayable(board, opp, 2) * TWO_IN_ROW;
|
||||
|
||||
// 4) Немедленная угроза оппонента → сильный штраф (чтобы бот приоритизировал блок)
|
||||
if (HasImmediateWin(board, opp))
|
||||
if (FieldChecker.HasImmediateWin(board, opp))
|
||||
score -= BLOCK_OPPONENT_BONUS;
|
||||
|
||||
return score;
|
||||
@ -343,44 +343,6 @@ public class Solver
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static bool HasImmediateWin(Team[,] board, Team player)
|
||||
{
|
||||
var valid = GetValidLocations(board);
|
||||
foreach (int c in valid)
|
||||
{
|
||||
int r = GetNextOpenRow(board, c);
|
||||
if (r < 0) continue;
|
||||
board[r, c] = player;
|
||||
bool win = WinningMoveAt(board, r, c, player);
|
||||
board[r, c] = Team.None;
|
||||
if (win) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool WinningMoveAt(Team[,] b, int r, int c, Team p)
|
||||
{
|
||||
bool In(int rr, int cc) => rr >= 0 && rr < ROWS && cc >= 0 && cc < COLS;
|
||||
|
||||
int CountDir(int dr, int dc)
|
||||
{
|
||||
int rr = r + dr, cc = c + dc, cnt = 0;
|
||||
while (In(rr, cc) && b[rr, cc] == p) { cnt++; rr += dr; cc += dc; }
|
||||
return cnt;
|
||||
}
|
||||
|
||||
// — (горизонталь)
|
||||
if (1 + CountDir(0, -1) + CountDir(0, +1) >= 4) return true;
|
||||
// | (вертикаль)
|
||||
if (1 + CountDir(-1, 0) + CountDir(+1, 0) >= 4) return true;
|
||||
// \ (диагональ)
|
||||
if (1 + CountDir(-1, -1) + CountDir(+1, +1) >= 4) return true;
|
||||
// / (диагональ)
|
||||
if (1 + CountDir(-1, +1) + CountDir(+1, -1) >= 4) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// -------- Стохастика на корне --------
|
||||
/// <summary>
|
||||
/// При околонулевой температуре с великой вероятностью лучший по score
|
||||
|
||||
@ -41,12 +41,12 @@ public class TurnManager : MonoBehaviour
|
||||
currentPlayer = player;
|
||||
}
|
||||
|
||||
private void OnTurnCompleted()
|
||||
private void OnTurnCompleted(int column, int row)
|
||||
{
|
||||
// Отписываемся от события текущего игрока
|
||||
currentPlayer.OnChipDropped -= OnTurnCompleted;
|
||||
|
||||
if (CheckGameOver())
|
||||
if (CheckGameOver(column, row))
|
||||
{
|
||||
OnGameOver();
|
||||
return;
|
||||
@ -75,11 +75,11 @@ public class TurnManager : MonoBehaviour
|
||||
StartTurn(currentPlayer);
|
||||
}
|
||||
|
||||
private bool CheckGameOver()
|
||||
private bool CheckGameOver(int column, int row)
|
||||
{
|
||||
if(currentPlayer is BasePlayer player)
|
||||
{
|
||||
var checkResult = FieldChecker.Check(player.team);
|
||||
var checkResult = FieldChecker.Check(player.team, row, column);
|
||||
return checkResult.End;
|
||||
}
|
||||
else
|
||||
@ -93,6 +93,12 @@ public class TurnManager : MonoBehaviour
|
||||
isGameOver = true;
|
||||
currentPlayer.Sleep();
|
||||
ControlsPerformer.Instance.SetControlable(null);
|
||||
Debug.Log("Game Over!");
|
||||
|
||||
BasePlayer lastPlayer = (BasePlayer)currentPlayer;
|
||||
var result = FieldChecker.lastResult;
|
||||
|
||||
|
||||
|
||||
Debug.Log($"end: {result.End}; draw: {result.Draw}; lastPlayer: {lastPlayer.team}");
|
||||
}
|
||||
}
|
||||
@ -4,5 +4,5 @@ public interface IGamePlayer : IControlable
|
||||
{
|
||||
void PrepareChip();
|
||||
void Sleep();
|
||||
event Action OnChipDropped;
|
||||
event Action<int, int> OnChipDropped;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user