尼姆游戏(人机对战)-Python

尼姆游戏(人机对战)-Python使用 python 实现尼姆游戏问题 尼姆游戏

大家好,欢迎来到IT知识分享网。

1.实验要求

编写程序设计和实现聪明的尼姆游戏(人机对战)。尼姆游戏是个著名的游戏,有很多变种玩法。两个玩家轮流从一堆物品中拿走一部分。在每一步中,玩家可以自由选择拿走多少物品,但是必须至少拿走一个并且最多只能拿走一半物品,然后轮到下一个玩家。拿走最后一个物品的玩家输掉游戏。

在聪明模式中,计算机每次拿走足够多的物品使得堆的大小是2 的幂次方减1——也就是3,7,15,31 或63。除了堆的大小已经是2 的幂次方减1,在其他情况下这样走都是符合游戏规则的。如果已是2的幂次方减1,计算机就按游戏规则随机拿走一些。

2.实验原理

2.1玩家回合

要确保玩家拿取的数要大于等于1,并且小于等于当前物品数的一半,可以使用while循环来完成。不过如果当前物品数为1时,会进入死循环,所以需要专门考虑:使用if语句来进行判断。拿取后,把更新的物品数返回即可。

其中用到的函数有player_turn。

def player_turn(heap_number): print(f'当前堆的大小为{heap_number},', end='') take_number = 0 while take_number < 1 or take_number > heap_number // 2: take_number = eval(input('请输入你要拿取的数量(至少为1,至多为当前堆大小的一半):')) if heap_number == 1 and take_number == 1: # 边界问题 break return heap_number - take_number

2.2电脑回合

根据传入的参数,来判断当前的模式。

如果是傻瓜模式,就随机拿取[1,当前堆的大小的一半],不过要注意这个区间有可能是非法的,当堆大小为1时,当前堆大小的一半为0,所以非法区间为[1,0]。

如果是聪明模式,就先找到比此时物品数小的最大2的幂次方减1。如果这个2的幂次方减1恰好等于此时的物品数,就进行随机拿取;如果不等于,就拿取*此时物品数-2的幂次方减1*。

记得最后更新一下堆大小(返回当前的物品数)

其中用到的函数有computer_turn。

def computer_turn(heap_number, game_mode): print(f'堆的大小为{heap_number},', end='') if game_mode == 1: # 傻瓜模式:随机拿取 if heap_number > 1: take_number = random.randint(1, heap_number // 2) # 如果heap_number <= 1,那么随机区间非法 else: take_number = 1 print(f'对手拿取了{take_number}个物品,还剩下{heap_number - take_number}个物品。') return heap_number - take_number else: x = 0 while True: # 找到此时比物品数小的 最大的2的幂次方减1 if pow(2, x) <= heap_number: x = x + 1 else: break x = x - 1 if pow(2, x) == heap_number: # 恰好等于物品数 if heap_number > 1: # 如果heap_number <= 1,那么随机区间非法 take_number = random.randint(1, heap_number // 2) else: take_number = 1 print(f'对手拿取了{take_number}个物品,还剩下{heap_number - take_number}个物品。') return heap_number - take_number else: take_number = heap_number - (pow(2, x) - 1) print(f'对手拿取了{take_number}个物品,还剩下{heap_number - take_number}个物品。') return heap_number - take_number

2.3实现交替拿取

仅需定义一个变量now_play,用它来表示当前拿取的是谁,0代表电脑,1代表玩家,然后每有人拿取后,把now_play更新为表示对手的值就行了,这样就可以进行轮流进行拿取物品。

其中用到的函数有change_play。

def change_play(now_play): # 改变玩家回合 if now_play == 0: return 1 return 0

2.4判断游戏结束

仅需判断当前物品数是否为0即可,一个玩家拿取后,如果此时物品数为0,那么游戏就可以结束了,这个玩家输了。

用到的函数有is_over。

def is_over(heap_number): # 判断游戏是否结束 if heap_number == 0: return True else: return False

3.全部代码

import random def game(): heap_number = eval(input('请输入堆的初始大小:')) game_mode = eval(input("请选择游戏模式:1.傻瓜模式 2.聪明模式")) now_play = eval(input('请输入谁先进行拿取:1.自己 0.对手')) # 此时轮到谁进行游戏 while True: if now_play == 0: heap_number = computer_turn(heap_number, game_mode) now_play = change_play(now_play) if is_over(heap_number): print('恭喜你,赢得了比赛!') break else: heap_number = player_turn(heap_number) now_play = change_play(now_play) if is_over(heap_number): print('很可惜呢,希望下一次能胜利!') break def player_turn(heap_number): print(f'当前堆的大小为{heap_number},', end='') take_number = 0 while take_number < 1 or take_number > heap_number // 2: take_number = eval(input('请输入你要拿取的数量(至少为1,至多为当前堆大小的一半):')) if heap_number == 1 and take_number == 1: # 边界问题 break return heap_number - take_number def computer_turn(heap_number, game_mode): print(f'堆的大小为{heap_number},', end='') if game_mode == 1: # 傻瓜模式:随机拿取 if heap_number > 1: take_number = random.randint(1, heap_number // 2) # 如果heap_number <= 1,那么随机区间非法 else: take_number = 1 print(f'对手拿取了{take_number}个物品,还剩下{heap_number - take_number}个物品。') return heap_number - take_number else: x = 0 while True: # 找到此时比物品数小的 最大的2的幂次方减1 if pow(2, x) <= heap_number: x = x + 1 else: break x = x - 1 if pow(2, x) == heap_number: if heap_number > 1: # 如果heap_number <= 1,那么随机区间非法 take_number = random.randint(1, heap_number // 2) else: take_number = 1 print(f'对手拿取了{take_number}个物品,还剩下{heap_number - take_number}个物品。') return heap_number - take_number else: take_number = heap_number - (pow(2, x) - 1) print(f'对手拿取了{take_number}个物品,还剩下{heap_number - take_number}个物品。') return heap_number - take_number def change_play(now_play): # 改变玩家回合 if now_play == 0: return 1 return 0 def is_over(heap_number): # 判断游戏是否结束 if heap_number == 0: return True else: return False if __name__ == '__main__': game() 

4.运行结果

尼姆游戏(人机对战)-Python

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/130689.html

(0)
上一篇 2025-08-13 17:33
下一篇 2025-08-13 17:45

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信