俄罗斯方块

俄罗斯方块

修改处:添加了 开始 和 设置 选项(但那里面没有加任何其它东西)

代码

  1 # _*_ coding:utf-8 _*_
  2 '''
  3 Created on 2017年7月30日上午11:16:44
  4 
  5 @author: xiaolin
  6 
  7 relief=RAISED
  8 sticky=N+E+S+W
  9 '''
 10 from tkinter import *
 11 import random
 12 import time
 13 # from tkMessageBox import *
 14 
 15 # 俄罗斯方块界面的高度
 16 HEIGHT = 20
 17 
 18 # 俄罗斯方块界面的宽度
 19 WIDTH = 10
 20 
 21 ACTIVE = 1
 22 PASSIVE = 0
 23 TRUE = 1
 24 FALSE = 0
 25 
 26 style = [
 27     [[(0, 0), (0, 1), (1, 1), (2, 1)], [(1, 0), (1, 1), (1, 2), (0, 2)], [(0, 1), (1, 1), (2, 1), (2, 2)],
 28      [(1, 0), (2, 0), (1, 1), (1, 2)]],  # j
 29     [[(1, 0), (1, 1), (1, 2), (2, 1)], [(1, 0), (0, 1), (1, 1), (2, 1)], [(1, 0), (1, 1), (1, 2), (0, 1)],
 30      [(0, 1), (1, 1), (2, 1), (1, 2)]],  # T
 31     [[(0, 1), (1, 1), (2, 1), (2, 0)], [(0, 0), (1, 0), (1, 1), (1, 2)], [(0, 1), (1, 1), (2, 1), (0, 2)],
 32      [(1, 0), (1, 1), (1, 2), (2, 2)]],  # 反L
 33     [[(0, 0), (0, 1), (1, 1), (1, 2)], [(2, 1), (1, 1), (1, 2), (0, 2)], [(0, 0), (0, 1), (1, 1), (1, 2)],
 34      [(2, 1), (1, 1), (1, 2), (0, 2)]],  # Z
 35     [[(1, 0), (1, 1), (0, 1), (0, 2)], [(0, 1), (1, 1), (1, 2), (2, 2)], [(1, 0), (1, 1), (0, 1), (0, 2)],
 36      [(0, 1), (1, 1), (1, 2), (2, 2)]],  # 反Z
 37     [[(0, 0), (0, 1), (1, 1), (1, 0)], [(0, 0), (0, 1), (1, 1), (1, 0)], [(0, 0), (0, 1), (1, 1), (1, 0)],
 38      [(0, 0), (0, 1), (1, 1), (1, 0)]],  #
 39     [[(1, 0), (1, 1), (1, 2), (1, 3)], [(0, 1), (1, 1), (2, 1), (3, 1)], [(1, 0), (1, 1), (1, 2), (1, 3)],
 40      [(0, 1), (1, 1), (2, 1), (3, 1)]]  # 长条
 41 ]
 42 
 43 root = Tk();
 44 root.title('俄罗斯方块')
 45 
 46 
 47 class App(Frame):
 48     def __init__(self, master):
 49         Frame.__init__(self)
 50         master.bind('<Up>', self.Up)
 51         master.bind('<Left>', self.Left)
 52         master.bind('<Right>', self.Right)
 53         master.bind('<Down>', self.Down)
 54 
 55         master.bind('<space>', self.Space)
 56         master.bind('<Control-Shift-Key-F12>', self.Play)
 57         master.bind('<Key-P>', self.Pause)
 58         master.bind('<Key-S>', self.StartByS)
 59 
 60         # rgb颜色值
 61         self.backg = "#%02x%02x%02x" % (120, 150, 30)  # 大背景
 62         self.frontg = "#%02x%02x%02x" % (40, 120, 150)  # 下一个形状颜色
 63         self.nextg = "#%02x%02x%02x" % (150, 100, 100)  # 小背景
 64         self.flashg = "#%02x%02x%02x" % (210, 130, 100)  # 炸的颜色
 65 
 66         self.LineDisplay = Label(master, text='Lines: ', bg='black', fg='red')
 67         self.Line = Label(master, text='0', bg='black', fg='red')
 68         self.ScoreDisplay = Label(master, text='Score: ', bg='black', fg='red')
 69         self.Score = Label(master, text='0', bg='black', fg='red')
 70         self.SpendTimeDisplay = Label(master, text='Time: ', bg='black', fg='red')
 71         self.SpendTime = Label(master, text='0.0', bg='black', fg='red')
 72 
 73         self.LineDisplay.grid(row=HEIGHT - 2, column=WIDTH, columnspan=2)
 74         self.Line.grid(row=HEIGHT - 2, column=WIDTH + 2, columnspan=3)
 75         self.ScoreDisplay.grid(row=HEIGHT - 1, column=WIDTH, columnspan=2)
 76         self.Score.grid(row=HEIGHT - 1, column=WIDTH + 2, columnspan=3)
 77         self.SpendTimeDisplay.grid(row=HEIGHT - 4, column=WIDTH, columnspan=2)
 78         self.SpendTime.grid(row=HEIGHT - 4, column=WIDTH + 2, columnspan=3)
 79 
 80         self.TotalTime = 0.0
 81         self.TotalLine = 0
 82         self.TotalScore = 0
 83 
 84         # 游戏结束
 85         self.isgameover = FALSE
 86         # 暂停
 87         self.isPause = FALSE
 88         # 开始
 89         self.isStart = FALSE
 90         self.NextList = []  # 整个小背景
 91         self.NextRowList = []  # 一行小背景
 92 
 93         self.px = 0
 94         self.py = 0  # 记录方块参考点
 95 
 96         # 渲染小背景
 97         r = 0;
 98         c = 0
 99         for k in range(4 * 4):
