Python聪明的尼姆游戏(人机对战)

验目的:

(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()

运行结果: 

  • 8
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值