Tic Tac Toe C++ algorithm debugging help

送分小仙女□ 提交于 2020-01-05 07:46:44

问题


Please help me understand why this isn't working. I don't know if there is a bug in my code, or whether my algorithm is fundamentally logically flawed.

My algorithm is based on minimax, but I've forgone a heuristic evaluation function for a more simple technique. Because of the simplicity of plain 3x3 tic tac toe, I just want to calculate all possible game outcomes for each potential move, and select the one with the highest 'score'. I create a 'top level' vector of valid moves as well as a matching sized vector for their corresponding 'scores' -i.e. for every possible outcome subsequent to that move: ++ for a win and -- for a loss.

However my vector of move scores is getting strange non-symmetrical values. Although even if the code worked, logically is it possible that a move which is calculated to lead to the most wins and least losses, would be blind to a simple tactic such as a fork? My instincts say yes, but I haven't worked out the math in detail.

char board [9] = { '.','.','.','.','.','.','.','.','.' };

int com_turn(int turn) 
    {
    char player=COM; // keeps track of current player  

    cout<<"Computer turn. \n";  

    vector<int> moves = get_valid_moves(board); // top level move list
    vector<int> m_scores (moves.size(), 0);  // top level move scores

    for (int m=0; m < moves.size(); m++) // eval each top level move
    {
        board[moves[m]] = player; // do move

        evaluate(board, turn, &m_scores[m], player); 
        cout<< m_scores[m] <<' '; // for debugging

        board[moves[m]]='.'; // undo move
    }

    int bestmove;
    for (int i=0; i < moves.size(); i++) // find best score
    {
        bestmove = max(bestmove, m_scores[i]);
    }
    for (int i=0; i < moves.size(); i++) // match to best move
    {
        if (bestmove == m_scores[i])
        {
            bestmove = moves[i];
            break;
        }
    }

    board[bestmove]=COM; // finally make com move
    print_board();
}

vector<int> get_valid_moves(char *board) 
{
    vector<int> vmoves;
    for (int i=0; i < 9; i++)
    {
        if (board[i]=='.') vmoves.push_back(i);
    }
    return vmoves;
}


void evaluate(char *board, int turn, int *mscore, char player) 
{
    if (check_win(board)) 
    {
        (player==HUMAN)? *mscore -= 1: *mscore += 1;  
        return;  
    }
    if (turn > 9) return;

    vector<int> child_moves = get_valid_moves(board);
    if (child_moves.size() < 1) return;

    (player==COM)? player=HUMAN: player=COM; // switch player

    for (int m=0; m < child_moves.size(); m++) 
    {
        board[child_moves[m]] = player; // do move

        evaluate(board, ++turn, mscore, player);

        board[child_moves[m]]='.'; // undo move
    }
}

回答1:


I think you'll see where the problem is if you make evaluate return the score rather than using return-by-reference.

Evaluate should be minimaxing, but right now I think it's doing some weird sum of the leaf nodes because of the side-effect of additions and subtractions.

Why summing up the scores is not correct

Suppose I have the board:

. . O
. . .
. X X

Then O only has one move, (block), because X's next move will win if O doesn't make it. However, there are lots of game paths that start at O making other moves, with O winning, like:

O2 O1 O
.  .  X1
.  X  X

Where the number indicates which move came first.

So you see, just getting the sum isn't going to give you the right answer.

The reason I recommend passing the values up the tree is that that forces you to write out what the score at a node is as a function of the children. In your code right now the function is the sum, in minimax it's either min or max, depending on the player's turn.



来源:https://stackoverflow.com/questions/6240995/tic-tac-toe-c-algorithm-debugging-help

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!