首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >MiniMax TicTacToe AI

MiniMax TicTacToe AI
EN

Stack Overflow用户
提问于 2020-06-15 17:05:36
回答 1查看 874关注 0票数 0

我正在尝试实现MiniMax来创建一个TicTacToe AI。我使用的是C#和Unity。我在跟踪编码列车视频。本教程是用JavaScript编写的,但我在C#中继续学习。我试过查看他网站上的MiniMax代码,但我不明白为什么我的“翻译”不起作用:

代码语言:javascript
运行
复制
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;
    }
}

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

EN

回答 1

Stack Overflow用户

发布于 2020-06-15 17:25:36

正如注释中提到的,您没有考虑到bestScore,因此bestMove始终是循环之后的最后一个空闲i

你也许应该做一些类似的事情(没有深入观察其他的)。

代码语言:javascript
运行
复制
    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;
    }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62393303

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档