实验目的:
(1)理解尼姆游戏规则。
(2)了解多个函数定义与调用。
(3)理解并熟练运用 while 循环。
(4)理解带 else 子句的循环结构执行流程。
(5)理解循环语句中的 break 语句的作用。
(6)了解使用循环和异常处理结构对用户输入进行约束的用法。
游戏介绍:
分为两种模式:
傻瓜模式(silly):两个玩家轮流从一堆物品中拿走一部分。在每一步中,玩家可以自由选择拿走多少物品,但是必须至少拿走一个并且最多只能拿走一半物品,然后轮到下一个玩家。拿走最后一个物品的玩家输掉游戏。
聪明模式(samrt):在聪明模式中,除傻瓜模式的规则外,每次到计算机拿走一部分时,计算机每次拿走足够多的物品使得堆的大小是 2 的幂次方减 1——也就是 3,7,15,31 或 63。除了堆的大小已经是 2 的幂次方减 1,在其他情况下这样走都是符合游戏规则的。在那种情况下,计算机就按游戏规则随机拿走一些。
傻瓜模式(silly):
# silly版本为在1到n/2之间随机取一个数,用random.randint(a,b)函数来随机选取
# 因为a,b参数类型为int,需要math.floor()函数取参数b的整数部分,不用math,round()四舍五入函数,因为random.randint(a,b)函数随机会选取[a,b]区间的数,包括b
def silly(n): # silly版本随机取数
if n <= 3:
return 1
return random.randint(1, math.floor(n / 2))
聪明模式(samrt):
def smart(n): # smart版本自动选择最佳数
# n==1会使下方floor(n / 2)取值为0,从而randint()函数会报错
# n=2或者3时,返回1,其实和下面的return randint(1, floor(n / 2))语句的结果一样,上面直接返回1,比下面调用内置函数快
if n <= 3:
return 1
x = 0
while True:
if pow(2, x) <= n < pow(2, x + 1):
break
x += 1
num = n - pow(2, x) + 1
if 1 <= num <= n / 2:
return num
else: # 若最佳数不在范围内,则选取随机数
return random.randint(1, math.floor(n / 2))
游戏逻辑:
def game(n, choose):
if choose == 'silly':
print("你选择了傻瓜难度")
f = silly # 函数指针选择silly函数
else:
print("你选择了地狱难度")
f = smart # 函数指针选择smart函数
while True:
print("现在共有" + str(n) + "个棋子")
nim = f(n)
print("Nim拿走了" + str(nim) + "个")
n -= nim
print("现在共有" + str(n) + "个棋子")
if n == 0:
print("你赢了!")
return
try:
you = int(input("该你了,你要拿走:"))
except (ValueError, UnboundLocalError):
you = error('取数')
while True:
if 1 <= you <= n / 2 or n == 1:
print("你拿走了" + str(you) + "个")
break
if you < 1:
print("至少要拿走一个棋子!")
else:
print("最多只能拿走一半的棋子!")
try:
you = int(input("请重新输入,你要拿走:"))
except (ValueError, UnboundLocalError):
you = error('取数')
n -= you
if n == 0:
print("现在共有" + str(n) + "个棋子")
print("你输了!")
return
异常处理:
def error(b):
while True:
print("输入格式有误!")
try:
if b == '取数':
you = int(input("请重新输入,你要拿走:"))
else:
you = int(input("请重新输入棋子的总数:"))
except (ValueError, UnboundLocalError):
pass
else:
break
return you
主函数:
def main():
try:
num = int(input("请输入棋子的总数: "))
except ValueError:
num = error('总数')
finally:
choose = input("请输入你要选择的难度('silly' or 'smart'): ")
game(num, choose)
源代码:
import random
import math
def silly(n): # silly版本随机取数
if n <= 3:
return 1
return random.randint(1, math.floor(n / 2))
def smart(n): # smart版本自动选择最佳数
if n <= 3:
return 1
x = 0
while True:
if pow(2, x) <= n < pow(2, x + 1):
break
x += 1
num = n - pow(2, x) + 1
if 1 <= num <= n / 2:
return num
else: # 若最佳数不在范围内,则选取随机数
return random.randint(1, math.floor(n / 2))
def game(n, choose):
if choose == 'silly':
print("你选择了傻瓜难度")
f = silly # 函数指针选择silly函数
else:
print("你选择了地狱难度")
f = smart # 函数指针选择smart函数
while True:
print("现在共有" + str(n) + "个棋子")
nim = f(n)
print("Nim拿走了" + str(nim) + "个")
n -= nim
print("现在共有" + str(n) + "个棋子")
if n == 0:
print("你赢了!")
return
try:
you = int(input("该你了,你要拿走:"))
except (ValueError, UnboundLocalError):
you = error('取数')
while True:
if 1 <= you <= n / 2 or n == 1:
print("你拿走了" + str(you) + "个")
break
if you < 1:
print("至少要拿走一个棋子!")
else:
print("最多只能拿走一半的棋子!")
try:
you = int(input("请重新输入,你要拿走:"))
except (ValueError, UnboundLocalError):
you = error('取数')
n -= you
if n == 0:
print("现在共有" + str(n) + "个棋子")
print("你输了!")
return
def error(b):
while True:
print("输入格式有误!")
try:
if b == '取数':
you = int(input("请重新输入,你要拿走:"))
else:
you = int(input("请重新输入棋子的总数:"))
except (ValueError, UnboundLocalError):
pass
else:
break
return you
def main():
try:
num = int(input("请输入棋子的总数: "))
except ValueError:
num = error('总数')
finally:
choose = input("请输入你要选择的难度('silly' or 'smart'): ")
game(num, choose)
main()
运行结果: