我正在用Java编写Nine Men's Morris game并且已经实现了游戏规则和使用negamax的AI。然而,游戏是基于数组的,当人工智能正在思考时,移动生成需要相当长的时间(从6层开始)。
我的位置数组基于下图:
// 0 1 2
// 3 4 5
// 6 7 8
// 9 10 11 12 13 14
// 15 16 17
// 18 19 20
// 21 22 23
我有更多的阵列充满了可能的工厂和相邻的位置。
我决定将游戏从阵列更改为使用位板,以便移动生成和当前使用阵列的其他区域将更快。
我的第一步是为每个玩家设置一个位板,以便跟踪玩家在棋盘上的棋子。
第二步是确定自由职位的位置。我知道我可以这样做:
freepositions = ~(player1bb | player2bb);
所以我的问题是,如何设置/更新播放器的位板以跟踪他们的作品?
答案 0 :(得分:1)
考虑到玩家的位板长度为24位,棋盘位置0为第一位,当玩家进行移动时设置位置变得非常简单:
player1bb |= (1 << pos);
答案 1 :(得分:0)
比特板很有趣: - )
我正在为这个问题编写一些代码,但这里有一些东西可以帮助你开始:
public class BitBoard {
public static final int White = 0;
public static final int Black = 1;
public long[] board = { 0, 0 };
public int Player = 0;
public int[] left = { 9, 9 };
public int Opponent()
{
return Player == White ? Black : White;
}
public void makemove(int from, int to, int capture)
{
if (from == 0) {
assert left[Player] > 0 : "makemove: no left";
left[Player]--;
}
if (from != 0)
{
assert (board[Player] & from) != 0 : "makemove: source empty";
board[Player] &= ~from;
}
assert (board[Player] & to) == 0 : "makemove: target must be empty";
board[Player] |= to;
if (capture != 0)
{
assert (board[Opponent()] & capture) != 0 : "makemove: capture empty";
board[Opponent()] &= ~capture;
}
}
public void unmakemove(int from, int to, int capture)
{
if (capture != 0)
{
assert (board[Opponent()] & capture) == 0 : "unmakemove: capture empty";
board[Opponent()] |= capture;
}
assert (board[Player] & to) != 0 : "unmakemove: target empty";
board[Player] &= ~to;
if (from != 0)
{
assert (board[Opponent()] & capture) != 0 : "unmakemove: source must be empty empty";
board[Player] |= from;
}
if (from == 0) {
assert left[Player] < 9 : "unmakemove: too many left";
left[Player]++;
}
}
public void generatemoves()
{
// determine phase
//
}
}
没有完全测试,但以下代码显示了如何使用:
import java.math.*;
public class NineMenBitboard {
static int tst;
// A B C D E F G
// 1 0 1 2
// 2 3 4 5
// 3 6 7 8
// 4 9 10 11 12 13 14
// 5 15 16 17
// 6 18 19 20
// 7 21 22 23
// positions
static int A1 = 1 << 0;
static int D1 = 1 << 1;
static int G1 = 1 << 2;
static int B2 = 1 << 3;
static int D2 = 1 << 4;
static int F2 = 1 << 5;
static int C3 = 1 << 6;
static int D3 = 1 << 7;
static int E3 = 1 << 8;
static int A4 = 1 << 9;
static int B4 = 1 << 10;
static int C4 = 1 << 11;
static int E4 = 1 << 12;
static int F4 = 1 << 13;
static int G4 = 1 << 14;
static int C5 = 1 << 15;
static int D5 = 1 << 16;
static int E5 = 1 << 17;
static int B6 = 1 << 18;
static int D6 = 1 << 19;
static int F6 = 1 << 20;
static int A7 = 1 << 21;
static int D7 = 1 << 22;
static int G7 = 1 << 23;
// mills
static int hor1 = A1 | D1 | G1;
static int hor2 = B2 | D2 | F2;
static int hor3 = C3 | D3 | E3;
static int hor4_1 = A4 | B4 | C4;
static int hor4_2 = E4 | F4 | G4;
static int hor5 = C5 | D5 | E5;
static int hor6 = B6 | D6 | F6;
static int hor7 = A7 | D7 | G7;
static int ver1 = A1 | A4 | A7;
static int ver2 = B2 | B4 | B6;
static int ver3 = C3 | C4 | C5;
static int ver4_1 = D1 | D2 | D3;
static int ver4_2 = D5 | D6 | D7;
static int ver5 = E3 | E4 | E5;
static int ver6 = F2 | F4 | F6;
static int ver7 = G1 | G4 | G7;
public static void main(String[] args) {
// sample on how to loop bits
BitBoard game = new BitBoard();
game.makemove(0, A1, 0);
game.makemove(A1, A4, 0);
System.out.println();
tst = 255;
for(int looper = tst, i = Integer.highestOneBit(looper); looper != 0; looper &= ~i, i = Integer.highestOneBit(looper))
{
System.out.println(i);
}
System.out.println(tst);
}
}
还添加了一个循环,以显示如何循环位置。
玩得开心。我也将编写这个游戏,因为我想刷新我的AB修剪: - )
答案 2 :(得分:0)
这是Perft代码。我也做了所有的第一步动作,但是在未来的版本中,我可能只会做6个独特的动作(其他的只会导致评估镜像)。
public long Perft(int depth)
{
long nodes = 0;
ArrayList<Integer> moves = generateMoves();
if (depth == 1)
{
//for(int move : moves)
// System.out.println(moveStr(move));
return moves.size();
}
for (int move : moves) {
int capture = 1 << (move >> 10) >> 1;
int to = 1 << ((move >> 5) & 31) >> 1;
int from = 1 << (move & 31) >> 1;
makemove(from, to, capture);
//System.out.print(this);
nodes += Perft(depth - 1);
unmakemove(from, to, capture);
}
return nodes;
}
如你所见,我把行动打包成了一切。
对于理智检查,这是我的第一个秘密结果:
答案 3 :(得分:0)
我知道你是aleadry实现它,但你应该像那样实现它
// 0 1 2
// 8 9 10
// 16 17 18
// 7 15 23 19 11 3
// 22 21 20
// 14 13 12
// 6 5 4
这样你可以移动投掷位置pos&gt;&gt; 1为私有pos&lt;&lt; 1为下一个,pos&lt;&lt; 8为下一个字节相同的postion pos&gt;&gt; 8之前的字节相同位置