c - Minimax 算法并检查每个选项/跟踪 C 中的最佳移动

标签 c algorithm

我尝试使用极小极大算法制作井字棋游戏,但我在递归和跟踪最佳移动方面遇到了困难。 现在,我的函数在出现获胜者时返回分数,然后从棋盘上删除该移动。我的问题是,如何防止它再次搜索同一个子节点?

int minimax(Board *board, int depth, char player, Position lastPosition)
{
    Position avMoves;
    int score = -2;

    if (didTheGameEnd(*board, (player == 'X') ? 'O' : 'X', lastPosition) == 1) {
        return (depth % 2 != 0) ? -10 : 10;
    } else if (didTheGameEnd(*board, (player == 'X') ? 'O' : 'X', lastPosition) == -1) {
        return 0;
    }

    if (board->numberOfBlanks != 0) {
        avMoves = getAvaliableMoves(*board);
    }

    for (int i = 0; i < board->numberOfBlanks; i++) {
        int newScore;
        placeMark(board, player, avMoves);
        newScore = minimax(board, depth+1, changePlayer(player), avMoves);
        if (depth % 2 != 0) {
            if (newScore > score) {
                score = newScore;
            }
        } else {
            if (newScore < score) {
                score = newScore;
            }
        }
        board->boardArr[avMoves.y][avMoves.x] = '-';
        board->numberOfBlanks++;
        board->numberOfOccupied--;
    }
    return score;
}

如何返回最佳棋步? 编辑我忘了添加,我尝试在 N 尺寸板上制作这个

最佳答案

查看下面 Tom Kerrigan 的“简单国际象棋程序”的源代码可能会有所帮助

基本上,以下代码是 alpha-beta (minmax) 函数的一部分。它生成移动并在 for 循环中检查移动中是否有任何合法移动(这是必要的,因为国际象棋使用伪合法移动生成器),返回最佳变化的关键部分是使用“三角数组”收集 pv[0][0..pv_length[0]] 中的最佳变化。 pv_length 跟踪博弈树不同深度的最佳变体的长度。这是一个乏味的索引方案,但完成了工作。

gen();
    if (follow_pv)  /* are we following the PV? */
        sort_pv();
    f = FALSE;

    /* loop through the moves */
    for (i = first_move[ply]; i < first_move[ply + 1]; ++i) {
        sort(i);
        if (!makemove(gen_dat[i].m.b))
            continue;
        f = TRUE;
        x = -search(-beta, -alpha, depth - 1);
        takeback();
        if (x > alpha) {

            /* this move caused a cutoff, so increase the history
               value so it gets ordered high next time we can
               search it */
            history[(int)gen_dat[i].m.b.from][(int)gen_dat[i].m.b.to] += depth;
            if (x >= beta)
                return beta;
            alpha = x;

            /* update the PV */
            pv[ply][ply] = gen_dat[i].m;
            for (j = ply + 1; j < pv_length[ply + 1]; ++j)
                pv[ply][j] = pv[ply + 1][j];
            pv_length[ply] = pv_length[ply + 1];
        }
    }

    /* no legal moves? then we're in checkmate or stalemate */
    if (!f) {
        if (c)
            return -10000 + ply;
        else
            return 0;
    }

    /* fifty move draw rule */
    if (fifty >= 100)
        return 0;
    return alpha;
}

关于c - Minimax 算法并检查每个选项/跟踪 C 中的最佳移动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43719150/

相关文章:

arrays - 找到分离数组的方法,使每个子数组的总和小于或等于一个数字

algorithm - Hashcode计算为什么乘法忽略溢出位?

algorithm - 枚举有向无环图中的所有路径

编译器没有看到我的元素被添加到我的数组中

c - 如何释放结构内的结构数组?

java - 在线性路径中从一个点移动到另一个点

algorithm - 如何在梯形边上加点?

c - 想弄清楚为什么在我什么都没做的情况下结构元素发生了变化

c - 我应该使用宏还是变量?

c - C 中的字符串操作