图形游戏算法

时间:2013-03-28 16:09:22

标签: c++ algorithm matrix graph-algorithm

我正在尝试模拟以下游戏: 该游戏由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;
}

提前致谢。

1 个答案:

答案 0 :(得分:1)

您似乎正在尝试实施某种形式的Minimax算法。这为玩家找到了最好的分数,假设两个玩家都为自己做出了最好的动作。

但是你的代码中有一些奇怪的东西:分数变量太多,在函数中间无条件地分配给maxScore(从而失去旧值),我看不出分数如何可能会收到非零值。

这是我在伪代码中实现的。函数getScore(graph)将为轮到它的玩家返回最佳分数(假设两个玩家都玩最大化他们自己的分数),其中“分数”表示玩家的分数减去其他玩家的分数。我正在使用minimax的Negamax变体。这使用了这样的事实:一个玩家的+ 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
相关问题