????????小时候和小伙伴围着板凳玩24点,抢答拍桌把小手拍红。至今遗憾还有好多次算不出来,Python可以帮助我们弄清每一局比赛有解还是无解。
1 编码
????????花色编码:0:红桃;1:黑桃;2:梅花;3:方块
????????面值编码:J:11;Q:12;K:13;A:14
2 数据结构
用列表存储每一局比赛的四张牌,每张牌是一个二元组[ 面值, 花色]
用字典结构记录上述编码
3 算法
需要解决三个组合问题:
1)四张牌的面值的不重复组合
2)三个四则运算符的可重复排列
3)括号在表达式中的位置组合
表达式的计算问题,简单地可以用Python的eval函数完成,也可以用《数据结构》中讲到的双堆栈方法,建立优先级矩阵,自行编程实现(难点)
4 界面
界面采用tkinter+turtle结合完成,tkinter提供窗口、画布、按钮、Label,turtle负责绘制游戏场景
?
5 程序结构
1)可采用结构化程序设计,将程序功能分解为一定粒度的函数,通过函数调用实现程序。
2)分析程序中的对象和行为,进行职责分配,通过对象实例化和通信实现程序
本文采用结构化程序设计方法。
6 代码
from tkinter import *
import turtle
import random
suit_dict = {'0': '0.gif', '1': '1.gif', '2': '2.gif', '3': '3.gif'}
card_dict = {'2': '2', '3': '3', '4': '4', '5': '5', '6': '6', '7': '7', '8': '8', '9': '9', '10': '10', '11': 'J',
'12': 'Q', '13': 'K', '14': 'A'}
opr_list = ['+', '-', '*', '/']
def drawcard(card, x, y):
tu.penup()
tu.goto(x - 100, y) # 坐标向左位移100
tu.shape(card)
tu.stamp()
def writerank(x, y, rank):
tu.penup()
tu.goto(x - 100, y)
tu.write(rank, font=("Arial", 30, "normal"))
def drawgame(hand_list): # 绘制一局游戏
for i in range(4):
drawcard(suit_dict[hand_list[i][1]], i * 100, 0) # 牌花色,每张牌间隔100像素
writerank(i * 100 - 22, -25, card_dict[hand_list[i][0]]) # 牌面值
def opengame(): # 游戏开场 绘制扑克牌背面
for i in range(4):
drawcard("back.gif", i * 100, 0)
def deal_cards(): # 随机发牌4张,每张牌是个2元祖[面值,花色]
global hand_list # 全局变量
answer.set("")
hand_list = [[str(random.randint(2, 14)), str(random.randint(0, 3))] for i in range(4)]
drawgame(hand_list)
solve(hand_list) # 先计算出24点保存起来
def combine_cards(): #计算时不关心花色,只对面值组合
temp_list = []
for i in range(4):
for j in range(4):
if i == j: continue
for k in range(4):
if k == j or k == i: continue
for l in range(4):
if l == k or l == j or l == i: continue
temp_list.append([hand_list[i][0], hand_list[j][0], hand_list[k][0], hand_list[l][0]])
return temp_list
def combine_opr():
temp_list = []
for opr1 in opr_list:
for opr2 in opr_list:
for opr3 in opr_list:
temp_list.append([opr1, opr2, opr3])
return temp_list
def solve(hand_list): # 解题
global answer_list
answer_list = []
cards_combination = combine_cards()
opr_combination = combine_opr()
for card_list in cards_combination:
opd1, opd2, opd3, opd4 = card_list
for opr_list in opr_combination:
opr1, opr2, opr3 = opr_list
expression_list = [['(', opd1, opr1, opd2, ')', opr2, '(', opd3, opr3, opd4, ')'],
['(', opd1, opr1, opd2, ')', opr2, opd3, opr3, opd4],
['(', opd1, opr1, opd2, opr2, opd3, ')', opr3, opd4]
] # 加括号,形成表达式
if opr1 == '-' and int(opd1) < int(opd2): # 去除负数运算
expression_list.pop(0)
expression_list.pop(1)
for expression in expression_list:
ex = ''.join(expression)
try: # 预防除数为0
if eval(ex) == 24 and type(eval(ex)) == int: # 去除小数运算
answer_list.append(ex)
except:
pass
def showanswer():
if len(answer_list) == 0:
answer.set("无解")
else:
answer.set(answer_list[0]) #只显示第一组答案
hand_list = []
answer_list = []
root = Tk()
root.geometry('520x520+600+300')
root.title('24点游戏')
root.resizable(False, False)
canvas = Canvas(root, width=620, height=400)
canvas.pack()
answer = StringVar()
theScreen = turtle.TurtleScreen(canvas)
theScreen.addshape("back.gif")
theScreen.addshape("0.gif") # 红心
theScreen.addshape("1.gif") # 黑桃
theScreen.addshape("2.gif") # 梅花
theScreen.addshape("3.gif") # 方块
tu = turtle.RawTurtle(theScreen)
theScreen.tracer(False)
opengame()
bt1 = Button(root, text=' 发牌 ', command=deal_cards)
bt1.place(x=60, y=425)
bt2 = Button(root, text=' 答案 ', command=showanswer)
bt2.place(x=160, y=425)
Label(textvariable=answer).place(x=230, y=428)
root.mainloop()
?7 素材
?
?
?
?
?
|