最近迷上了24点数字游戏,让四个数字在脑子里随意碰撞,结合,然后检查最后的结果,然后再碰撞,结合,检查,不断重复…到最后总会有一种方法让这四个数字乖乖的等于24。当然,前提是这四个数字得来自正规的24点游戏库,因为不是随便四个数字都能得到24点的。
在手机上的游戏软件上玩了数十关之后,我突发奇想,为何不把这活交给程序做做呢?由于最近一直在学习Python,就打算用Python玩玩这个游戏,看看结果如何。
我本着先怼出来为敬的原则(就是不考虑算法,不考虑效率,不考虑计算时间等等,先出结果再说)自然而然想到的就是穷举。一共四个数字,外加三个运算符(将四个数字整合成一个数字只须要三个运算符号即可,实际用到的运算符号有四个:加、减、乘、除),这些都是小整数,计算机穷举其实也费不了多大劲。
既然要穷举,那就要考虑到所有的情况。下面上一个“24点游戏万能公式”:
●代表任一运算符。我的思路是先给这四个数字一个全排列,也就是24种情况,然后每一个运算符来一个遍历,也就是64种情况,这样算来最多只要循环24x64次就能得到结果。
思路有了,然后开始编程。对于运算符号,我用的是operator模块中的add,sub,mul 和 truediv 函数,因为基于Python中所有函数都是一等对象的理念,把这四个函数放进一个列表里之后很容易实现遍历。实现全排列则用的是 itertools 模块中的 permutations 函数。好了,废话不多说,直接上程序:
from operator import add,sub,mul,truediv as div
from itertools import permutations
def pts_24(list_int_4):
operator_4 = [add,sub,mul,div]
ops = ['+','-','x','/']
for ls in permutations(list_int_4,4):
for oprt_1 in operator_4:
for oprt_2 in operator_4:
for oprt_3 in operator_4:
try:
result = oprt_1(ls[0],oprt_2(ls[1],oprt_3(ls[2],ls[3])))
except ZeroDivisionError: #除数是零的情况在这种全面的遍历下似乎不可避免
pass #为了程序流畅以及输出美观,所以跳过
#PS:反正这种情况肯定不是我们想要的结果
if result == 24:
print('Done')
i = operator_4.index(oprt_1)
j = operator_4.index(oprt_2)
k = operator_4.index(oprt_3)
bra1='' #以下包括两个if语句是针对运算优先级做的输出格式上的优化
bra2=''
ket1=''
ket2=''
if i>=1 and j<2 or i==3:
bra1 = '('
ket1 = ')'
if j>=1 and k<2 or j==3:
bra2 = '('
ket2 = ')'
return (str(ls[0])+ops[i]+bra1+str(ls[1])+ops[j]+
bra2+str(ls[2])+ops[k]+str(ls[3])+ket2+ket1)
return("These four numbers can not be calculated to 24")
while True:
str_4 = input("Please input 4 integers separated by ' ': ")
if str_4 == 'q':
break
list_4 = str_4.split()
list_int_4 = [int(i) for i in list_4]
print(pts_24(list_int_4))
程序写好后,我先上了一组 ‘6666’ 测试了一下:
Please input 4 integers separated by ' ': 6 6 6 6
Done
6+6+6+6
果然很顺利。我又打开24点游戏软件,上了一组“专业测试”,也都能一一通过。至此,我这个“先怼出来为敬的版本”算是大功告成了。
Please input 4 integers separated by ' ': 4 5 7 9
Done
5-(9-4x7)
Please input 4 integers separated by ' ': 4 10 8 10
Done
4-10x(8-10)
Please input 4 integers separated by ' ': 8 8 8 6
Done
8+8x(8-6)
Please input 4 integers separated by ' ': 99 99 99 99
These four numbers can not be calculated to 24
Please input 4 integers separated by ' ': 1 1 1 1
These four numbers can not be calculated to 24
最后两种例外情况也都确证了不能找到使他们运算得到24的结果,但是到这里有人可能会说,慢着,你看这:(1+1+1+1)! 不就正好等于24吗?好啊,少侠有如此眼力,我的程序自然甘拜下风,所以我就只好在程序里加上一行这个了:(滑稽)
if A==B==C==D==1 or A==B==C==D==0:
print('(A!+B!+C!+D!)! = 24') #考虑到0,每个数字后面都加了阶乘
在写这个程序的过程中,中间也出了不少问题。我程序中计算的核心代码行:
result = oprt_1(ls[0],oprt_2(ls[1],oprt_3(ls[2],ls[3])))
运算的优先级是从后往前的,而不管运算符号如何,这也算是遍历(便利)中的一点小小不足吧。但是后面用上小括号,这个问题便迎刃而解了。这其中还有很多细节上的问题,我就不一一赘述了,对程序员来说,文字不重要,代码才是最重要的。
再会!