经典趣味24点游戏程序设计(python)
一、游戏玩法介绍:
24点游戏是儿时玩的主要益智类游戏之一,玩法为:从一副扑克中抽取4张牌,对4张牌使用加减乘除中的任何方法,使计算结果为24。例如,2,3,4,6,通过( ( ( 4 + 6 ) - 2 ) * 3 ) = 24,最快算出24者剩。
二、设计思路:
由于设计到了表达式,很自然的想到了是否可以使用表达式树来设计程序。本程序的确使用了表达式树,也是程序最关键的环节。简要概括为:先列出所有表达式的可能性,然后运用表达式树计算表达式的值。程序中大量的运用了递归,各个递归式不是很复杂,大家耐心看看,应该是能看懂的
表达式树:
表达式树的所有叶子节点均为操作数(operand),其他节点为运算符(operator)。由于本例中都是二元运算,所以表达式树是二叉树。下图就是一个表达式树

具体步骤:
1、遍历所有表达式的可能情况
遍历分为两部分,一部分遍历出操作数的所有可能,然后是运算符的所有可能。全排列的计算采用了递归的思想
#返回一个列表的全排列的列表集合
def list_result(l):
if len(l) == 1:
return [l]
all_result = []
for index,item in enumerate(l):
r = list_result(l[0:index] + l[index+1:])
map(lambda x : x.append(item),r)
all_result.extend(r)
return all_result
2、根据传入的表达式的值,构造表达式树
由于表达式树的特点,所有操作数均为叶子节点,操作符为非叶子节点,而一个表达式(例如( ( ( 6 + 4 ) - 2 ) * 3 ) = 24) 只有3个运算符,即一颗表达式树只有3个非叶子节点。所以树的形状只有两种可能,就直接写死了

#树节点
class Node: def __init__(self, val):
self.val = val
self.left = None
self.right = None
def one_expression_tree(operators, operands):
root_node = Node(operators[0])
operator1 = Node(operators[1])
operator2 = Node(operators[2])
operand0 = Node(operands[0])
operand1 = Node(operands[1])
operand2 = Node(operands[2])
operand3 = Node(operands[3])
root_node.left = operator1
root_node.right =operand0
operator1.left = operator2
operator1.right = operand1
operator2.left = operand2
operator2.right = operand3
return root_node def two_expression_tree(operators, operands):
root_node = Node(operators[0])
operator1 = Node(operators[1])
operator2 = Node(operators[2])
operand0 = Node(operands[0])
operand1 = Node(operands[1])
operand2 = Node(operands[2])
operand3 = Node(operands[3])
root_node.left = operator1
root_node.right =operator2
operator1.left = operand0
operator1.right = operand1
operator2.left = operand2
operator2.right = operand3
return root_node
3、计算表达式树的值
也运用了递归
#根据两个数和一个符号,计算值
def cal(a, b, operator):
return operator == '+' and float(a) + float(b) or operator == '-' and float(a) - float(b) or operator == '*' and float(a) * float(b) or operator == '÷' and float(a)/float(b) def cal_tree(node):
if node.left is None:
return node.val
return cal(cal_tree(node.left), cal_tree(node.right), node.val)
4、输出所有可能的表达式
还是运用了递归
def print_expression_tree(root):
print_node(root)
print ' = 24' def print_node(node):
if node is None :
return
if node.left is None and node.right is None:
print node.val,
else:
print '(',
print_node(node.left)
print node.val,
print_node(node.right)
print ')',
#print ' ( %s %s %s ) ' % (print_node(node.left), node.val, print_node(node.right)),
5、输出结果

