对于该项作业,我修改了原代码中,
1,修改了游戏结束时语句播放错误的代码,使其正常播报;
2,调整了背景配色为黑灰使其辨识度更高;
3,对于没有内置功能的设置选项添加了播报语句,使其不再print结果在命令台。
4,增加了对于俄罗斯方块游戏的故事在新创的关于模块
原错误代码经VScode检查为 showinfo('T_T', 'The game is over!')
showinfo("FishC Demo","祝您新年快乐!")
showinfo('Made in China', '^_^')
我通过百度的查找得到了其解决方法,网址:https://jingyan.baidu.com/article/c74d6000ccc51e0f6a595d3a.html
将其改为,使其能够播报
tkinter.messagebox.showinfo('T_T', 'The game is over!')
tkinter.messagebox.showinfo("FishC Demo","祝您新年快乐!")
tkinter.messagebox.showinfo('Made in China', '^_^')
下面是修改后的代码:
# _*_ coding:utf-8 _*_ ''' Created on 2017年7月30日上午11:16:44 @author: xiaolin relief=RAISED sticky=N+E+S+W ''' from tkinter import * import random import time # from tkMessageBox import * import tkinter.messagebox from tkinter import * # 俄罗斯方块界面的高度 HEIGHT = 20 # 俄罗斯方块界面的宽度 WIDTH = 10 ACTIVE = 1 PASSIVE = 0 TRUE = 1 FALSE = 0 style = [ [[(0, 0), (0, 1), (1, 1), (2, 1)], [(1, 0), (1, 1), (1, 2), (0, 2)], [(0, 1), (1, 1), (2, 1), (2, 2)], [(1, 0), (2, 0), (1, 1), (1, 2)]], # j [[(1, 0), (1, 1), (1, 2), (2, 1)], [(1, 0), (0, 1), (1, 1), (2, 1)], [(1, 0), (1, 1), (1, 2), (0, 1)], [(0, 1), (1, 1), (2, 1), (1, 2)]], # T [[(0, 1), (1, 1), (2, 1), (2, 0)], [(0, 0), (1, 0), (1, 1), (1, 2)], [(0, 1), (1, 1), (2, 1), (0, 2)], [(1, 0), (1, 1), (1, 2), (2, 2)]], # 反L [[(0, 0), (0, 1), (1, 1), (1, 2)], [(2, 1), (1, 1), (1, 2), (0, 2)], [(0, 0), (0, 1), (1, 1), (1, 2)], [(2, 1), (1, 1), (1, 2), (0, 2)]], # Z [[(1, 0), (1, 1), (0, 1), (0, 2)], [(0, 1), (1, 1), (1, 2), (2, 2)], [(1, 0), (1, 1), (0, 1), (0, 2)], [(0, 1), (1, 1), (1, 2), (2, 2)]], # 反Z [[(0, 0), (0, 1), (1, 1), (1, 0)], [(0, 0), (0, 1), (1, 1), (1, 0)], [(0, 0), (0, 1), (1, 1), (1, 0)], [(0, 0), (0, 1), (1, 1), (1, 0)]], # 田 [[(1, 0), (1, 1), (1, 2), (1, 3)], [(0, 1), (1, 1), (2, 1), (3, 1)], [(1, 0), (1, 1), (1, 2), (1, 3)], [(0, 1), (1, 1), (2, 1), (3, 1)]] # 长条 ] root = Tk(); root.title('俄罗斯方块') class App(Frame): def __init__(self, master): Frame.__init__(self) master.bind('<Up>', self.Up) master.bind('<Left>', self.Left) master.bind('<Right>', self.Right) master.bind('<Down>', self.Down) master.bind('<space>', self.Space) master.bind('<Control-Shift-Key-F12>', self.Play) master.bind('<Key-P>', self.Pause) master.bind('<Key-S>', self.StartByS) # rgb颜色值 self.backg = "#%02x%02x%02x" % (0, 0, 0) # 大背景 self.frontg = "#%02x%02x%02x" % (40, 120, 150) # 下一个形状颜色 self.nextg = "#%02x%02x%02x" % (150, 150, 150) # 小背景 self.flashg = "#%02x%02x%02x" % (210, 130, 100) # 炸的颜色 self.LineDisplay = Label(master, text='Lines: ', bg='black', fg='red') self.Line = Label(master, text='0', bg='black', fg='red') self.ScoreDisplay = Label(master, text='Score: ', bg='black', fg='red') self.Score = Label(master, text='0', bg='black', fg='red') self.SpendTimeDisplay = Label(master, text='Time: ', bg='black', fg='red') self.SpendTime = Label(master, text='0.0', bg='black', fg='red') self.LineDisplay.grid(row=HEIGHT - 2, column=WIDTH, columnspan=2) self.Line.grid(row=HEIGHT - 2, column=WIDTH + 2, columnspan=3) self.ScoreDisplay.grid(row=HEIGHT - 1, column=WIDTH, columnspan=2) self.Score.grid(row=HEIGHT - 1, column=WIDTH + 2, columnspan=3) self.SpendTimeDisplay.grid(row=HEIGHT - 4, column=WIDTH, columnspan=2) self.SpendTime.grid(row=HEIGHT - 4, column=WIDTH + 2, columnspan=3) self.TotalTime = 0.0 self.TotalLine = 0 self.TotalScore = 0 # 游戏结束 self.isgameover = FALSE # 暂停 self.isPause = FALSE # 开始 self.isStart = FALSE self.NextList = [] # 整个小背景 self.NextRowList = [] # 一行小背景 self.px = 0 self.py = 0 # 记录方块参考点 # 渲染小背景 r = 0; c = 0 for k in range(4 * 4): LN = Label(master, text=' ', bg=str(self.nextg), fg='white', relief=FLAT, bd=3) LN.grid(row=r, column=WIDTH + c, sticky=N + E + S + W) self.NextRowList.append(LN) c = c + 1 if c >= 4: r = r + 1; c = 0 self.NextList.append(self.NextRowList) self.NextRowList = [] # 渲染大背景 self.BlockList = [] self.BlockRowList = [] self.LabelList = [] self.LabelRowList = [] row = 0; col = 0 for i in range(HEIGHT * WIDTH): L = Label(master, text=' ', bg=str(self.backg), fg='white', relief=FLAT, bd=4) L.grid(row=row, column=col, sticky=N + E + S + W) L.row = row; L.col = col; L.isactive = PASSIVE self.BlockRowList.append(0); # 大背景每个格子初始化为0值 self.LabelRowList.append(L) col = col + 1 if col >= WIDTH: row = row + 1; col = 0 self.BlockList.append(self.BlockRowList) self.LabelList.append(self.LabelRowList) self.BlockRowList = [] self.LabelRowList = [] # file fw = open('text.txt', 'a') fw.close() hasHead = FALSE f = open('text.txt', 'r') if f.read(5) == 'score': hasHead = TRUE f.close() self.file = open('text.txt', 'a') if hasHead == FALSE: self.file.write('score line time scorePtime linePtime scorePline date/n') self.file.flush() self.time = 1000 self.OnTimer() def __del__(self): # self.file.close() pass def Pause(self, event): self.isPause = 1 - self.isPause def Up(self, event): BL = self.BlockList # 格子的值 LL = self.LabelList # 格子Label Moveable = TRUE # 是否可旋转 # 代码编写开始 nowStyle = style[self.xnow][(self.ynow)] newStyle = style[self.xnow][(self.ynow + 1) % 4] # 算出下一俄罗斯方块 self.ynow = (self.ynow + 1) % 4 # 此行代码非常重要,否则响应UP时,只能变第一次 print("nowStyle:" + str(nowStyle) + "=====>>newStyle:" + str(newStyle)) # 根据现有形状中每个label的坐标计算出旋转后目标坐标(x,y) SourceList = []; DestList = [] for i in range(4): SourceList.append([nowStyle[i][0] + self.px, nowStyle[i][1] + self.py]) x = newStyle[i][0] + self.px y = newStyle[i][1] + self.py DestList.append([x, y]) if x < 0 or x >= HEIGHT or y < 0 or y >= WIDTH: # or BL[x][y]==1 or LL[x][y].isactive==PASSIVE Moveable = FALSE if Moveable == TRUE: for i in range(len(SourceList)): self.Empty(SourceList[i][0], SourceList[i][1]) for i in range(len(DestList)): self.Fill(DestList[i][0], DestList[i][1]) def Left(self, event): BL = self.BlockList; LL = self.LabelList Moveable = TRUE for i in range(HEIGHT): for j in range(WIDTH): if LL[i][j].isactive == ACTIVE and j - 1 < 0: Moveable = FALSE if LL[i][j].isactive == ACTIVE and j - 1 >= 0 and BL[i][j - 1] == 1 and LL[i][ j - 1].isactive == PASSIVE: Moveable = FALSE if Moveable == TRUE: self.py -= 1 for i in range(HEIGHT): for j in range(WIDTH): if j - 1 >= 0 and LL[i][j].isactive == ACTIVE and BL[i][j - 1] == 0: self.Fill(i, j - 1); self.Empty(i, j) def Right(self, event): BL = self.BlockList; LL = self.LabelList Moveable = TRUE for i in range(HEIGHT): for j in range(WIDTH): if LL[i][j].isactive == ACTIVE and j + 1 >= WIDTH: Moveable = FALSE if LL[i][j].isactive == ACTIVE and j + 1 < WIDTH and BL[i][j + 1] == 1 and LL[i][ j + 1].isactive == PASSIVE: Moveable = FALSE if Moveable == TRUE: self.py += 1 for i in range(HEIGHT - 1, -1, -1): for j in range(WIDTH - 1, -1, -1): if j + 1 < WIDTH and LL[i][j].isactive == ACTIVE and BL[i][j + 1] == 0: self.Fill(i, j + 1); self.Empty(i, j) def Down(self, event): BL = self.BlockList; LL = self.LabelList Moveable = TRUE for i in range(HEIGHT): for j in range(WIDTH): if LL[i][j].isactive == ACTIVE and i + 1 >= HEIGHT: Moveable = FALSE if LL[i][j].isactive == ACTIVE and i + 1 < HEIGHT and BL[i + 1][j] == 1 and LL[i + 1][ j].isactive == PASSIVE: Moveable = FALSE if Moveable == TRUE and self.isStart: self.px += 1 for i in range(HEIGHT - 1, -1, -1): for j in range(WIDTH - 1, -1, -1): if i + 1 < HEIGHT and LL[i][j].isactive == ACTIVE and BL[i + 1][j] == 0: self.Fill(i + 1, j); self.Empty(i, j); if Moveable == FALSE: for i in range(HEIGHT): for j in range(WIDTH): LL[i][j].isactive = PASSIVE self.JudgeLineFill() self.Start() if self.isgameover == TRUE: tkinter.messagebox.showinfo('T_T', 'The game is over!');self.Distroy();return FALSE for i in range(4): for j in range(4): self.NextEmpty(i, j) self.Rnd() return Moveable def Space(self, event): while 1: if self.Down(0) == FALSE: break def OnTimer(self): if self.isStart == TRUE and self.isPause == FALSE: self.TotalTime = self.TotalTime + float(self.time) / 1000 self.SpendTime.config(text=str(self.TotalTime)) if self.isPause == FALSE: self.Down(0) if self.TotalScore >= 1000: self.time = 900 if self.TotalScore >= 2000: self.time = 750 if self.TotalScore >= 3000: self.time = 600 if self.TotalScore >= 4000: self.time = 400 self.after(self.time, self.OnTimer) # 随着分数增大,俄罗斯方块下降速度加快 def JudgeLineFill(self): BL = self.BlockList; LL = self.LabelList count = 0; LineList = [] for i in range(WIDTH): LineList.append(1) # display flash for i in range(HEIGHT): if BL[i] == LineList: count = count + 1 for k in range(WIDTH): LL[i][k].config(bg=str(self.flashg)) LL[i][k].update() if count != 0: self.after(100) # delete block for i in range(HEIGHT): if BL[i] == LineList: # count=count+1 for j in range(i, 0, -1): for k in range(WIDTH): BL[j][k] = BL[j - 1][k] LL[j][k]['relief'] = LL[j - 1][k].cget('relief') LL[j][k]['bg'] = LL[j - 1][k].cget('bg') for l in range(WIDTH): BL[0][l] = 0 LL[0][l].config(relief=FLAT, bg=str(self.backg)) self.TotalLine = self.TotalLine + count if count == 1: self.TotalScore = self.TotalScore + 1 * WIDTH if count == 2: self.TotalScore = self.TotalScore + 3 * WIDTH if count == 3: self.TotalScore = self.TotalScore + 6 * WIDTH if count == 4: self.TotalScore = self.TotalScore + 10 * WIDTH self.Line.config(text=str(self.TotalLine)) self.Score.config(text=str(self.TotalScore)) def Fill(self, i, j): if j < 0: return if self.BlockList[i][j] == 1: self.isgameover = TRUE self.BlockList[i][j] = 1 self.LabelList[i][j].isactive = ACTIVE self.LabelList[i][j].config(relief=RAISED, bg=str(self.frontg)) def Empty(self, i, j): self.BlockList[i][j] = 0 self.LabelList[i][j].isactive = PASSIVE self.LabelList[i][j].config(relief=FLAT, bg=str(self.backg)) def Play(self, event): tkinter.messagebox.showinfo('Made in China', '^_^') def NextFill(self, i, j): self.NextList[i][j].config(relief=RAISED, bg=str(self.frontg)) def NextEmpty(self, i, j): self.NextList[i][j].config(relief=FLAT, bg=str(self.nextg)) def Distroy(self): # save if self.TotalScore != 0: # cehkongfu savestr = '%-9u%-8u%-8.2f%-14.2f%-13.2f%-14.2f%s/n' % ( self.TotalScore, self.TotalLine, self.TotalTime , self.TotalScore / self.TotalTime , self.TotalLine / self.TotalTime , float(self.TotalScore) / self.TotalLine , time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())) self.file.seek(0, 2) self.file.write(savestr) self.file.flush() for i in range(HEIGHT): for j in range(WIDTH): self.Empty(i, j) self.TotalLine = 0; self.TotalScore = 0; self.TotalTime = 0.0 self.Line.config(text=str(self.TotalLine)) self.Score.config(text=str(self.TotalScore)) self.SpendTime.config(text=str(self.TotalTime)) self.isgameover = FALSE self.isStart = FALSE self.time = 1000 for i in range(4): for j in range(4): self.NextEmpty(i, j) # 游戏开始方块 def Start(self): nextStyle = style[self.x][self.y] # 下一形状 self.xnow = self.x self.ynow = self.y # 记录大背景中的方块 self.py = random.randint(0, 6) print("给py赋任意值:" + str(self.py)) self.px = 0 for ii in range(4): self.Fill(int(nextStyle[ii][0]), int(nextStyle[ii][1]) + self.py) self.isStart = TRUE # 游戏开始 # 预处理方块 def Rnd(self): self.x = random.randint(0, 6) self.y = random.randint(0, 3) nextStyle = style[self.x][self.y] # 下一形状 for ii in range(4): self.NextFill(int(nextStyle[ii][0]), int(nextStyle[ii][1])) # 游戏开始给出一次任意形状的方块 def RndFirst(self): self.x = random.randint(0, 6) # 选择第一个方块style self.y = random.randint(0, 3) def Show(self): self.file.seek(0) strHeadLine = self.file.readline() dictLine = {} strTotalLine = '' for OneLine in self.file.readlines(): temp = int(OneLine[:5]) dictLine[temp] = OneLine list = sorted(dictLine.items(), key=lambda d: d[0]) ii = 0 for onerecord in reversed(list): ii = ii + 1 if ii < 11: strTotalLine += onerecord[1] tkinter.messagebox.showinfo("FishC Demo","祝您新年快乐!") tkinter.messagebox.showinfo('Ranking', strHeadLine + strTotalLine) def StartByS(self, event): self.RndFirst() self.Start() self.Rnd() def Start(): app.RndFirst() app.Start() app.Rnd() def End(): app.Distroy() def Set(): tkinter.messagebox.showinfo('1422能力不足','设置不存在') def Show(): app.Show() def about(): tkinter.messagebox.showinfo('故事','''顾名思义,俄罗斯方块自然是俄罗斯人发明的。 这人叫阿列克谢·帕基特诺夫(Алексей Пажитнов 英文:Alexey Pazhitnov)。 俄罗斯方块原名是俄语Тетрис(英语是Tetris),这个名字来源于希腊语tetra,意思是“四”,而游戏的作者最喜欢网球(tennis)。 于是,他把两个词tetra和tennis合而为一,命名为Tetris,这也就是俄罗斯方块名字的由来。''') # 主菜单 mainmenu = Menu(root) root['menu'] = mainmenu # 二级菜单:game gamemenu = Menu(mainmenu) mainmenu.add_cascade(label='游戏', menu=gamemenu) gamemenu.add_command(label='开始', command=Start) gamemenu.add_command(label='结束', command=End) gamemenu.add_separator() gamemenu.add_command(label='退出', command=root.quit) # 二级菜单:set setmenu = Menu(mainmenu) mainmenu.add_cascade(label='设置', menu=setmenu) setmenu.add_command(label='背景颜色设置', command=Set) setmenu.add_command(label='游戏难度(速度)', command=Set) # 二级菜单:about aboutmenu = Menu(mainmenu) mainmenu.add_cascade(label='关于', menu=aboutmenu) aboutmenu.add_command(label='俄罗斯方块游戏的背景故事',command=about) # 绑定功能 app = App(root) # 程序入口 root.mainloop()
运行截图如下:
思考:
def Play(self, event):
tkinter.messagebox.showinfo('Made in China', '^_^')
我们可以看见在原代码中,存在一个event但是似乎难以进行触发,可以通过怎样的修改来使该事件按逻辑进行触发呢?