C# 极小极大

C# 极小极大,c#,unity3d,artificial-intelligence,tic-tac-toe,minimax,C#,Unity3d,Artificial Intelligence,Tic Tac Toe,Minimax,我正在尝试实现MiniMax来创建一个TicTacToe人工智能。我使用C和Unity。我跟着。本教程是用JavaScript编写的,但我还是用C编写的。我试着从他的网站上查看MiniMax代码,但我不明白为什么我的翻译不起作用: using System.Collections.Generic; using UnityEngine; public class GameManager : MonoBehaviour { public SpriteRenderer[] sprites;

我正在尝试实现MiniMax来创建一个TicTacToe人工智能。我使用C和Unity。我跟着。本教程是用JavaScript编写的,但我还是用C编写的。我试着从他的网站上查看MiniMax代码,但我不明白为什么我的翻译不起作用:

using System.Collections.Generic;
using UnityEngine;

public class GameManager : MonoBehaviour
{

    public SpriteRenderer[] sprites;

    char[] board = new char[] { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' };
    Dictionary<char, Color> boardColor = new Dictionary<char, Color>()
    {
        { ' ', Color.white },
        { 'O', Color.red },
        { 'X', Color.blue }
    };

    char ai = 'O';
    char player = 'X';

    Camera cam;
    bool gameOver = false;
    bool playerTurn;

    private void Awake()
    {
        playerTurn = Random.value > .5f;
        cam = Camera.main;
    }

    private void Start()
    {
        DrawBoard();
    }

    private void Update()
    {
        if (gameOver) return;

        if (playerTurn)
            PlayerMove();
        else
            CompMove();

        DrawBoard();

        if (IsWinner(player))
        {
            print("Good job, you won!");
            gameOver = true;
        }

        else if (IsWinner(ai))
        {
            print("Too bad, you lost!");
            gameOver = true;
        }

        else if (BoardIsFull())
        {
            print("Close one, it's a tie!");
            gameOver = true;
        }
    }

    void PlayerMove()
    {
        if (Input.GetMouseButtonDown(0))
        {
            RaycastHit2D hit = Physics2D.Raycast(cam.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);

            if (hit)
            {
                int pos = hit.transform.GetComponent<SpritePos>().pos;
                if (SpaceIsFree(pos))
                {
                    InsertLetter(player, pos);
                    playerTurn = false;
                }
            }
        }
    }

    void CompMove()
    {
        float bestScore = -Mathf.Infinity;
        int bestMove = 0;

        for (int i = 0; i < board.Length; i++)
            if(SpaceIsFree(i))
            {
                board[i] = ai;
                float score = Minimax(board, 0, false);
                board[i] = ' ';
                bestScore = Mathf.Max(score, bestScore);
                bestMove = i;
            }


        InsertLetter(ai, bestMove);
        playerTurn = true;
    }

    float Minimax(char[] board, int depth, bool isMaximizer)
    {
        if (IsWinner(ai))
            return 1;
        if (IsWinner(player))
            return -1;
        if (BoardIsFull())
            return 0;

        if (isMaximizer)
        {
            float bestScore = -Mathf.Infinity;
            for (int i = 0; i < board.Length; i++)
            {
                if (SpaceIsFree(i))
                {
                    board[i] = ai;
                    float score = Minimax(board, depth + 1, false);
                    board[i] = ' ';
                    bestScore = Mathf.Max(score, bestScore);
                }
            }
            return bestScore;
        }
        else
        {
            float bestScore = Mathf.Infinity;
            for (int i = 0; i < board.Length; i++)
            {
                if (SpaceIsFree(i))
                {
                    board[i] = player;
                    float score = Minimax(board, depth + 1, true);
                    board[i] = ' ';
                    bestScore = Mathf.Min(score, bestScore);
                }
            }
            return bestScore;
        }
    }

    void InsertLetter(char letter, int pos)
    {
        board[pos] = letter;
    }

    bool SpaceIsFree(int pos)
    {
        return board[pos] == ' ';
    }

    bool IsWinner(char letter)
    {
        return (board[0] == letter && board[1] == letter && board[2] == letter) ||
               (board[4] == letter && board[5] == letter && board[6] == letter) ||
               (board[0] == letter && board[1] == letter && board[2] == letter) ||
               (board[0] == letter && board[3] == letter && board[6] == letter) ||
               (board[1] == letter && board[4] == letter && board[7] == letter) ||
               (board[2] == letter && board[5] == letter && board[8] == letter) ||
               (board[0] == letter && board[4] == letter && board[8] == letter) ||
               (board[6] == letter && board[4] == letter && board[2] == letter);
    }

    void DrawBoard()
    {
        for (int i = 0; i < board.Length; i++)
            sprites[i].color = boardColor[board[i]];
    }

    bool BoardIsFull()
    {
        foreach (char space in board)
            if (space == ' ')
                return false;
        return true;
    }
}

它似乎从右下角开始,然后每次都向左走

如评论中所述,您没有考虑bestScore,因此bestMove始终是循环后的最后一个自由i

你可能更愿意做类似的事情,而不必深入研究其他的事情

    void CompMove()
    {
        float bestScore = -Mathf.Infinity;
        int bestMove = 0;

        for (int i = 0; i < board.Length; i++)
        {
            if(SpaceIsFree(i))
            {
                board[i] = ai;
                float score = Minimax(board, 0, false);
                board[i] = ' ';
                if(score > bestScore)
                {
                    bestScore = score;
                    bestMove = i;
                }
            }
        }

        InsertLetter(ai, bestMove);
        playerTurn = true;
    }

因为您没有检查最佳分数的结果,所以您会立即将bestMove设置为i。因此,它将始终是最后一个可用的索引,这是问题所在,感谢您的链接