gpt4 book ai didi

java - 使用 Minimax 算法的 NIM 游戏和 AI 玩家 - AI 会输棋

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:31:48 32 4
gpt4 key购买 nike

我接到了一项任务,要编写一个由人类玩家和 AI 玩家组成的 NIM 游戏。游戏是“Misere”(最后一个必须拿起一根棍子的人输了)。 AI 应该使用 Minimax 算法,但它正在采取使其输得更快的 Action ,我不明白为什么。几天来我一直处于死胡同。Minimax算法的重点是不输,如果处于亏损位置,尽量延迟亏损,对吧?

考虑以下几点:

NIMBoard board = new 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<Move> generateSuccessors(NIMBoard start)
{
ArrayList<Move> successors = new ArrayList<Move>();
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();
}

}

最佳答案

您认为对 AI 来说更好的一步实际上并不是更好的一步。在那种棋盘情况下,人类玩家会从第 1 行拿走两根棍子,而计算机仍然在拿最后一根棍子。这并不能保证你的程序能正常工作,但我认为你应该尝试一些不同的测试用例。例如,如果您给它假设人类玩家会输的情况,看看 AI 会怎么做。

关于java - 使用 Minimax 算法的 NIM 游戏和 AI 玩家 - AI 会输棋,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32773102/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com