我对我的象棋游戏的最小极大算法的实现有问题。它的大部分似乎都起作用了,但它要么从来没有做出好的动作,要么对它们的评估(基于两个玩家的活动棋子的分数)出了问题。例如,如果我设置了check(例如,傻瓜的伴侣),ai会做一些随机的事情,而不是杀死国王。我真的找不出我做错了什么。
评估电路板的类StandardBoardEvaluator在经过一些测试后似乎可以工作,因此问题很可能出现在MiniMax实现中的某个地方。这个游戏是由一个类棋盘组成的,它有和我自己的类方块的8x8对象的2D数组,它本身有一个棋子的引用(可以是空的,或者任何典型的棋子)。在算法中,我不断地在搜索中创建新的Board实例,这就是为什么我在Board和Square中创建这些“深度克隆”构造函数的原因,所以这似乎不是问题。像这样:
public Board(Board originalBoard) {
this.turnIsWhite = originalBoard.getTurnIsWhite();
winner = null;
squares = new Square[8][8];
for (int rank=0; rank<squares.length; rank++) {
for(int file=0; file<squares[rank].length; file++) {
squares[rank][file] = new Square(originalBoard.getSquare(posStringFromFileRank(rank, file)));
}
}
}
public Square(Square originalSquare) {
this.pos = new String(originalSquare.getPos());
this.piece = originalSquare.getPiece();
}
我有一个典型的命令类,MovePiece,用于移动碎片。这将使用另一个类MoveCheck来检查move命令是否合法。MovePiece返回一个布尔值,表示移动是否合法。这两个类都经过了大量的测试,并且正在工作,所以我不认为问题出在这些类内部。
以下是算法:
public class MiniMax implements MoveStrategy{
BoardEveluator bV;
MoveGenerator mGen;
int depth;
public MiniMax(int depth){
bV = new StandardBoardEvaluator();
mGen = new MoveGenerator();
this.depth = depth;
}
@Override
public MovePiece execute(Board board) {
MovePiece bestMove = null;
int lowestValue = Integer.MAX_VALUE;
int highestValue = Integer.MIN_VALUE;
int currentValue = 0;
String color = (board.getTurnIsWhite() ? "white" : "black");
System.out.println(color + " is evaluation best move with MiniMax depth " + depth);
List<MovePiece> allPossibleMoves = mGen.getLegalMoves(board, board.getTurnIsWhite());
for (MovePiece mp : allPossibleMoves){
Board tempBoard = new Board(board);
mp.setBoard(tempBoard);
if (mp.execute()){
currentValue = tempBoard.getTurnIsWhite() ? min(tempBoard, depth -1) : max(tempBoard, depth -1);
if (board.getTurnIsWhite() && currentValue >= highestValue){
highestValue = currentValue;
bestMove = mp;
}
else if (!board.getTurnIsWhite() && currentValue <= lowestValue){
lowestValue = currentValue;
bestMove = mp;
}
mp.unexecute();
}
}
return bestMove;
}
int min (Board board, int depth){
if (depth == 0 || board.getWinner() != null){
return bV.eveluate(board);
}
int lowestValue = Integer.MAX_VALUE;
List<MovePiece> legalMoves = mGen.getLegalMoves(board, board.getTurnIsWhite());
for (MovePiece mp : legalMoves){
Board tempBoard = new Board(board);
mp.setBoard(tempBoard);
if (mp.execute()){
int currentValue = max(tempBoard, depth - 1);
if (currentValue <= lowestValue){
lowestValue = currentValue;
}
mp.unexecute();
}
}
return lowestValue;
}
int max (Board board, int depth){
if (depth == 0 || board.getWinner() != null){
return bV.eveluate(board);
}
int highestValue = Integer.MIN_VALUE;
List<MovePiece> legalMoves = mGen.getLegalMoves(board, board.getTurnIsWhite());
for (MovePiece mp : legalMoves){
Board tempBoard = new Board(board);
mp.setBoard(tempBoard);
if (mp.execute()){
int currentValue = min(tempBoard, depth - 1);
if (currentValue >= highestValue){
highestValue = currentValue;
}
mp.unexecute();
}
}
return highestValue;
}
和evalutor类
public class StandardBoardEvaluator implements BoardEveluator {
private int scorePlayer(Board board, boolean isWhite){
return pieceValue(board, isWhite) + mobolity(isWhite, board);
}
private int mobolity(boolean isWhite, Board board){
return (int) (board.getActiveSquares(isWhite).size() * 1.5);
}
private static int pieceValue(Board board, boolean isWhite){
int piceValueScore = 0;
for (Square square : board.getActiveSquares(isWhite)){
piceValueScore += square.getPiece().getPieceValue();
}
return piceValueScore;
}
@Override
public int eveluate(Board board) {
return scorePlayer(board, true) - scorePlayer(board, false);
}
}
private Square from;
private Square to;
private Board board;
private MoveCheck mCheck;
private RulesCheck rCheck;
private boolean done = false;
private Piece killed;
public MovePiece(Board board, String from, String to) {
this.board = board;
this.from = board.getSquare(from);
this.to = board.getSquare(to);
mCheck = new MoveCheck();
}
public MovePiece(Board board, Square from, Square to) {
this.board = board;
this.from = from;
this.to = to;
mCheck = new MoveCheck();
rCheck = new RulesCheck(board);
}
public void setBoard(Board board) {
this.board = board;
}
public Board getBoard() {
return board;
}
public Square getFrom() {
return from;
}
public Square getTo() {
return to;
}
public void setFrom(Square from) {
this.from = from;
}
public void setTo(Square to) {
this.to = to;
}
public void setFrom(String from) {
this.from = board.getSquare(from);
}
public void setTo(String to) {
this.to = board.getSquare(to);
}
@Override
public boolean execute() {
rCheck = new RulesCheck(board);
if (done) {
board.movePiece(from, to);
return true;
}
else if (mCheck.isLegal(board, from, to)){
if (to.getPiece() != null) {
killed = to.getPiece();
rCheck.winCheck(killed);
}
board.setGameOutput("Moved " + from.pieceToString() + " at " + from.getPos() + " - to " + to.getPos() + "(" + to.pieceToString() + ")");
board.movePiece(from, to);
rCheck.checkPromotion(to);
done = true;
return true;
}
return false;
}
@Override
public void unexecute() {
if (to.getPiece().getClass() == Pawn.class)
((Pawn) to.getPiece()).decreaseMoves();
board.movePiece(to, from);
if (killed != null) {
to.setPiece(killed);
}
}
MoveCheck类只查看移动是否合法(路径清晰、目标是敌人或空的等等),不认为它与我的问题相关,因为代码已经测试并可以工作。
piece值在抽象类piece的子类(所有类型的pieces)中声明为int。一个卒100分,主教和骑士300分,鲁克500分,皇后900分,国王10000分。
如果有人能帮我解决这个问题,我将永远感激!请让我知道,如果您需要执行一些其他代码,我没有显示。
您还没有共享MovePiece
实现和主游戏循环,但我在minimax.execute
方法中发现了两个可能的问题:
currentValue = tempBoard.getTurnIsWhite() ? min(tempBoard, depth -1) : max(tempBoard, depth -1)
根据上面的代码,您假设MinMax播放器将始终是黑色的,因为它为白色计算min
而为黑色计算max
。对于一个通用算法,这是一个错误的假设,不知道它是否适用于您。
第二件事是在调用mp.execute()
并赋值bestmove=mp
之后,调用mp.unexecute()
,因此有效地调用bestmove.unexecute()
,因为变量指向同一个对象。
请考虑上面的建议,如果它不能解决问题,请分享上面的实现部分。
我为象棋游戏做了一个负极算法,我想知道如何使用最终的棋盘值结果。我知道负极算法的最终回报代表了玩家采取最佳策略后的棋盘值,但这并不完全是有用的信息。我需要知道那一步是什么,而不是它的价值。 代码如下: 在确定bestValue后,我考虑重新评估当前匹配状态的子项。然后我遍历它们,找出其中哪个孩子的statecore等于bestValue。但这是行不通的,因为不管怎样,他们中的很多人都会有相同的状态
DreamChess 是一款开放源码、跨平台(可在 Windows、Mac OS X 及 Linux 上运行)的 3D 国际象棋游戏。该游戏包含自身的引擎 Dreamer,提供各种国际象棋棋盘,并具有背景音乐及声效等其他附属功能。
我正在下国际象棋,除了一件事,我几乎得到了所有的东西:我需要使棋手不可能将棋子移动到棋盘上。我很难解决这个问题。 我现在用伪代码生成的有效移动是:类getMoveLocations(我定义了一个位置为国际象棋中的一个方块):如果这个位置在边界内,这个位置的棋子是敌人的棋子,并且模拟的移动不会导致棋盘被检查,然后将该位置添加到工件可以移动到的可能位置。 问题是我如何检查棋盘是否“在检查中”。在我的代
我试图实现一个带有alpha beta修剪的国际象棋游戏。以下几乎可以工作,但它返回错误的动作。 例如,可以出现以下情况。 白色(用户)移动,白色国王位置-a1/黑色(计算机),黑色国王位置-h1 白色从a1-a2移动其国王,然后黑色返回移动g2-g1??? 计算机似乎返回了错误节点的移动(电路板表示),就好像给定电路板位置的最佳评估没有一直传播到树的后面。因此,在探索的一个模拟位置中,计算机“想
我已经为我的国际象棋游戏实现了alpha-beta算法,但是要最终做出一个相当愚蠢的动作需要很多时间(4-ply需要几分钟)。 我已经试图找到错误(我假设我犯了一个)2天了,我非常感谢对我的代码的一些外部输入。 getMobile函数:为根节点调用,它为所有子节点调用alphaBeta函数(可能的移动),然后选择得分最高的移动。 AlphaBeta函数: 编辑:我应该注意到,评估板只评估棋子的机动
我已经有一个Board对象,包含一个碎片列表。Piece是一个抽象类,有一个位置(x,y)和一个颜色(黑色或白色)。然后是King、Queen、Knight这三个类,实现了Piece类。 谢谢