Python 尼姆游戏(人机对战)

设计和实现尼姆游戏(人机对战)

实验目的

  • 理解尼姆游戏规则
  • 了解多个函数的定义与调用
  • 理解并熟练运行while循环
  • 理解带else子句的循环结构执行流程
  • 理解循环语句的break语句的作用
  • 了解使用循环和异常处理结构对用户输入进行约束的用法
  • 养成时刻注意各级代码缩进级别的习惯
  • 实验内容

实验内容

  • 尼姆游戏是一个著名的游戏,有很多变种玩法。两个玩家轮流从一堆物品中拿走一部分。在每一步中,玩家可以自由选择拿走多少物品,但是必须至少拿走一个并且最多只能拿走一半物品,然后轮到下一个玩家。拿走最后一个物品的玩家输掉游戏。
  • 在聪明模式中,计算机每次拿走一定数量的物品使得堆的大小是2的幂次方减1—也就是3,7,15,31,63等。如果有一定数量的剩余物品,计算就随机拿走一些。
  • 编写程序,模拟聪明版及非聪明版的尼姆游戏。并进行两种的比较及分析。给出聪明版比非聪明版的胜算结论。
n目的数操作数xn目的数操作数x
11失败17152
21118153
3*ran19154
43120155
53221156
63322157
7*ran23158
87124159
972251510
1073261511
1174271512
1275281513
1376291514
1477301515
15*ran31*ran
1615132311
'''模拟聪明版尼姆游戏
一人进行“聪明操作”
另一人随机生成数'''
import math
import random

def smart(n):
    logn = int(math.log(n, 2))
    if n == math.pow(2, logn + 1) - 1:
        return random.randint(1,int(n/2))
    return n - int(math.pow(2, logn)) + 1

def playn(n):
    if n <= 3:
        return 1
    else:
        return random.randint(1, int(n/2))

sumnum = int(input("请输入总和:"))
while sumnum > 0:
    tmp = sumnum
    player_smart = smart(sumnum)
    sumnum = sumnum - player_smart
    tmp2 = sumnum
    if not sumnum:
        print("player_smart失败")
    player_random = playn(sumnum)
    sumnum = sumnum - player_random

    if not sumnum:
        print("player_random失败")
    print("原本总和{3},聪明玩家出数{1},聪明玩家出数后{4},随机玩家出数{2},当前剩余{0}".format(sumnum, player_smart, player_random,tmp,tmp2))


一方采取聪明算法时,获胜概率远远大于随机出数
   请输入总和:123
原本总和123,聪明玩家出数60,聪明玩家出数后63,随机玩家出数7,当前剩余56
原本总和56,聪明玩家出数25,聪明玩家出数后31,随机玩家出数8,当前剩余23
原本总和23,聪明玩家出数8,聪明玩家出数后15,随机玩家出数1,当前剩余14
原本总和14,聪明玩家出数7,聪明玩家出数后7,随机玩家出数3,当前剩余4
原本总和4,聪明玩家出数1,聪明玩家出数后3,随机玩家出数1,当前剩余2
player_random失败
原本总和2,聪明玩家出数1,聪明玩家出数后1,随机玩家出数1,当前剩余0


    请输入总和:263
原本总和263,聪明玩家出数8,聪明玩家出数后255,随机玩家出数94,当前剩余161
原本总和161,聪明玩家出数34,聪明玩家出数后127,随机玩家出数21,当前剩余106
原本总和106,聪明玩家出数43,聪明玩家出数后63,随机玩家出数26,当前剩余37
原本总和37,聪明玩家出数6,聪明玩家出数后31,随机玩家出数10,当前剩余21
原本总和21,聪明玩家出数6,聪明玩家出数后15,随机玩家出数7,当前剩余8
原本总和8,聪明玩家出数1,聪明玩家出数后7,随机玩家出数3,当前剩余4
原本总和4,聪明玩家出数1,聪明玩家出数后3,随机玩家出数1,当前剩余2
player_random失败
原本总和2,聪明玩家出数1,聪明玩家出数后1,随机玩家出数1,当前剩余0

请输入总和:1025
原本总和1025,聪明玩家出数2,聪明玩家出数后1023,随机玩家出数122,当前剩余901
原本总和901,聪明玩家出数390,聪明玩家出数后511,随机玩家出数216,当前剩余295
原本总和295,聪明玩家出数40,聪明玩家出数后255,随机玩家出数29,当前剩余226
原本总和226,聪明玩家出数99,聪明玩家出数后127,随机玩家出数32,当前剩余95
原本总和95,聪明玩家出数32,聪明玩家出数后63,随机玩家出数27,当前剩余36
原本总和36,聪明玩家出数5,聪明玩家出数后31,随机玩家出数2,当前剩余29
原本总和29,聪明玩家出数14,聪明玩家出数后15,随机玩家出数2,当前剩余13
原本总和13,聪明玩家出数6,聪明玩家出数后7,随机玩家出数2,当前剩余5
原本总和5,聪明玩家出数2,聪明玩家出数后3,随机玩家出数1,当前剩余2
player_random失败
原本总和2,聪明玩家出数1,聪明玩家出数后1,随机玩家出数1,当前剩余0
'''常规方法'''
import random
def playn(n):
    if n <=3:
        return 1
    else:
        return random.randint(1, int(n/2))
sumnum = int(input("请输入总和"))

while sumnum > 0:
    tmp = sumnum
    player1 = playn(sumnum)
    sumnum = sumnum - player1
    if not sumnum:
        print("player1失败")
    player2 = playn(sumnum)
    sumnum = sumnum - player2

    if not sumnum:
        print("player2失败")
    print("原本总和{3}当前剩余{0},玩家1出数{1},玩家2出数{2}".format(sumnum, player1, player2,tmp))

双方都随机出数时,获胜概率是相等的
请输入总和123
原本总和123当前剩余51,玩家1出数34,玩家2出数38
原本总和51当前剩余29,玩家1出数13,玩家2出数9
原本总和29当前剩余20,玩家1出数6,玩家2出数3
原本总和20当前剩余8,玩家1出数4,玩家2出数8
原本总和8当前剩余5,玩家1出数1,玩家2出数2
原本总和5当前剩余2,玩家1出数2,玩家2出数1
player2失败
原本总和2当前剩余0,玩家1出数1,玩家2出数1

请输入总和100
原本总和100当前剩余56,玩家1出数14,玩家2出数30
原本总和56当前剩余28,玩家1出数18,玩家2出数10
原本总和28当前剩余22,玩家1出数5,玩家2出数1
原本总和22当前剩余9,玩家1出数11,玩家2出数2
原本总和9当前剩余3,玩家1出数3,玩家2出数3
原本总和3当前剩余1,玩家1出数1,玩家2出数1
player1失败
原本总和1当前剩余-1,玩家1出数1,玩家2出数1
posted @ 2021-05-21 21:44  SKPrimin  阅读(704)  评论(0编辑  收藏  举报