C# Tic-Tac-Toe Minimax

В настоящее время я пробую свои силы в создании минимаксного AI для tictactoe. Моя цель состояла в том, чтобы этого хватило и для больших досок. Тем не менее, мне довольно трудно обдумать, как реализовать алгоритм. Я прочитал бесчисленное множество различных описаний алгоритма, но я все еще не могу заставить его работать. Мой результат пока невероятно глупый ИИ. Вот мой код для этого.

Редактировать: Главное, что меня интересует, это то, как я заставляю ИИ ценить меня, а не побеждать, направляя себя к победе. На данный момент все равно, что я выиграю следующий ход.

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;




    }
}

}

0 ответов

Другие вопросы по тегам