100             LN = Label(master, text='    ', bg=str(self.nextg), fg='white', relief=FLAT, bd=3)
101             LN.grid(row=r, column=WIDTH + c, sticky=N + E + S + W)
102             self.NextRowList.append(LN)
103             c = c + 1
104             if c >= 4:
105                 r = r + 1;
106                 c = 0
107                 self.NextList.append(self.NextRowList)
108                 self.NextRowList = []
109 
110         # 渲染大背景
111         self.BlockList = []
112         self.BlockRowList = []
113         self.LabelList = []
114         self.LabelRowList = []
115         row = 0;
116         col = 0
117         for i in range(HEIGHT * WIDTH):
118             L = Label(master, text='    ', bg=str(self.backg), fg='white', relief=FLAT, bd=4)
119             L.grid(row=row, column=col, sticky=N + E + S + W)
120             L.row = row;
121             L.col = col;
122             L.isactive = PASSIVE
123             self.BlockRowList.append(0);  # 大背景每个格子初始化为0值
124             self.LabelRowList.append(L)
125             col = col + 1
126             if col >= WIDTH:
127                 row = row + 1;
128                 col = 0
129                 self.BlockList.append(self.BlockRowList)
130                 self.LabelList.append(self.LabelRowList)
131                 self.BlockRowList = []
132                 self.LabelRowList = []
133 
134         # file
135         fw = open('text.txt', 'a')
136         fw.close()
137         hasHead = FALSE
138         f = open('text.txt', 'r')
139         if f.read(5) == 'score':
140             hasHead = TRUE
141         f.close()
142         self.file = open('text.txt', 'a')
143         if hasHead == FALSE:
144             self.file.write('score    line    time    scorePtime    linePtime    scorePline    date/n')
145             self.file.flush()
146 
147         self.time = 1000
148         self.OnTimer()
149 
150     def __del__(self):
151         # self.file.close()
152         pass
153 
154     def Pause(self, event):
155         self.isPause = 1 - self.isPause
156 
157     def Up(self, event):
158         BL = self.BlockList  # 格子的值
159         LL = self.LabelList  # 格子Label
160 
161         Moveable = TRUE  # 是否可旋转
162 
163         # 代码编写开始
164         nowStyle = style[self.xnow][(self.ynow)]
165         newStyle = style[self.xnow][(self.ynow + 1) % 4]  # 算出下一俄罗斯方块
166         self.ynow = (self.ynow + 1) % 4  # 此行代码非常重要,否则响应UP时,只能变第一次
167 
168         print("nowStyle:" + str(nowStyle) + "=====>>newStyle:" + str(newStyle))
169 
170         # 根据现有形状中每个label的坐标计算出旋转后目标坐标(x,y)
171         SourceList = [];
172         DestList = []
173 
174         for i in range(4):
175             SourceList.append([nowStyle[i][0] + self.px, nowStyle[i][1] + self.py])
176             x = newStyle[i][0] + self.px
177             y = newStyle[i][1] + self.py
178             DestList.append([x, y])
179 
180             if x < 0 or x >= HEIGHT or y < 0 or y >= WIDTH:  # or BL[x][y]==1 or LL[x][y].isactive==PASSIVE
181                 Moveable = FALSE
182 
183         if Moveable == TRUE:
184             for i in range(len(SourceList)):
185                 self.Empty(SourceList[i][0], SourceList[i][1])
186             for i in range(len(DestList)):
187                 self.Fill(DestList[i][0], DestList[i][1])
188 
189     def Left(self, event):
190         BL = self.BlockList;
191         LL = self.LabelList
192         Moveable = TRUE
193         for i in range(HEIGHT):
194             for j in range(WIDTH):
195                 if LL[i][j].isactive == ACTIVE and j - 1 < 0: Moveable = FALSE
196                 if LL[i][j].isactive == ACTIVE and j - 1 >= 0 and BL[i][j - 1] == 1 and LL[i][
197                     j - 1].isactive == PASSIVE: Moveable = FALSE
198         if Moveable == TRUE:
199             self.py -= 1
200             for i in range(HEIGHT):
201                 for j in range(WIDTH):
202                     if j - 1 >= 0 and LL[i][j].isactive == ACTIVE and BL[i][j - 1] == 0:
203                         self.Fill(i, j - 1);
204                         self.Empty(i, j)
205 
206     def Right(self, event):
207         BL = self.BlockList;
208         LL = self.LabelList
209         Moveable = TRUE
210         for i in range(HEIGHT):
211             for j in range(WIDTH):
212                 if LL[i][j].isactive == ACTIVE and j + 1 >= WIDTH: Moveable = FALSE
213                 if LL[i][j].isactive == ACTIVE and j + 1 < WIDTH and BL[i][j + 1] == 1 and LL[i][
214                     j + 1].isactive == PASSIVE: Moveable = FALSE
215         if Moveable == TRUE:
216             self.py += 1
217             for i in range(HEIGHT - 1, -1, -1):
218                 for j in range(WIDTH - 1, -1, -1):
219                     if j + 1 < WIDTH and LL[i][j].isactive == ACTIVE and BL[i][j + 1] == 0:
220                         self.Fill(i, j + 1);
221                         self.Empty(i, j)
222 
223     def Down(self, event):
224         BL = self.BlockList;
225         LL = self.LabelList
226         Moveable = TRUE
227         for i in range(HEIGHT):
228             for j in range(WIDTH):
229                 if LL[i][j].isactive == ACTIVE and i + 1 >= HEIGHT: Moveable = FALSE
230                 if LL[i][j].isactive == ACTIVE and i + 1 < HEIGHT and BL[i + 1][j] == 1 and LL[i + 1][
231                     j].isactive == PASSIVE: Moveable = FALSE
232         if Moveable == TRUE and self.isStart:
233             self.px += 1
234             for i in range(HEIGHT - 1, -1, -1):
235                 for j in range(WIDTH - 1, -1, -1):
236                     if i + 1 < HEIGHT and LL[i][j].isactive == ACTIVE and BL[i + 1][j] == 0:
237                         self.Fill(i + 1, j);
238                         self.Empty(i, j);
239         if Moveable == FALSE:
240             for i in range(HEIGHT):
241                 for j in range(WIDTH):
242                     LL[i][j].isactive = PASSIVE
243             self.JudgeLineFill()
244             self.Start()
245             if self.isgameover == TRUE: showinfo('T_T', 'The game is over!');self.Distroy();return FALSE
246             for i in range(4):
247                 for j in range(4):
248                     self.NextEmpty(i, j)
249             self.Rnd()
250         return Moveable
251 
252     def Space(self, event):
253         while 1:
254             if self.Down(0) == FALSE: break
255 
256     def OnTimer(self):
257         if self.isStart == TRUE and self.isPause == FALSE:
258             self.TotalTime = self.TotalTime + float(self.time) / 1000
259             self.SpendTime.config(text=str(self.TotalTime))
260 
261         if self.isPause == FALSE:
262             self.Down(0)
263         if self.TotalScore >= 1000: self.time = 900
264         if self.TotalScore >= 2000: self.time = 750
265         if self.TotalScore >= 3000: self.time = 600
266         if self.TotalScore >= 4000: self.time = 400
267         self.after(self.time, self.OnTimer)  # 随着分数增大,俄罗斯方块下降速度加快
268 
269     def JudgeLineFill(self):
270         BL = self.BlockList;
271         LL = self.LabelList
272         count = 0;
273         LineList = []
274         for i in range(WIDTH): LineList.append(1)
275         # display flash
276         for i in range(HEIGHT):
277             if BL[i] == LineList:
278                 count = count + 1
279                 for k in range(WIDTH):
280                     LL[i][k].config(bg=str(self.flashg))
281                     LL[i][k].update()
282         if count != 0: self.after(100)
283         # delete block
284         for i in range(HEIGHT):
285             if BL[i] == LineList:
286                 # count=count+1
287                 for j in range(i, 0, -1):
288                     for k in range(WIDTH):
289                         BL[j][k] = BL[j - 1][k]
290                         LL[j][k]['relief'] = LL[j - 1][k].cget('relief')
291                         LL[j][k]['bg'] = LL[j - 1][k].cget('bg')
292                 for l in range(WIDTH):
293                     BL[0][l] = 0
294                     LL[0][l].config(relief=FLAT, bg=str(self.backg))
295         self.TotalLine = self.TotalLine + count
296         if count == 1: self.TotalScore = self.TotalScore + 1 * WIDTH
297         if count == 2: self.TotalScore = self.TotalScore + 3 * WIDTH
298         if count == 3: self.TotalScore = self.TotalScore + 6 * WIDTH
299         if count == 4: self.TotalScore = self.TotalScore + 10 * WIDTH
300         self.Line.config(text=str(self.TotalLine))
301         self.Score.config(text=str(self.TotalScore))
302 
303     def Fill(self, i, j):
304         if j < 0: return
305         if self.BlockList[i][j] == 1: self.isgameover = TRUE
306         self.BlockList[i][j] = 1
307         self.LabelList[i][j].isactive = ACTIVE
308         self.LabelList[i][j].config(relief=RAISED, bg=str(self.frontg))
309 
310     def Empty(self, i, j):
311         self.BlockList[i][j] = 0
312         self.LabelList[i][j].isactive = PASSIVE
313         self.LabelList[i][j].config(relief=FLAT, bg=str(self.backg))
314 
315     def Play(self, event):
316         showinfo('Made in China', '^_^')
317 
318     def NextFill(self, i, j):
319         self.NextList[i][j].config(relief=RAISED, bg=str(self.frontg))
320 
321     def NextEmpty(self, i, j):
322         self.NextList[i][j].config(relief=FLAT, bg=str(self.nextg))
323 
324     def Distroy(self):
325         # save
326         if self.TotalScore != 0:
327             # cehkongfu
328             savestr = '%-9u%-8u%-8.2f%-14.2f%-13.2f%-14.2f%s/n' % (
329                 self.TotalScore, self.TotalLine, self.TotalTime
330                 , self.TotalScore / self.TotalTime
331                 , self.TotalLine / self.TotalTime
332                 , float(self.TotalScore) / self.TotalLine
333                 , time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
334             self.file.seek(0, 2)
335             self.file.write(savestr)
336             self.file.flush()
337 
338         for i in range(HEIGHT):
339             for j in range(WIDTH):
340                 self.Empty(i, j)
341         self.TotalLine = 0;
342         self.TotalScore = 0;
343         self.TotalTime = 0.0
344         self.Line.config(text=str(self.TotalLine))
345         self.Score.config(text=str(self.TotalScore))
346         self.SpendTime.config(text=str(self.TotalTime))
347         self.isgameover = FALSE
348         self.isStart = FALSE
349         self.time = 1000
350         for i in range(4):
351             for j in range(4):
352                 self.NextEmpty(i, j)
353 
354     # 游戏开始方块
355     def Start(self):
356         nextStyle = style[self.x][self.y]  # 下一形状
357         self.xnow = self.x
358         self.ynow = self.y  # 记录大背景中的方块
359         self.py = random.randint(0, 6)
360         print("给py赋任意值:" + str(self.py))
361         self.px = 0
362         for ii in range(4):
363             self.Fill(int(nextStyle[ii][0]), int(nextStyle[ii][1]) + self.py)
364         self.isStart = TRUE  # 游戏开始
365 
366     # 预处理方块
367     def Rnd(self):
368         self.x = random.randint(0, 6)
369         self.y = random.randint(0, 3)
370         nextStyle = style[self.x][self.y]  # 下一形状
371         for ii in range(4):
372             self.NextFill(int(nextStyle[ii][0]), int(nextStyle[ii][1]))
373 
374     # 游戏开始给出一次任意形状的方块
375     def RndFirst(self):
376         self.x = random.randint(0, 6)  # 选择第一个方块style
377         self.y = random.randint(0, 3)
378 
379     def Show(self):
380         self.file.seek(0)
381         strHeadLine = self.file.readline()
382         dictLine = {}
383         strTotalLine = ''
384         for OneLine in self.file.readlines():
385             temp = int(OneLine[:5])
386             dictLine[temp] = OneLine
387 
388         list = sorted(dictLine.items(), key=lambda d: d[0])
389         ii = 0
390         for onerecord in reversed(list):
391             ii = ii + 1
392             if ii < 11:
393                 strTotalLine += onerecord[1]
394         showinfo('Ranking', strHeadLine + strTotalLine)
395 
396     def StartByS(self, event):
397         self.RndFirst()
398         self.Start()
399         self.Rnd()
400 
401 
402 def Start():
403     app.RndFirst()
404     app.Start()
405     app.Rnd()
406 
407 
408 def End():
409     app.Distroy()
410 
411 
412 def Set():
413     print("设置功能待完善...")
414 
415 
416 def Show():
417     app.Show()
418 
419 
420 # 主菜单
421 mainmenu = Menu(root)
422 root['menu'] = mainmenu
423 
424 # 二级菜单:game
425 gamemenu = Menu(mainmenu)
426 mainmenu.add_cascade(label='游戏', menu=gamemenu)
427 gamemenu.add_command(label='开始', command=Start)
428 gamemenu.add_command(label='结束', command=End)
429 gamemenu.add_separator()
430 gamemenu.add_command(label='退出', command=root.quit)
431 
432 # 二级菜单:set
433 setmenu = Menu(mainmenu)
434 mainmenu.add_cascade(label='设置', menu=setmenu)
435 setmenu.add_command(label='设置', command=Set)
436 
437 # 二级菜单:show
438 showmenu = Menu(mainmenu)
439 mainmenu.add_cascade(label='展示', menu=showmenu)
440 showmenu.add_command(label='展示', command=Show)
441 
442 # 绑定功能
443 
444 app = App(root)
445 # 程序入口
446 root.mainloop()

 

效果图:

 

 

posted @ 2020-11-29 14:53  20201320石志涛  阅读(153)  评论(0编辑  收藏  举报