using System;
using System.Collections.Generic;
namespace TicTacToe
{
public class Game
{
public enum SquareState { Empty, X, O }
private SquareState[,] board;
private GameMode gameMode;
private const int SIZE = 5;
public AIPlayer aiPlayer { get; private set; }
public Game()
{
board = new SquareState[SIZE, SIZE];
ResetBoard();
}
public void SetGameMode(GameMode gameMode)
{
this.gameMode = gameMode;
}
public void SetAIPlayer(AIPlayer aiPlayer)
{
this.aiPlayer = aiPlayer;
}
public void ResetBoard()
{
for (int i = 0; i < SIZE; i++)
{
for (int j = 0; j < SIZE; j++)
{
board[i, j] = SquareState.Empty;
}
}
}
public bool MakeMove(int x, int y, SquareState state)
{
if (board[x, y] == SquareState.Empty)
{
board[x, y] = state;
if (gameMode == GameMode.AI && state == SquareState.X) // if AI mode and player X just moved
{
MakeAIMove(); // make AI move immediately after player X
}
return true;
}
else
{
return false;
}
}
public bool MakeAIMove()
{
if (gameMode != GameMode.AI || aiPlayer == null)
{
return false;
}
var aiMove = aiPlayer.GetMove(this);
if (aiMove.Item1 == -1 && aiMove.Item2 == -1)
{
return false; // no available moves
}
board[aiMove.Item1, aiMove.Item2] = SquareState.O;
return true;
}
public SquareState GetState(int x, int y)
{
return board[x, y];
}
public bool IsBoardFull()
{
for (int i = 0; i < SIZE; i++)
{
for (int j = 0; j < SIZE; j++)
{
if (board[i, j] == SquareState.Empty)
{
return false;
}
}
}
return true;
}
public bool CheckForWinner()
{
// horizontal checks
for (int i = 0; i < SIZE; i++)
{
for (int j = 0; j < SIZE - 2; j++)
{
if (board[i, j] != SquareState.Empty && board[i, j] == board[i, j + 1] && board[i, j] == board[i, j + 2])
{
return true;
}
}
}
// vertical checks
for (int i = 0; i < SIZE - 2; i++)
{
for (int j = 0; j < SIZE; j++)
{
if (board[i, j] != SquareState.Empty && board[i, j] == board[i + 1, j] && board[i, j] == board[i + 2, j])
{
return true;
}
}
}
// diagonal checks
for (int i = 0; i < SIZE - 2; i++)
{
for (int j = 0; j < SIZE - 2; j++)
{
if (board[i, j] != SquareState.Empty && board[i, j] == board[i + 1, j + 1] && board[i, j] == board[i + 2, j + 2])
{
return true;
}
}
}
for (int i = 0; i < SIZE - 2; i++)
{
for (int j = 2; j < SIZE; j++)
{
if (board[i, j] != SquareState.Empty && board[i, j] == board[i + 1, j - 1] && board[i, j] == board[i + 2, j - 2])
{
return true;
}
}
}
return false;
}
public List<(int, int)> GetAvailableMoves()
{
List<(int, int)> availableMoves = new List<(int, int)>();
for (int i = 0; i < SIZE; i++)
{
for (int j = 0; j < SIZE; j++)
{
if (board[i, j] == SquareState.Empty)
{
availableMoves.Add((i, j));
}
}
}
return availableMoves;
}
public (int, int) GetBestMove()
{
var availableMoves = GetAvailableMoves();
if (availableMoves.Count == 0)
{
return (-1, -1); // no available moves
}
// Check if there's a winning move
foreach (var move in availableMoves)
{
board[move.Item1, move.Item2] = SquareState.O;
if (CheckForWinner())
{
board[move.Item1, move.Item2] = SquareState.Empty; // reset the move
return move;
}
board[move.Item1, move.Item2] = SquareState.Empty; // reset the move
}
// If no winning move, return a random move
var random = new Random();
return availableMoves[random.Next(availableMoves.Count)];
}
}
}