为什么我的tic tac toe minimax程序不起作用?

问题描述 投票:-2回答:1

我制作了一个游戏,其中2个井字游戏AI在3x3网格上互相对抗。但是当我运行代码时,它说bestMoveX正在使用而未初始化。

这个问题可能很容易解决,但是我无法解决这个问题。

#include <iostream>
#include<algorithm>

const short sizeX = 3, sizeY = 3, marksNeeded = 3, n = 3;

struct move
{
    int x;
    int y;
    int score;
};

void printGrid(char grid[][sizeY]);

void initGrid(char grid[][sizeY]);

move getBestMove(bool maxTurn, char grid[][sizeY], char player);

bool isThisMoveWinner(char grid[][sizeY], short iX, short iY);

#include <iostream>
#include<algorithm>
#include "TicTacTo.h"

void printGrid(char grid[][sizeY]) {
    for (short x = 0, y = 0; y != sizeY;) {
        std::cout << grid[x][y] << ' ';
        if (x == sizeX - 1) {
            std::cout << '\n';
            x = 0;
            ++y;
        }
        else {
            ++x;
        }
    }
}

bool isItATie(char grid[][sizeY]) {
    for (short x = 0, y = 0; y != sizeY;) {
        if (grid[x][y] == 45) {
            return false;
        }
        if (x == sizeX - 1) {
            x = 0;
            ++y;
        }
        else {
            ++x;
        }
    }
    return true;
}

void initGrid(char grid[][sizeY]) {
    for (short x = 0, y = 0; y != sizeY;) {
        grid[x][y] = 45;
        if (x == sizeX - 1) {
            x = 0;
            ++y;
        }
        else {
            ++x;
        }
    }
}

move getBestMove(bool maxTurn, char grid[][sizeY], char player) {
    // this function uses the minimax algorithm

    // these are low, so that the first move is always better
    static int maxScore = -2;
    static int minScore = 2;

    int bestMoveX, bestMoveY;
    // check if it is the maximizers turn (maximizer picks the move that gets the most points) (points mean who wins (1 point = max wins) (-1 point = min wins) (0 points = nobody wins))
    if (maxTurn) {
        // for every move
        for (short x = 0, y = 0; y != sizeY;) {
            if (grid[x][y] == 45) {

                // do this
                // make grid with new move
                char newGrid[sizeX][sizeY];
                std::copy(&grid[0][0], &grid[0][0] + sizeX * sizeY, &newGrid[0][0]);
                newGrid[x][y] = player;

                // if the move wins, return 1
                if (isThisMoveWinner(newGrid, x, y)) {
                    move thisMove = { x, y, 1 };
                    return thisMove;
                }

                // if its a tie, return 0
                if (isItATie(newGrid)) {
                    move thisMove = { x, y, 0 };
                    return thisMove;
                }

                // if the move doesnt win or tie recursively go through all moves possible, until you get a move that results in a tie or a win
                move thisMove = getBestMove(!maxTurn, newGrid, (player == 'x' ? 'o' : 'x'));

                // if the move is better than some other move, update bestMove
                if (maxScore < thisMove.score) {
                    maxScore = thisMove.score;
                    bestMoveX = x;
                    bestMoveY = y;
                }


            }
            if (x == sizeX - 1) {
                x = 0;
                ++y;
            }
            else {
                ++x;
            }
        }

        //return the bestMove
        move bestMove = { bestMoveX, bestMoveY, maxScore };
        return bestMove;
    }

    // it is the minimizers turn (minimizer picks the move that gets the least points because more point = good for max) (points mean who wins (1 point = max wins) (-1 point = min wins) (0 points = nobody wins))
    else {
        // for every move
        for (short x = 0, y = 0; y != sizeY;) {
            if (grid[x][y] == 45) {

                // do this
                // make grid with new move
                char newGrid[sizeX][sizeY];
                std::copy(&grid[0][0], &grid[0][0] + sizeX * sizeY, &newGrid[0][0]);
                newGrid[x][y] = player;

                // if the move wins, return -1 because it is minimizers win
                if (isThisMoveWinner(newGrid, x, y)) {
                    move thisMove = { x, y, -1 };
                    return thisMove;
                }

                // if its a tie, return 0
                if (isItATie(newGrid)) {
                    move thisMove = { x, y, 0 };
                    return thisMove;
                }

                // if the move doesnt win recursively go through all moves possible, until you get a move that results in a tie or a win
                move thisMove = getBestMove(!maxTurn, newGrid, (player == 'x' ? 'o' : 'x'));

                // if the move is better than some other move, update bestMove ( remember minimizer wants least points)
                if (minScore > thisMove.score) {
                    minScore = thisMove.score;
                    bestMoveX = x;
                    bestMoveY = y;
                }


            }
            if (x == sizeX - 1) {
                x = 0;
                ++y;
            }
            else {
                ++x;
            }
        }

        //return the bestMove
        move bestMove = { bestMoveX, bestMoveY, minScore };
        return bestMove;
    }
}


bool isThisMoveWinner(char grid[][sizeY], short iX, short iY) {
    char moveP = grid[iX][iY];

    //following code from stackoverflow

    //check col
    for (int i = 0; i < n; i++) {
        if (grid[iX][i] != moveP)
            break;
        if (i == n - 1) {
            return true;
        }
    }

    //check row
    for (int i = 0; i < n; i++) {
        if (grid[i][iY] != moveP)
            break;
        if (i == n - 1) {
            return true;
        }
    }

    //check diag
    if (iX == iY) {
        //we're on a diagonal
        for (int i = 0; i < n; i++) {
            if (grid[i][i] != moveP)
                break;
            if (i == n - 1) {
                return true;
            }
        }
    }

    //check anti diag
    if (iX + iY == n - 1) {
        for (int i = 0; i < n; i++) {
            if (grid[i][(n - 1) - i] != moveP)
                break;
            if (i == n - 1) {
                return true;
            }
        }
    }

    // end code from stackoverflow

    return false;
}

int main()
{
    char grid[sizeX][sizeY];
    initGrid(grid);
    bool xTurn = true;
    char curP;

    while (true) {
        curP = (xTurn ? 'x' : 'o');
        move thisMove = getBestMove(true, grid, curP);

        grid[thisMove.x][thisMove.y] = curP;
        printGrid(grid);
        std::cout << '\n';
        if (isThisMoveWinner(grid, thisMove.x, thisMove.y)) {
            std::cout << "The winner is " << curP;
            break;
        }
        else if (isItATie(grid)) {
            std::cout << "It's a tie";
        }
        xTurn = !xTurn;
    }
}

[根据我的大脑,最好没有初始化bestMoveX,因为如果有一个填充网格的动作,它将不会传递到getBestMove的下一层,因为isItATie将在此之前退出该函数。] >

我制作了一个游戏,其中2个井字游戏AI在3x3网格上互相对抗。但是当我运行代码时,它说bestMoveX正在使用而未初始化。问题可能非常...

c++ algorithm recursion artificial-intelligence minimax
1个回答
0
投票

我不知道为什么将STATIC放在minScore和maxScore中。移除STATIC即可解决。

© www.soinside.com 2019 - 2024. All rights reserved.