21个计数游戏(例如nim游戏)

时间:2018-09-15 16:33:01

标签: javascript algorithm numbers counting nim-game

我想开发一个机器人,该机器人每次都能赢得 21-计数游戏/ NIM-游戏

规则以下是游戏规则

  • 在游戏中,玩家轮流说出最多3个数字(从1开始并逐渐上升)。
  • 每个人说的数字 21 被淘汰。

策略:如果您知道正确的策略,如何获胜?

  • 继续,如果您说12获胜

  • 如果您说9,您就赢了,

  • 如果您说6,您将获胜,
  • 如果你说3,你赢了
  • 因此,如果您获得第二名,您可以保证说3,并且每次都赢。

我的问题:我想使用能够击败用户的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)

注意:我尚未完成开发,但显然存在一些问题。如果有人能够帮助我查找/修复它们,我将不胜感激。

1 个答案:

答案 0 :(得分:1)

要解决Nim游戏,我们需要计算位数:

  1. 失败状态的数字为0
  2. 通过查看所有可到达的状态并取0、1、2、3,...等序列中最小的缺失数mex(最小排他数)来计算其余木材。
  • nimber(21)= 0
  • nimber(20)= 1,只能达到0,所以1是混合比例
  • nimber(19)= 2、0和1可以在一move之内到达,因此mex为2
  • nimber(18)= 3
  • nimber(17)= 0,因为我们可以达到1到3,所以0是最小的遗漏数字

以此类推...

很容易看出,它在重复。这样我们就可以这样计算出木材(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,则我们处于亏损状态,否则将有获胜的举动。