public void Take(Ply ply) { if (ply == null) { throw new ArgumentNullException("ply"); } if (IsEnded) { throw new InvalidOperationException("Position is closed"); } if (HasWinner) { throw new InvalidOperationException(string.Format("Position has winner, but isn't closed")); } if (board[ply.Row, ply.Column] != Stone.Empty) { throw new InvalidOperationException(string.Format("Cannot do ply, because target cell isn't empty: [{0},{1}]", ply.Row, ply.Column)); } board[ply.Row, ply.Column] = next; hashing.Modify(2 * (BoardSize * ply.Row + ply.Column) + (next == Stone.Black ? 0 : 1)); history.Add(ply); if (IsWinningMove(ply)) { winner = next; ChangeNext(); } else { ChangeNext(); UpdateScore(ply.Row, ply.Column); } for (int i = Math.Max(0, ply.Row - radius); i < Math.Min(BoardSize, ply.Row + radius + 1); i++) { for (int j = Math.Max(0, ply.Column - radius); j < Math.Min(BoardSize, ply.Column + radius + 1); j++) { if (GetStone(i, j) == 0 && relevantEmptyCells[i, j] == 0) { relevantEmptyCells[i, j] = history.Count; } } } relevantEmptyCells[ply.Row, ply.Column] *= -1; }
public IEnumerable <Stone> Enumerate(Ply from, Direction direction) { switch (direction) { case Direction.Up: for (int i = from.Row - 1; i >= 0; i--) { yield return(board[i, from.Column]); } yield break; case Direction.Down: for (int i = from.Row + 1; i < BoardSize; i++) { yield return(board[i, from.Column]); } yield break; case Direction.Left: for (int i = from.Column - 1; i >= 0; i--) { yield return(board[from.Row, i]); } yield break; case Direction.Right: for (int i = from.Column + 1; i < BoardSize; i++) { yield return(board[from.Row, i]); } yield break; case Direction.UpLeft: for (int i = 1; i <= Math.Min(from.Row, from.Column); i++) { yield return(board[from.Row - i, from.Column - i]); } yield break; case Direction.DownRight: for (int i = 1; i < Math.Min(BoardSize - from.Row, BoardSize - from.Column); i++) { yield return(board[from.Row + i, from.Column + i]); } yield break; case Direction.DownLeft: for (int i = 1; i < Math.Min(BoardSize - from.Row, from.Column + 1); i++) { yield return(board[from.Row + i, from.Column - i]); } yield break; case Direction.UpRight: for (int i = 1; i < Math.Min(from.Row + 1, BoardSize - from.Column); i++) { yield return(board[from.Row - i, from.Column + i]); } yield break; default: throw new InvalidOperationException(string.Format("Unknown direction: {0}!", direction)); } }
private bool IsWinningMove(Ply cell) { var cellValue = board[cell.Row, cell.Column]; int verticalCount = 1; foreach (var value in Enumerate(cell, Direction.Up)) { if (value != cellValue) { break; } verticalCount++; } foreach (var value in Enumerate(cell, Direction.Down)) { if (value != cellValue) { break; } verticalCount++; } if (verticalCount >= 5) { return(true); } int horizontalCount = 1; foreach (var value in Enumerate(cell, Direction.Left)) { if (value != cellValue) { break; } horizontalCount++; } foreach (var value in Enumerate(cell, Direction.Right)) { if (value != cellValue) { break; } horizontalCount++; } if (horizontalCount >= 5) { return(true); } int diagonalCount = 1; foreach (var value in Enumerate(cell, Direction.UpLeft)) { if (value != cellValue) { break; } diagonalCount++; } foreach (var value in Enumerate(cell, Direction.DownRight)) { if (value != cellValue) { break; } diagonalCount++; } if (diagonalCount >= 5) { return(true); } int reverseDiagonalCount = 1; foreach (var value in Enumerate(cell, Direction.DownLeft)) { if (value != cellValue) { break; } reverseDiagonalCount++; } foreach (var value in Enumerate(cell, Direction.UpRight)) { if (value != cellValue) { break; } reverseDiagonalCount++; } if (reverseDiagonalCount >= 5) { return(true); } return(false); }