我正在尝试在Reversi / Othello游戏中实现MiniMax算法,而且我很困难,因为我写的函数看起来非常正常,但是我得到了一些奇怪的动作,并且在几次之后发生了崩溃。这是找到最佳动作的函数:
public Field findBestMove(GameBoard gb, int depth, int player)
{
if(depth >= max_depth) return null;
ArrayList <Field> moves = findAllPossibleMoves(gb, player);
Field best_move = null;
/** iterating over all possible moves, to find the best one */
for (int i=0; i<moves.size(); i++)
{
/* board to simulate moves */
GameBoard temp_board = new GameBoard(gb);
Field move = moves.get(i);
game.move(move, temp_board, player);
int opposite_player = player == GameBoard.WHITE ? GameBoard.BLACK : GameBoard.WHITE;
Field best_deep_move = findBestMove (temp_board, depth + 1, opposite_player);
/** if the maximum depth is reached, we have a null, so we evaluate */
if (best_deep_move == null)
{
/** we rate it according to the evaluation table */
move.setRating(evaluate (temp_board, player));
}
else
{
move.setRating(best_deep_move.getRating());
}
if(best_move == null)
{
best_move = move;
}
else
{
if (depth%2==0)
{
/** for us, we look for the maximum */
if (best_move.getRating() < move.getRating()) best_move = move;
}
else
{
/** for the opponent, we look for the minimum */
if (best_move.getRating() > move.getRating()) best_move = move;
}
}
}
return best_move;
}
每次移动后,活动播放器都会更改。在GameView的onTouchEvent方法中,首先玩家进行移动,然后将玩家改为WHITE,即AI,然后进行移动。它应该在他的树中搜索最佳移动,然后执行一次移动,而不是做几个奇怪的移动。我不知道为什么,为每个分支创建一个新的主板副本,所以我不知道为什么主游戏板会被修改。
有什么想法吗?
答案 0 :(得分:2)
如果更改对象的副本会影响原始对象。然后它是一个“浅拷贝”。这意味着数据结构对象中的某个位置是共享的。你想要一个“深层复制”。
向我们展示new GameBoard(gb)
一些optinos:您可以为Gameboard及其包含的所有对象(以及它们包含的对象)实现克隆。或者,在游戏板中实现undo()函数。只要您撤消游戏板中的每个动作,您就可以对其进行移动。这可以在评估期间进行测试移动时节省内存和对象创建开销。