python 之玩转24点数字游戏

最近迷上了24点数字游戏,让四个数字在脑子里随意碰撞,结合,然后检查最后的结果,然后再碰撞,结合,检查,不断重复…到最后总会有一种方法让这四个数字乖乖的等于24。当然,前提是这四个数字得来自正规的24点游戏库,因为不是随便四个数字都能得到24点的。

在手机上的游戏软件上玩了数十关之后,我突发奇想,为何不把这活交给程序做做呢?由于最近一直在学习Python,就打算用Python玩玩这个游戏,看看结果如何。

我本着先怼出来为敬的原则(就是不考虑算法,不考虑效率,不考虑计算时间等等,先出结果再说)自然而然想到的就是穷举。一共四个数字,外加三个运算符(将四个数字整合成一个数字只须要三个运算符号即可,实际用到的运算符号有四个:加、减、乘、除),这些都是小整数,计算机穷举其实也费不了多大劲。

既然要穷举,那就要考虑到所有的情况。下面上一个“24点游戏万能公式”:
A B C D = 24 A●B●C●D = 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])))

运算的优先级是从后往前的,而不管运算符号如何,这也算是遍历(便利)中的一点小小不足吧。但是后面用上小括号,这个问题便迎刃而解了。这其中还有很多细节上的问题,我就不一一赘述了,对程序员来说,文字不重要,代码才是最重要的。

再会!

猜你喜欢

转载自blog.csdn.net/qq_38624569/article/details/85233943