我正在努力为tictactoe制作一个极小极大的AI。我的目标是它应该足够大的董事会。但是,我很难绕过如何实现算法。我已经阅读了无数不同的算法描述,但我似乎还没有能够使它工作。我的结果是一个令人难以置信的愚蠢AI。这是我的代码。
编辑:我想知道的主要观点是我如何让AI值得胜利,而不是在赢得胜利。截至目前,它并不关心我将赢得下一回合。
namespace TicTacToe_AI
{
public class Move //A class for moves
{
public int x, y, value, MoveNumber;
void SetMove(int a, int b)
{
x = a;
y = b;
}
public Move(int a, int b)
{
SetMove(a, b);
}
public Move()
{ }
}
class AI //AIClass
{
//The minimax algorithm
public Move CalculateMoves(int[,] Board, int BoardSize, int Depth, Move BestMoveAI, Move BestMovePlayer, int OriginalDepth, int CurrentTurn)
{
Depth--; //Decrease the depth for each iteration
bool Alpha = false; //Alpha-beta pruning - needs improvement
bool Beta = false;
bool WinningMove = false;
if (CurrentTurn == 1) CurrentTurn = 2;
if (CurrentTurn == 2) CurrentTurn = 1;
List<Move> DifferentMoves = new List<Move>();
List<Move> PossibleMoves = new List<Move>();
for (int i = 0; i < BoardSize; i++) //Add all possible moves to a list
{
for (int j = 0; j < BoardSize; j++)
{
if (Board[i, j] == 0)
{
Move Possible = new Move(i, j);
PossibleMoves.Add(Possible);
}
}
}
if (CurrentTurn == 2 && Depth >= 0 && Depth < BestMoveAI.MoveNumber) Alpha = true; //Alpha-beta pruning
if (CurrentTurn == 1 && Depth >= 0 && Depth < BestMovePlayer.MoveNumber) Beta = true;
if(Alpha || Beta)
{
foreach (Move TryMove in PossibleMoves) //Try every possible move to see if they are a winning move
{
int[,] Trying = new int[BoardSize, BoardSize];
Trying = (int[,])Board.Clone();
Trying[TryMove.x, TryMove.y] = CurrentTurn;
TryMove.MoveNumber = OriginalDepth - Depth;
if (Form1.Win(Trying) == 2)
{
TryMove.value = -1;
DifferentMoves.Add(TryMove);
if (Depth + 1 == OriginalDepth)
{
if (TryMove.MoveNumber < BestMoveAI.MoveNumber) BestMoveAI = TryMove;
WinningMove = true;
break;
}
else
{
WinningMove = true;
if (TryMove.MoveNumber < BestMoveAI.MoveNumber) BestMoveAI = TryMove;
return TryMove;
}
}
else if (Form1.Win(Trying) == 1)
{
WinningMove = true;
TryMove.value = 1;
BestMovePlayer = TryMove;
DifferentMoves.Add(TryMove);
return TryMove;
}
}
if (!WinningMove) // If no winning move was found, try recursively searching for a winning move
{
if (Alpha || Beta)
{
foreach (Move TryMove2 in PossibleMoves)
{
int[,] TestMove = new int[BoardSize, BoardSize];
TestMove = (int[,])Board.Clone();
TestMove[TryMove2.x, TryMove2.y] = CurrentTurn;
TryMove2.value = CalculateMoves(TestMove, BoardSize, Depth, BestMoveAI, BestMovePlayer, OriginalDepth, CurrentTurn).value;
DifferentMoves.Add(TryMove2);
}
}
}
}
//Find the best possible move and return it
BestMoveAI.value = 0;
BestMoveAI.MoveNumber = OriginalDepth;
BestMovePlayer.value = 0;
BestMovePlayer.MoveNumber = OriginalDepth;
if (CurrentTurn == 2)
{
foreach (Move AllMoves in DifferentMoves)
{
if (AllMoves.value <= BestMoveAI.value && AllMoves.MoveNumber <= BestMoveAI.MoveNumber)
{
BestMoveAI = AllMoves;
}
}
return BestMoveAI;
}
else if(CurrentTurn == 1)
{
foreach (Move AllMoves in DifferentMoves)
{
if (AllMoves.value >= BestMovePlayer.value && AllMoves.MoveNumber <= BestMovePlayer.MoveNumber)
{
BestMovePlayer = AllMoves;
}
}
return BestMovePlayer;
}
Move BadMove = new Move();
BadMove.value = 0;
BadMove.MoveNumber = Depth;
return BadMove;
}
}
}