记忆对对碰
为了巩固GUI,把上星期在coursera上课的作业改成Tkinter版
完成课程miniproject所用的module,是simplegui,代码.py), 需要用这个在线的CLI来运行
simplegui版的效果如下
下面进入Tkinter版的实现过程
源代码
这种桌面的GUI,虽然simplegui和tkinter不同,肯定也都是跟tk相关,于是在github上查找了下源代码,果然simplegui只是像tkinter的变种,前者能把后者更explicitly地“翻译”过来,便于理解。研究完之后发现,与其这样翻译,还不如直接用tkinter再实现一遍这个游戏
框架
from Tkinter import *
import random
def new_game():
pass
def draw_canvas():
pass
def mouseclick():
pass
root = Tk()
canvas_frame = Frame(root, width = 800, height = 100, bg = 'yellow')
canvas_frame.grid(row=0, column=1, rowspan=2, padx=5, pady=5)
new_game()
root.mainloop()
创建一个Frame,三个函数,分别是用来初始化的函数,处理canvas的函数,以及处理鼠标信息的函数
在Frame上创建一个canvas, 在canvas上随机输入16个预制数字
def new_game():
list1 = range(0,8)
list2 = range(0,8)
global m_list
m_list = list1 + list2
random.shuffle(m_list)
draw_canvas()
def draw_canvas():
cv = Canvas(canvas_frame, width = 800, height = 100, bg = 'white')
cv.grid(row=0, column=1, rowspan=2, padx=5, pady=5)
n = 30
for numb in m_list:
cv.create_text((n, 50), font = 'Verdana 35',text=str(numb))
n += 49
其中create_text中的参数(n, 50)是输入数字的坐标,n之所以选30是因为和字号35配合,刚好能在canvas上把16个数字平均分开,以便之后用来翻牌的程序正常的显示出完整的数字。
添加翻牌程序
def new_game():
list1 = range(0,8)
list2 = range(0,8)
global m_list
m_list = list1 + list2
random.shuffle(m_list)
global expo_list
expo_list = [False] * 16
draw_canvas()
def draw_canvas():
cv = Canvas(canvas_frame, width = 800, height = 100, bg = 'white')
cv.grid(row=0, column=1, rowspan=2, padx=5, pady=5)
n = 30
for numb in m_list:
cv.create_text((n, 50), font = 'Verdana 35',text=str(numb))
n += 49
for i in range(16):
if expo_list[i] == False:
cv.create_rectangle(i * 50, 0, (i * 50)+ 49, 100,width=1,outline='Red',fill = 'Green')
new_game()下添加一个global list,expo_list, 当它是False的时候,其对应位置的数字上会用绿色的矩形(也就是所谓牌的背面),其大小就由create_rectangle来控制。
i 50, 0, (i 50) + 49, 100分别是矩形的左上,左下,↘️,↗️,四个点,i对应的牌的号码。
鼠标点击的坐标处理
def draw_canvas():
cv = Canvas(canvas_frame, width = 800, height = 100, bg = 'white')
cv.grid(row=0, column=1, rowspan=2, padx=5, pady=5)
n = 30
for numb in m_list:
cv.create_text((n, 50), font = 'Verdana 35',text=str(numb))
n += 49
for i in range(16):
if expo_list[i] == False:
cv.create_rectangle(i * 50, 0, (i * 50)+ 49, 100,width=1,outline='Red',fill = 'Green')
cv.bind("<Button-1>", mouseclick)
def mouseclick(event):
global state, no_1, no_2
pos = event.x
no_i = pos // 50
if expo_list[no_i] != True:
if state == 0:
no_1 = no_i
expo_list[no_1] = True
state = 1
elif state == 1:
no_2 = no_i
expo_list[no_2] = True
state =2
else:
if m_list[no_1] != m_list[no_2]:
expo_list[no_1] = False
expo_list[no_2] = False
no_1 = no_i
expo_list[no_1] = True
state = 1
else:
no_1 = no_i
expo_list[no_1] = True
state = 1
draw_canvas()
cv.bind("< Button-1 >", mouseclick):当有鼠标左键点击时,触发mouseclick函数,并传入event数据。
state, no_1, no_2,都是要重复使用并且每次点击鼠标都有可能更新的参数,所以要在初始化函数New_game先声明出来,然后再在mouseclick中引用。
pos = event.x <- 取横坐标
逻辑:先判断此牌是否被掀开,没被掀开执行 -> state = 0 时,初始状态,0张牌被翻到正面,翻开一张牌记作no1;state = 1 时,一张牌已被翻开,再翻开一张牌,记作no2;state = 2 时,2张牌已被翻开,比较这两张牌的数字,如果不相等,则把两个牌翻回去,新的一张牌再翻成正面,如果相同,则直接执行新番一张牌。