Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/374.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 九人莫里斯游戏的比特板表示_Java_Artificial Intelligence_Bitboard - Fatal编程技术网

Java 九人莫里斯游戏的比特板表示

Java 九人莫里斯游戏的比特板表示,java,artificial-intelligence,bitboard,Java,Artificial Intelligence,Bitboard,我正在用Java编写一个应用程序,已经用negamax实现了游戏规则和AI。然而,游戏是基于阵列的,当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 我有更多的阵列,可能有磨坊

我正在用Java编写一个应用程序,已经用negamax实现了游戏规则和AI。然而,游戏是基于阵列的,当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);

所以我的问题是,我如何设置/更新玩家的比特板来跟踪他们的棋子?

考虑到玩家的比特板有24位长,棋盘的位置0是第一位,当玩家移动时设置比特板非常简单,方法如下:

player1bb |= (1 << pos);
player1bb |=(1比特板很有趣:-)

我正在为这个问题编写一些代码,但这里有一些东西可以帮助您开始:

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

        // 

    }
}
公共类位板{
公共静态最终整数白色=0;
公共静态最终整数黑色=1;
公共长[]板={0,0};
公共整数播放器=0;
公共int[]左={9,9};
公共int对手()
{
返回玩家==白色?黑色:白色;
}
公共void makemove(int-from、int-to、int-capture)
{
如果(from==0){
断言左[玩家]>0:“makemove:无左”;
左[玩家]——;
}       
如果(从!=0)
{
断言(棋盘[玩家]&来自)!=0:“makemove:源空”;
棋盘[玩家]&=~来自;
}
断言(棋盘[Player]&to)==0:“makemove:目标必须为空”;
棋盘[牌手]|=到;
如果(捕获!=0)
{
断言(棋盘[对手()]和捕获)!=0:“makemove:捕获为空”;
棋盘[对手()]&=~捕获;
}
}
公共无效取消移动(int-from、int-to、int-capture)
{
如果(捕获!=0)
{
断言(棋盘[对手()]和捕获)=0:“取消移动:捕获为空”;
棋盘[对手()]|=捕获;
}
断言(棋盘[玩家]&目标)!=0:“取消移动:目标为空”;
棋盘[玩家]&=~to;
如果(从!=0)
{
assert(board[hatcher()]和capture)!=0:“取消移动:源必须为空”;
棋盘[玩家]|=来自;
}
如果(from==0){
断言左[玩家]<9:“取消移动:左过多”;
左[玩家]+;
}           
}
公共void generatemoves()
{
//定相
// 
}
}
未对此进行全面测试,但以下代码显示了如何使用:

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);
      }
}
import java.math.*;
公共类九位板{
静态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
//职位

静态int A1=1这是性能代码。我也会做所有的第一步,但在未来的版本中,我可能只会做6个唯一的(其他的只会导致镜像的评估)

public long Perft(整数深度)
{
长节点=0;
ArrayList moves=generateMoves();
如果(深度==1)
{
//for(整数移动:移动)
//System.out.println(moveStr(move));
返回移动。size();
}
for(整数移动:移动){
int capture=1>10)>>1;
int to=1>5)和31>1;
int from=1>1;
makemove(从、到、捕获);
//系统输出打印(本);
节点+=性能(深度-1);
取消移动(从、到、捕获);
}
返回节点;
}
如你所见,我将移动打包成整数

对于健全性检查,以下是我的第一个性能结果:

  • 124
  • 2552
  • 312144
  • 4255024
  • 55140800
  • 699274176(3.107ms)
  • 7 1873562112(53秒)
  • 8需要太长时间

    • 我知道你是阿莱德里要求的,但你应该这样实施

      //  0        1           2
      //     8     9       10
      //        16  17  18
      //  7 15  23      19 11  3
      //        22   21 20
      //    14    13       12
      //  6       5            4
      

      通过这种方式,你可以移动私密位置8的投掷位置>>1之前的字节相同位置

      比特板的真正优势是在生成makemove和unmakemove时保留一些额外的数据。我的第一个新增功能是跟踪每个玩家的成形磨数和铣削位置。这将大大改进移动生成(以及稍后的电路板评估)。我有类似的比特板代码。我正在与TT合作Negascout。如果您想共享更多代码,请告诉我。我们可以共享代码。我考虑在稍后阶段将其放在github上。我通过跟踪磨石完成了makemove/unmakemove。似乎可行,但需要进行健全性检查。我运行了性能测试(7)is在53秒内给出了1.873.562.112步。我要发布性能代码以便您检查吗?请发电子邮件到blastedw(at)hotmail(dot)com或add me on FBMy perft on ply 6在5.79秒内返回2164535个节点。但是我的perft复制电路板,生成移动,移动并撤销。嗯,pitty nodecounts不一致:好吧,我将深入调试:-)
      //  0        1           2
      //     8     9       10
      //        16  17  18
      //  7 15  23      19 11  3
      //        22   21 20
      //    14    13       12
      //  6       5            4