Java i';我坚持使用alpha-beta剪枝算法实现
我正在尝试为9男子莫里斯游戏实施游戏AI。 到目前为止,我的董事会如下所示:Java i';我坚持使用alpha-beta剪枝算法实现,java,algorithm,alpha-beta-pruning,Java,Algorithm,Alpha Beta Pruning,我正在尝试为9男子莫里斯游戏实施游戏AI。 到目前为止,我的董事会如下所示: public class board { public node []gNode = null; ... // so the table has 24 nodes, for 9 men morris game: gNode = new node[24]; ... int evalua
public class board
{
public node []gNode = null;
... // so the table has 24 nodes, for 9 men morris game:
gNode = new node[24];
...
int evaluateBoard(); // evaluates the current board (tokens)
}
好的,现在每个节点都是这样表示的:
public class node
{
node() // constructor
{ ... }
// setting current node's neighbours (maximum 4 neighbours)
void setNeighbours(int left, int right, int top, int bottom)
{ ... }
short gOccupiedByTeam = renderer.TEAM_NOTEAM; // info if this node is occupied by a token (and a wich team this token belongs to)
short []gNeighbourId = null; // info about this node neighbours (can be max. 4 in a 9Men's morris game)
short gInternalID = -1; // board's IDs (from 0..23)
short gTokenID = -1; // this node can be occupied by a token. (from 0 .. 8) -see below the token class.
short gNodeScore = -1; // a dummy node score.
vector3 gLocation = null; // 3d coordinates for this node.
}
而标记如下所示:
public class token
{
token(vector3 startpos, short nodeId) // Constructor.
{ ... }
public physx gPhysX = null; // 3d coordinates , velocity , accel. for this Token.
public boolean bIsAlive = false; // is this token alive ? (or eliminated?)
public boolean bFormsMill = false; // does it form a Mill?
public short gNodeID = -1; // "link" this token with a gNodeID (when placing a token on current board). See above the node class. This represents a link ID to that node.
public short gTokenMill1 = -1; // used when this token forms a mill (with gTokenMill1 token!)
public short gTokenMill2 = -1; // same.
}
这是我的Alpha-Beta剪枝算法实现,我被卡住了:
public int getBestMove(board board, int depth, int alpha, int beta, boolean bIsPlayer)
{
// if depth reached, return current's board's Evaluation (a score).
if (depth == 0) return board.evaluateBoard(bIsPlayer);
// is it Player's turn ? (max?)
if (bIsPlayer)
{
// QUESTIONS:
// retrevie all possible "boards" below ! (all new possible token moves)
// 1. here i should generate a new board with 1st possible move (for player token1) ?? ... then a second new board with 2nd possible move still for token1 ? .. and so on until no possible moves for token1?
// (remembering that a token can move in 4 available spots - wich are a neighbour?)
//
// 2. the problem is that if i generate 4 new boards as per token 1 above let's say, then it will "eat" lot of memory for all 18 tokens and a function recursion depth of 5 for example, right ?
// 3. how do i fix point 2?
ArrayList<board> possible_boards = board.getAllPossibleBoards();
// 4. ok, some possible boards were generated, loop thru them starting with the first one and calling recursively this function, is it right ?
for(board iterator: possible_boards)
{
alpha = Math.max(alpha, getBestMove(iterator, depth - 1, alpha, beta, !bIsPlayer));
if (beta < alpha)
{
break;
}
}
// 5. how do i return best move to main calling function ? (wich token is it best move from all of these board's moves ?
return alpha;
}
else
{
ArrayList<board> possible_boards = board.getAllPossibleBoards();
for(board iterator: possible_boards)
{
beta = Math.min(beta, getBestMove(iterator, depth - 1, alpha, beta, !bIsPlayer));
if (beta < alpha)
{
break;
}
}
return beta;
}
}
好的,现在有一个新生成的板,递归,如果找到更好的板(得分更好的板),则将当前板保存到chosenBoard。如果没有,则切断并返回(不要在树下进一步检查)
再次非常感谢saeedn 一般来说,您的代码是可以的,但是您应该记住一些要点 首先,您应该检查节点(这里是一个棋盘)是否为最终节点(有人赢得了游戏),然后检查深度是否等于零。如果有人在该状态下获胜,您可能希望分别为exmaple MAXINT和MININT返回一个大值(用于赢得max player)和一个小值(用于赢得min player) 为避免高内存消耗,请勿生成所有可能的电路板。生成一块电路板,对其进行递归调用,然后生成另一块电路板并搜索该电路板,依此类推。这样,您只需在每个堆栈帧中为一个状态使用内存。这在具有高分支因子的搜索中至关重要 最后,您应该记录max player的棋盘更新分数(更新alpha) 有关更多说明,请参见我的伪代码:
if ( board.checkWinner(bIsPlayer) ) return board.evaluateBoard(bIsPlayer);
// if depth reached, return current's board's Evaluation (a score).
if (depth == 0) return board.evaluateBoard(bIsPlayer);
board chosenBoard;
if (bIsPlayer)
{
// You should implement this method, or write your board generation code here
// returns false if no more boards could be generated
board nextBoard;
while( board.generateNextPossibleBoard(nextBoard) )
{
int v = getBestMove(iterator, depth - 1, alpha, beta, !bIsPlayer));
if ( v > alpha )
{
alpha = v;
chosenBoard = nextBoard; // return this chosenBoard by reference ;)
}
if (beta < alpha)
{
break;
}
}
return alpha;
}
else
{
// The same for beta except you don't need to update chosenBoard :)
}
if(board.checkWinner(bIsPlayer))返回board.evaluateBoard(bIsPlayer);
//如果达到深度,返回当前板的评估(分数)。
如果(深度==0)返回板。评估板(bIsPlayer);
董事会选择董事会;
如果(双星玩家)
{
//您应该实现此方法,或者在此处编写电路板生成代码
//如果无法生成更多板,则返回false
下一块板;
while(板生成下一个板)
{
intv=getBestMove(迭代器,深度-1,alpha,beta,!bIsPlayer));
如果(v>alpha)
{
α=v;
chosenBoard=nextBoard;//通过引用返回此chosenBoard;)
}
如果(β<α)
{
打破
}
}
返回α;
}
其他的
{
//测试版也一样,只是不需要更新chosenBoard:)
}
因此,请确定,这是一个极小极大算法,对吗?是的,极小极大alpha-beta修剪。谢谢你的快速回复。我不知道要传递给getBestMove()的参数是什么?作为节点?作为象征?我以董事会的身份发送。。以及如何生成下一个可能的移动(板)是我做的正确到目前为止吗?生成所有可能的板与你阿尔法-贝塔树。然后使用“EvaluateBoard”功能评估结束节点(板),评估板的分数(您根据AI的碎片配置确定如何给出分数)。然后你拿了他们中最好的一块(根据分数)。然后下一步将是走向最好的董事会。谢谢弗朗西斯。哦,看来我在上面所做的是正确的。但是我不知道我是否应该为token1生成一个棋盘,然后为token1生成第二个移动..以此类推,直到token1没有移动。在那之后,我将继续为token2制作一块板,就像我为Token1制作的一样??我不完全确定,但不应该制作。evaluateBoard(bIsPlayer);beboard.evaluateBoard(root_color)?@FolkertvanHeusden这取决于evaluateBoard
的实现方式。根据OP的代码,它应该是board.evaluateBoard(bIsPlayer)
。如果你做了皇后数[当前玩家]-皇后数[当前玩家的对手],那么它应该是bIsPlayer?对不起,我唠叨了这么多,但我想100%肯定地知道,然后我会适应维基百科页面,这样其他人现在也可以肯定了。顺便说一句,谢谢:-)@FolkertvanHeusden我不知道目标游戏!我的建议是alpha-beta实现的一般思路。在这里,您可以将评估板的过程封装在函数中。如果你认为evaluateBoard
有一个错误的输入参数,请在原始帖子的评论中提及,这样作者就会得到通知并回答你的问题:)
if ( board.checkWinner(bIsPlayer) ) return board.evaluateBoard(bIsPlayer);
// if depth reached, return current's board's Evaluation (a score).
if (depth == 0) return board.evaluateBoard(bIsPlayer);
board chosenBoard;
if (bIsPlayer)
{
// You should implement this method, or write your board generation code here
// returns false if no more boards could be generated
board nextBoard;
while( board.generateNextPossibleBoard(nextBoard) )
{
int v = getBestMove(iterator, depth - 1, alpha, beta, !bIsPlayer));
if ( v > alpha )
{
alpha = v;
chosenBoard = nextBoard; // return this chosenBoard by reference ;)
}
if (beta < alpha)
{
break;
}
}
return alpha;
}
else
{
// The same for beta except you don't need to update chosenBoard :)
}