graph-game algorithm

graph-game algorithm

本文关键字:algorithm graph-game      更新时间:2023-10-16

我正在尝试模拟以下游戏:这个游戏是2个人玩的。想象你有一个图,有顶点和边。每个回合你可以移除一条边,如果你隔离一个顶点,你会得到一个点,你可以移除另一个点。直到所有边都没有了,得分最多的玩家获胜。

我用一个数组来表示图形,这个数组是从另一个程序生成的单独文件中读取的,例如下面这个:

0 1 1 0
1 0 1 1
1 1 0 0
0 1 0 0

玩家1可以以4/0获胜,但玩家2也可以。玩家1的最佳结果是1/3。

编辑:"一个4/0的球员怎么能赢?":

A--B--D 
| /
c
A--B--D
|
C
A  B--D
|
C

正如你所看到的,如果中间边缘被移除,第一个玩家将得到4分,否则另一个玩家将得到4分。

我可以让每个玩家都得到最好的结果,但另一个玩家不会在每个回合都选择他最好的回合。我花了很多时间进行实验,但我总是遇到同样的问题。

编辑:我认为我现在非常接近解决这个问题(然后我一直在想),我只需要为每个回合保存2个分数,然后我必须以某种方式使它只有当前玩家的最高分被接受。这样我就可以让玩家忽略4/0的移动。

编辑:我试着执行这个建议,但不幸的是我又卡住了。我要么得到一个奇怪的输出,这个输出太高了,要么这个函数只给我一个-2作为答案,但它不适用于其他更大的图。我试了很多方法来修理它,但就是不管用。下面的代码是我现在正在尝试的,不幸的是它也不起作用:
int Matrix::getTurn (bool** array) {
   if (edges == 0) 
      return 0;
    for (int i=0; i<edges; i++) {
        for (int j=0; j<edges; j++) {
            if (array[i][j] == true) {
                array[i][j] = false;
                array[j][i] = false;
                score = getScore (array, i, j);
                if (score > 0)
                   score += getTurn (array);
                else score -= getTurn (array);
                if (score > maxScore)
                   maxScore = score;
                array[i][j] = true;
                array[j][i] = true;
            }
        }
    }
   return maxScore;
}

maxScore和score是类的成员变量。谁能指出哪部分需要修改?

另一个编辑,仍然不工作,现在我只是没有看到错误。它一直输出1,就像它从来没有改变过maxScore…Takken是剩余边的数量,我尝试使用数组的边界,但它没有任何区别…

int Matrix::berekenZet (bool** array) {
   if (takken == 0)
      return 0;
   int maxScore = 0, score = 0;
    for (int i=0; i<takken; i++) {
        for (int j=0; j<takken; j++) {
            if (array[i][j] == true) {
                array[i][j] = false;
                array[j][i] = false;
                takken -= 1;
                score = berekenScore (array, i, j);
                if (score > 0)
                   score += berekenZet (array);
                 else score -= berekenZet (array);
                if (score > maxScore)
                   maxScore = score;
                array[i][j] = true;
                array[j][i] = true;
                takken += 1;
                score = 0;
            }
        }
    }
   return maxScore;
}

看起来你是在尝试实现某种形式的极大极小算法。这将为玩家找到最好的可能得分,假设两个玩家都采取了最好的行动。

但是在你的代码中有一些奇怪的事情:太多的分数变量,在函数中间无条件地分配给maxScore(从而失去其旧值),并且我不知道分数如何能够接收非零值。

这是我在伪代码中实现的。函数getScore(graph)将返回轮到该玩家的最佳得分(假设两名玩家都在最大化自己的得分),其中"得分"意味着玩家的分数减去另一名玩家的分数。我用的是极大极小的负极大变式。这使用了这样一个事实,即一个玩家的+x分数与另一个玩家的-x分数是相同的,以避免编写两次内容。你甚至不需要知道轮到谁了,因为两个玩家都可以做出完全相同的动作。

int getScore(graph):
    if no possible moves:
        return 0
    maxScore = -infinity
    for each possible move:
        make the move
        score = the score directly obtained by this move
        if the player gets another turn:
            score += getScore(graph)
        else:  //opponent turn - subtract opponent's best score from player score
            score -= getScore(graph)
        maxScore = max(maxScore, score)
        undo the move
    return maxScore