我正在为类似于国际象棋的游戏编写人工智能。棋盘为 10x10,每边 15 个棋子,所有棋子都有类似的棋步。
游戏中的一切都组织在对象中。瓦片[][]瓦片;10x10,每个 Tile 都有一个指向一块或空的块指针。
到目前为止,我已经实现了一个没有修剪的 MinMax 算法。每轮可能的移动平均是国际象棋游戏的两倍。
该算法有效,但速度很慢。平均而言,它可以检查 40000 次移动/pr 秒。因此,深度为 4 时,我的游戏使用大约 4-5 秒来计算所有可能的移动。我稍后会实施修剪,但可能需要先对我的实施提供一些反馈。
问题:我是否必须转换为 char-arrays/bit-board 或类似的格式来加快计算速度,还是我做错了什么?
实现:(sudo) 为了避免大量的双 for 循环,我在 Tiles 列表中跟踪 myPieces 和对手Pieces。棋盘评估也只进行一次,然后仅更新,并且仅通过添加和减去移动的值来更新。在我的 minMax 算法的实现中,我使用了一个保存当前游戏状态的 GameState 类。
GameState {
Tile[][] board
List<Tile> myPieces;
List<Tile> otherPieces;
int[][] evaluatedBoard
int evaluatedValue
Piece moveFrom, moveTo //used to save pointer when applying move
int moveFromValue, moveToValue //used to save evaluationValue when applying move
void applyMove(Tile from, Tile to)
void undoMove(Tile from, Tile to)
GameState createCopy()
}
ApplyMove 只更新evaluateValue 而不会遍历整个数组。myPieces 和otherPieces 也通过apply/undo 更新。
最小值最大值:
maxMove(GameState state, int depth) {
for(Tile from : state.getMyPieces().clone()) { //list will be changed
for(Tile to : from.getPiece().getPossibleMoves()) {
if(depth == 0)
//find best move and so forth
else {
state.applyMove(from, to);
minMove(state.createCopy(), depth - 1) //similar to maxMove except it uses otherPieces
state.undoMove(from, to)
}
}
}
//return best move
}
编辑:添加了有关 applyMove 和 Profiler 的信息
Profiler: instructions
applyMove() 3200ms 11 430 000
undoMove() 1800ms 11 430 000
evaluateTile() 1400ms 22 400 000
minMove() 1700ms 315 493
applyMove 和 undoMove 只存储/反向指向旧值的指针,并用移动中的新值替换它们。然后调用evaluateTile,它根据一个枚举类型返回一个1-10 的数字。