21 счет игры (как игра NIM) - PullRequest
0 голосов
/ 15 сентября 2018

Я бы хотел разработать бота , способного выигрывать 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 голосов
/ 16 сентября 2018

Чтобы решить игру NIM, мы рассчитываем Nimbers:

  1. состояние проигрыша имеет номер 0
  2. Остальная часть nimbers рассчитывается путем просмотра всех достижимых состояний и взятия mex (минимального эксклюзива), который является наименьшим отсутствующим числом в последовательности 0, 1, 2, 3, ...
  • nimber (21) = 0
  • nimber (20) = 1, только 0 может быть достигнуто, поэтому 1 - это мекс
  • nimber (19) = 2, 0 и 1 могут быть достигнуты за один ход, поэтому мекс равен 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).

Таким образом, если nimber состояния не равен 0, выигрышный ход - это переход в следующее проигрышное состояние с nimber 0. Как оказалось, выигрышный ход (сколько чисел считать) в точности равен nimber .

Важно отметить, что 21 обозначает состояние, когда было сказано 20, а 21 еще не было сказано.

Это становится интересным, когда мы играем с несколькими экземплярами, как, например, карты с нумерацией от 1 до 21 в нескольких стопках, где вы можете взять от 1 до 3 самых младших карт в стопке. Тот, кто берет самую последнюю карту, проигрывает. Здесь мы можем просто переписать число всех стеков, если оно равно 0, мы находимся в проигрышном состоянии, в противном случае выигрышный ход.

...