python24点游戏

24点游戏python解法

一. 游戏介绍

棋牌类益智游戏,要求四个数字运算结果等于二十四,一起来玩玩吧!这个游戏用扑克牌更容易来开展。拿一副牌,抽去大小王后(初练也可以把J/Q/K/大小王也拿去),剩下1~10这40张牌(以下用1代替A)。任意抽取4张牌(称为牌组),用加、减、乘、除(可加括号,高级玩家也可用乘方开方与阶乘运算)把牌面上的数算成24。每张牌必须用且只能用一次。如抽出的牌是3、8、8、9,那么算式为(9-8)×8×3=24

二,问题分析

对于此类问题,最先考虑到的是穷举算法,也就是在计算机的算力范围内,通过每个结果的穷举,最终得除整个问题集合。
首先,对于只有数字,那么它的全排列有4!= 24种可能的排列情况。
然后是在其中插入运算符,由于只有三个运算符,那么三个运算符全排列的话也是 43 = 64种表示方法,两者再任意组合,那么就有了1536种计算结果。再加上运算过程中的括号,分别有一个括号两个括号两种分类,其中一个括号能有5种方式,分别是(a+b)+c+d,a+(b+c)+d,a+b+(c+d),(a+b+c)+d,a+(b+c+d) 两个括号能有1种方式,(a+b)+ (c+d),故总的只有一种。因此加起来是六种方法,总的算出来有9216种结果,因此完全可以靠穷举来获得结果。

三,主要算法

主要的算法就是表达式的计算,最开始想利用逆波兰表达式通过入栈出栈进行计算得到表达式的结果,但是通过查找资料发现,python种有一个表达式的计算函数,可以直接实现字符串表达式的计算,比如eval(‘8+9+10+11’) = 38,所以就不需要通过复杂的入栈出栈的操作来计算表达式的值。

次要的算法就是构建全排列的数字和字符表达式集合,python种可以通过iteratools来实现全排列的构建和使用,也可以使用穷举的办法来实现全排列的构建。本次程序使用循环来实现排列的构建。

四,具体步骤

初始化操作:
数据结构初始化:

    func = []
    func2 = []
    game = []
    result = []
    result2 = []
    result3 = []
    result4 = []
    evaluate = []
    # 产生随机数
    # nums = [randint(1,13) for i in range(4)]
    # 运算符集合
    operations = ['+','-','*','/']

游戏初始化

def gameInit():
    nums = [randint(1, 13) for i in range(4)]
    # 防止得出的数没有结果
    while gameStart(nums) == []:
        nums = [randint(1, 13) for i in range(4)]
    return nums

1,数字全排列

以每一种的排列方式作为一个列表,然后将其输入一个新的列表,也就是每一种数字的排列作为一个数字列表,然后直接用数字列表来操作。

# 数字全排列可能出现的组合
    for i in range(4):
        for j in range(4) :
            for k in range(4):
                for l in range(4):
                    if i != j and i != k and i != l and j != k and j != l and k != l:
                        func.append([nums[i],nums[j],nums[k],nums[l]])

2.运算符排列

同样的原理,但是基于运算符能够重复,于是乎就不用去限定下表是否相等,直接排列存在func2[]列表种就行

# 运算符全排列可能出现的组合
    for i in range(4):
        for j in range(4):
            for k in range(4):
                func2.append([operations[i],operations[j],operations[k]])

3.数字排列与运算符排列的两者相互混合

# 两者以一定的规则组合
    for num in func:
        # print(type(num))
        for ope in func2:
            num1 = num.copy()
            num1.insert(1,ope[0])
            num1.insert(3,ope[1])
            num1.insert(5,ope[2])
            result.append(num1)

4.加入一对括号的的排列

 # 括两个数的括号与表达式的介结合
    for i in range(0,5,2):
        for res in result:
            rescopy = res.copy()
            rescopy.insert(i,'(')
            rescopy.insert(i+4,')')
            result2.append(rescopy)

    # 括三个数的括号与表达式结合
    for  i in range(0,3,2):
        for res in result:
            rescopy = res.copy()
            rescopy.insert(i,'(')
            rescopy.insert(i+6,')')
            result3.append(rescopy)

5.加入两个括号的排列

 # 两个括号系列
    for res in  result:
        rescopy = res.copy()
        rescopy.insert(0,'(')
        rescopy.insert(4,')')
        rescopy.insert(6,'(')
        rescopy.insert(10,')')
        result4.append(rescopy)

6.综合整合

 # 合并并转化成字符串
    result = result2 + result3 + result4
    for res in result:
        res = [str(i) for i in res]
        # print(str(res))
        evaluate.append(''.join(res))


    # 计算表达式结果
    for eva in evaluate:
        try:
            if eval(eva) == 24:
                game.append(eva)
        except:
            pass

7.游戏的构建

# 正式游戏
def gameing():
    point = 0
    life = 3
    nums = gameInit()
    print("给出的四张牌为:" + str(nums))
    games = gameStart(nums)
    while life > 0:
        start = time.time()   # 获取开始时间
        game = input("请在120秒内输入你的运算式:")
        end = time.time() - start   # 获取结束时间
        if end > 120:               # 限制时间
            print("您已超时!")
            life = life - 1
            continue
        gamecopy = game
        gamecopy = gamecopy.replace('J','11')
        # print(gamecopy)
        gamecopy = gamecopy.replace('Q','12')
        # print(gamecopy)
        gamecopy = gamecopy.replace('k','13')
        # print(gamecopy)
        if gamecopy in games:
            print("正确,进入下一题!")
            point = point + 20    # 加分
            nums = gameInit()    # 获取新的组合
            games = gameStart(nums)
        else:
            print("结果不正确!")
            life = life - 1
            nums = gameInit()    # 获取新的组合
            games = gameStart(nums)

    print("游戏结束,你的分数为:" + str(point))
    name = input("请输入你的名字,以便我们存入高分榜单")
    with open('TopList.txt','a') as file:
        file.write(name + str(point) + '\n')

五,游戏优化

1.全排列的产生的优化

利用itertools优化全排列的四个循环

import itertools
nums = [1,2,3,4]
alllist = []
for each_list in itertools.permutations(nums,4):
    str_list = [str(num) for num  in each_list]
    alllist.append(str_list)
print(alllist)

结果如下:
测试结果1

2.构造数字和运算符的混合表达式的优化

利用zip函数来实现两者的两两混合,其中定义的两个函数是用来获取所有的数字数列和操作符列表,可以在实际使用过程中替换。

def get_allNumList():
    return [['1','2','3','4'],['2','3','4','5']]

def get_allOpeList():
    return [['+','-','*']]


num_and_list_mixs = []
for str_list in get_allNumList():
    for op_list in get_allOpeList():
        op_list.append('')
        num_and_list_mix = zip(str_list,op_list)
        num_and_list_mixs.append(num_and_list_mix)

print(num_and_list_mixs)

最终测试结果:
测试结果

题目总结

解决一个算法问题的过程中,遵循以下规则:

  1. 分析算法问题
  2. 设计实际算法
  3. 算法优化

最后应该从多方面测试。

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值