三、所有源码
#coding:utf-8
from __future__ import division from Node import Node def calculate(nums):
nums_possible = list_result(nums)
operators_possible = list_result(['+','-','*','÷'])
goods_noods = []
for nums in nums_possible:
for op in operators_possible:
node = one_expression_tree(op, nums)
if cal_tree(node) == 24:
goods_noods.append(node)
node = two_expression_tree(op, nums)
if cal_tree(node) == 24:
goods_noods.append(node)
map(lambda node: print_expression_tree(node), goods_noods) def cal_tree(node):
if node.left is None:
return node.val
return cal(cal_tree(node.left), cal_tree(node.right), node.val) #根据两个数和一个符号,计算值
def cal(a, b, operator):
return operator == '+' and float(a) + float(b) or operator == '-' and float(a) - float(b) or operator == '*' and float(a) * float(b) or operator == '÷' and float(a)/float(b) def one_expression_tree(operators, operands):
root_node = Node(operators[0])
operator1 = Node(operators[1])
operator2 = Node(operators[2])
operand0 = Node(operands[0])
operand1 = Node(operands[1])
operand2 = Node(operands[2])
operand3 = Node(operands[3])
root_node.left = operator1
root_node.right =operand0
operator1.left = operator2
operator1.right = operand1
operator2.left = operand2
operator2.right = operand3
return root_node def two_expression_tree(operators, operands):
root_node = Node(operators[0])
operator1 = Node(operators[1])
operator2 = Node(operators[2])
operand0 = Node(operands[0])
operand1 = Node(operands[1])
operand2 = Node(operands[2])
operand3 = Node(operands[3])
root_node.left = operator1
root_node.right =operator2
operator1.left = operand0
operator1.right = operand1
operator2.left = operand2
operator2.right = operand3
return root_node #返回一个列表的全排列的列表集合
def list_result(l):
if len(l) == 1:
return [l]
all_result = []
for index,item in enumerate(l):
r = list_result(l[0:index] + l[index+1:])
map(lambda x : x.append(item),r)
all_result.extend(r)
return all_result def print_expression_tree(root):
print_node(root)
print ' = 24' def print_node(node):
if node is None :
return
if node.left is None and node.right is None:
print node.val,
else:
print '(',
print_node(node.left)
print node.val,
print_node(node.right)
print ')', if __name__ == '__main__':
calculate([2,3,4,6])
经典趣味24点游戏程序设计(python)的更多相关文章
- 用python代替人脑运算24点游戏
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:老方玩编程 PS:如有需要Python学习资料的小伙伴可以加点击下方链 ...
- 《HTML5经典坦克大战》游戏(代码)
前几天粗略地学了HTML5,然后就用它写了一个<经典坦克大战>游戏. 现在想分享一下我写的代码,写得不好请大家多多指教. 给大家推荐一个网站,这个网站是为大学生而做,为方便学习编程的同学而 ...
- php实现 24点游戏算法
php实现 24点游戏算法 一.总结 一句话总结:把多元运算转化为两元运算,先从四个数中取出两个数进行运算,然后把运算结果和第三个数进行运算,再把结果与第四个数进行运算.在求表达式的过程中,最难处理的 ...
- cdoj 1252 24点游戏 dfs
24点游戏 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/problem/show/1252 Descr ...
- 24点游戏&&速算24点(dfs)
24点游戏 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Submit Sta ...
- 24点游戏详细截图介绍以及原型、Alpha、Beta对比
原型设计 图片展示 功能与界面设计 1.登录注册 2.手机号验证 3.24点游戏 4.粉色系女生界面 Alpha 图片展示 功能与界面设计 1.24点游戏 2.背景音乐 3.可查看多种可能的答案 4. ...
- 「JavaScript」手起刀落-一起来写经典的贪吃蛇游戏
回味 小时候玩的经典贪吃蛇游戏我们印象仍然深刻,谋划了几天,小时候喜欢玩的游戏,长大了终于有能力把他做出来(从来都没有通关过,不知道自己写的程序,是不是能通关了...),好了,闲话不多谈,先来看一下效 ...
- C#俄罗斯方块小游戏程序设计与简单实现
C#俄罗斯方块小游戏程序设计与简单实现 相信90后或者80后都玩过这款小游戏,一直想干一票,琢磨一下,但又不太懂,于是网上搜集修改就有了以下效果!bug较多,多多包涵! 1.效果展示 2.实现方法 参 ...
- 【Nodejs】“快算24”扑克牌游戏算法
算24是一款扑克牌游戏,它的游戏方式是把四张牌的牌面数值通过四则运算得到结果24,四张牌必须仅用一次.这是一种挺好的锻炼孩子算数能力的扑克牌游戏. 各地玩法还有点差别,有的只算1-10,其它抽出来:有 ...
随机推荐
- iOS证书失效
iOS证书突然失效 今早上班打包直接报错,错误如图 根据错误信息到“钥匙串”里面看了一下证书,证书都莫名其妙的失效了,昨天还是好好的. 重新去钥匙串从证颁发中心获取证书,然后登陆开发者账号重新申请证书 ...
- python 读写、创建 文件
python中对文件.文件夹(文件操作函数)的操作需要涉及到os模块和shutil模块. 得到当前工作目录,即当前Python脚本工作的目录路径: os.getcwd() 返回指定目录下的所有文件和目 ...
- android之旋转的刻度盘
这是在学习android的Canvas绘图技巧时做的一个实例.主要用的核心方法就是canvas.save,canvas.rotate, canvas.translate以及canvas.restore ...
- springMVC请求流程详解
SpringMVC框架是一个基于请求驱动的Web框架,并且使用了'前端控制器'模型来进行设计,再根据'请求映射规则'分发给相应的页面控制器进行处理. (一)整体流程 具体步骤: 1. 首先用户发送请 ...
- MFC 窗口分割
动态分割窗口: BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) { , , CSize(, ...
- JasperReports教程:Report Data Sources
原文地址:http://www.tutorialspoint.com/jasper_reports/jasper_report_data_sources.htm Datasources是一个结构化的数 ...
- 免费的无次数限制的各类API接口(2)
之前整理过一些聚合数据上的免费API(各类免费的API接口分享,无限次),这次还有一些其他的进行了整理,主要是聚合数据上和API Store上的一些,还有一些其他的. 聚合数据提供30大类,160种以 ...
- Programming ActionScript 3.0 for Flash
http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7ec ...
- [转]Performance Analysis Using SQL Server 2008 Activity Monitor Tool
本文转自:https://www.mssqltips.com/sqlservertip/1917/performance-analysis-using-sql-server-2008-activity ...
- POJ 3304 Segments --枚举,几何
题意: 给n条线段,问有没有一条直线,是每条线段到这条直线上的投影有一个公共点. 解法: 有公共点说明有一条这条直线的垂线过所有线段,要找一条直线过所有线段,等价于从所有线段中任选两端点形成的直线存在 ...