java里nim游戏问题_使用Minimax算法的NIM游戏和AI玩家 - AI会失去动作

我已经完成了与人类玩家和AI玩家一起编写NIM游戏的任务 . 该游戏是“Misere”(最后一个必须选择一根棒) . 人工智能应该是使用Minimax算法,但它正在进行移动,使其失去更快,我无法弄清楚为什么 . 我已经连续几天走到了尽头 . Minimax算法的目的是不输,如果它处于失败状态,延迟失去尽可能多的动作,对吧?

考虑以下:

NIMBoard board =新的NIMBoard(34,2);

34 =棒的二进制编码位置,2桩2支

2 =桩数

所以我们从这个场景开始,*字符代表一个棒:

Row 0: **

Row 1: **

在这种特殊的电路板情况下,Minimax算法总是提出“从第1行中删除2支”的动作 . 这显然是一个糟糕的举动,因为它在第0行留下2支,然后人类玩家可以从第0行中挑选1支并赢得比赛 .

AI玩家应该选择从任何一堆中挑选一根棍子 . 这留给了人类玩家:

Row 0: *

Row 1: **

因此,无论人类玩家现在采取何种行动,当计算机在此之后进行下一步行动时,人类玩家将永远失败 . 显然是一个更好的策略,但为什么算法没有提出这一举措呢?

public class Minimax

{

public Move nextMove;

public int evaluateComputerMove(NIMBoard board, int depth)

{

int maxValue = -2;

int calculated;

if(board.isFinal())

{

return -1;

}

for(Move n : this.generateSuccessors(board))

{

NIMBoard newBoard = new NIMBoard(board.getPos(), board.getNumPiles());

newBoard.parseMove(n);

calculated = this.evaluateHumanMove(newBoard, depth + 1);

if(calculated > maxValue)

{

maxValue = calculated;

if(depth == 0)

{

System.out.println("Setting next move");

this.nextMove = n;

}

}

}

if(maxValue == -2)

{

return 0;

}

return maxValue;

}

public int evaluateHumanMove(NIMBoard board, int depth)

{

int minValue = 2;

int calculated;

if(board.isFinal())

{

return 1;

}

for(Move n : this.generateSuccessors(board))

{

NIMBoard newBoard = new NIMBoard(board.getPos(), board.getNumPiles());

newBoard.parseMove(n);

calculated = this.evaluateComputerMove(newBoard, depth + 1);

// minValue = Integer.min(this.evaluateComputerMove(newBoard, depth + 1), minValue);

if(calculated < minValue)

{

minValue = calculated;

}

}

if(minValue == 2)

{

return 0;

}

return minValue;

}

public ArrayList generateSuccessors(NIMBoard start)

{

ArrayList successors = new ArrayList();

for(int i = start.getNumPiles() - 1; i >= 0; i--)

{

for(long j = start.getCountForPile(i); j > 0; j--)

{

Move newMove = new Move(i, j);

successors.add(newMove);

}

}

return successors;

}

}

public class NIMBoard

{

/**

* We use 4 bits to store the number of sticks which gives us these

* maximums:

* - 16 piles

* - 15 sticks per pile

*/

private static int PILE_BIT_SIZE = 4;

private long pos;

private int numPiles;

private long pileMask;

/**

* Instantiate a new NIM board

* @param pos Number of sticks in each pile

* @param numPiles Number of piles

*/

public NIMBoard(long pos, int numPiles)

{

super();

this.pos = pos;

this.numPiles = numPiles;

this.pileMask = (long) Math.pow(2, NIMBoard.PILE_BIT_SIZE) - 1;

}

/**

* Is this an endgame board?

* @return true if there's only one stick left

*/

public boolean isFinal()

{

return this.onePileHasOnlyOneStick();

}

/**

* Figure out if the board has a pile with only one stick in it

* @return true if yes

*/

public boolean onePileHasOnlyOneStick()

{

int count = 0;

for(int i = 0; i < this.numPiles; i++)

{

count += this.getCountForPile(i);

}

if(count > 1)

{

return false;

}

return true;

}

public int getNumPiles()

{

return this.numPiles;

}

public long getPos()

{

return this.pos;

}

public long getCountInPile(int pile)

{

return this.pos & (this.pileMask << (pile * NIMBoard.PILE_BIT_SIZE));

}

public long getCountForPile(int pile)

{

return this.getCountInPile(pile) >> (pile * NIMBoard.PILE_BIT_SIZE);

}

public void parseMove(Move move)

{

this.pos = this.pos - (move.getCount() << (move.getPile() * NIMBoard.PILE_BIT_SIZE));

}

@Override

public String toString()

{

String tmp = "";

for(int i = 0; i < this.numPiles; i++)

{

tmp += "Row " + i + "\t";

for(int j = 0; j < this.getCountForPile(i); j++)

{

tmp += "*";

}

tmp += System.lineSeparator();

}

return tmp.trim();

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值