我想开发一个机器人,该机器人每次都能赢得 21-计数游戏/ NIM-游戏。
规则:以下是游戏规则:
策略:如果您知道正确的策略,如何获胜?
继续,如果您说12获胜
如果您说9,您就赢了,
我的问题:我想使用能够击败用户的JavaScript创建机器人。
let _ = function(call, int) {
setTimeout(call, int)
}
class game {
constructor() {
this.number = 1;
}
user(val) {
console.log(`Userinput: +${val}`)
for (let i=0; i<val; i++)
console.log(`number: ${this.number++}`)
this.checkWin("bot")
console.log("\n\n\n")
this.bot()
}
bot() {
let val = (this.number === 3) ? 3 : parseInt(Math.random()*2)+1
console.log(`Botinput: +${val}`)
for (let i=0; i<val; i++)
console.log(`number: ${this.number++}`)
this.checkWin("user")
console.log("\n\n\n")
}
checkWin(looser) {
if (this.number >= 21) {
console.log(`${looser} lost the game.`);
}
}
}
let instance = new game()
_(function() {
instance.user(3)
},0)
_(function() {
instance.user(2)
},100)
_(function() {
instance.user(3)
},200)
_(function() {
instance.user(3)
},300)
_(function() {
instance.user(1)
},400)
注意:我尚未完成开发,但显然存在一些问题。如果有人能够帮助我查找/修复它们,我将不胜感激。
答案 0 :(得分:1)
要解决Nim游戏,我们需要计算位数:
以此类推...
很容易看出,它在重复。这样我们就可以这样计算出木材(n
是当前状态):3 - (n + 2) % 4
。或广义地说,如果我们最多可以计数x
个数字,而输掉的数字是y
:我们想在z
上加上y
,这样(y + z) % (x + 1) = x
然后公式为x - (n + z) % (x + 1)
。我们也可以说y % (x + 1) + z = x
(为了找到最小的非负z
,另一个公式对z
具有无限数量的解),所以z = x - y % (x + 1)
。>
因此,如果状态的零位数不为0,则获胜举动就是进入数字为0的下一个丢失状态的获胜举动。事实证明,获胜举动(要计数的数字个数)与该位数完全相等。
值得注意的是,21表示说20的状态,而21本身还没有说。
当我们处理多个实例时,这变得很有意思,例如在多个堆栈中将编号从1到21的纸牌放在其中,您可以在堆栈中抽出1至3的最低纸牌。拿到最后一张卡的人输了。在这里,我们可以对所有堆栈的乘积进行异或运算,如果为0,则我们处于亏损状态,否则将有获胜的举动。