python實現(xiàn)簡單俄羅斯方塊
更新時間:2020年03月13日 08:19:47 作者:-葵藿傾陽
這篇文章主要為大家詳細介紹了python實現(xiàn)簡單俄羅斯方塊,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
本文實例為大家分享了python實現(xiàn)俄羅斯方塊的具體代碼,供大家參考,具體內容如下
# teris.py
# A module for game teris.
# By programmer FYJ
from tkinter import *
from time import sleep
from random import *
from tkinter import messagebox
class Teris:
def __init__(self):
#方塊顏色列表
self.color = ['red','orange','yellow','purple','blue','green','pink']
# Set a core squre and any shape can be drawn by the relative location.
#字典 存儲形狀對應7種形狀 元組存儲坐標
self.shapeDict = {1:[(0,0),(0,-1),(0,-2),(0,1)], # shape I
2:[(0,0),(0,-1),(1,-1),(1,0)], # shape O
3:[(0,0),(-1,0),(0,-1),(1,0)], # shape T T型
4:[(0,0),(0,-1),(1,0),(2,0)], # shape J 右長倒L蓋子
5:[(0,0),(0,-1),(-1,0),(-2,0)], # shape L
6:[(0,0),(0,-1),(-1,-1),(1,0)], # shape Z
7:[(0,0),(-1,0),(0,-1),(1,-1)]} # shape S
#旋轉坐標控制
self.rotateDict = {(0,0):(0,0),(0,1):(-1,0),(0,2):(-2,0),(0,-1):(1,0),
(0,-2):(2,0),(1,0):(0,1),(2,0):(0,2),(-1,0):(0,-1),
(-2,0):(0,-2),(1,1):(-1,1),(-1,1):(-1,-1),
(-1,-1):(1,-1),(1,-1):(1,1)}
# 初始高度,寬度 核心塊位置
self.coreLocation = [4,-2]
self.height,self.width = 20,10
self.size = 32
# Map can record the location of every square.i寬 j高
self.map = {}
#全部置0
for i in range(self.width):
for j in range(-4,self.height):
self.map[(i,j)] = 0
#添加邊界
for i in range(-4,self.width+4):
self.map[(i,self.height)] = 1
for j in range(-4,self.height+4):
for i in range(-4,0):
self.map[(i,j)] = 1
for j in range(-4,self.height+4):
for i in range(self.width,self.width+4):
self.map[(i,j)] = 1
# 初始化分數(shù)0 默認不加快 按下時加快
self.score = 0
self.isFaster = False
# 創(chuàng)建GUI界面
self.root = Tk()
self.root.title("Teris")
self.root.geometry("500x645")
self.area = Canvas(self.root,width=320,height=640,bg='white')
self.area.grid(row=2)
self.pauseBut = Button(self.root,text="Pause",height=2,width=13,font=(18),command=self.isPause)
self.pauseBut.place(x=340,y=100)
self.startBut = Button(self.root,text="Start",height=2,width=13,font=(18),command=self.play)
self.startBut.place(x=340,y=20)
self.restartBut = Button(self.root,text="Restart",height=2,width=13,font=(18),command=self.isRestart)
self.restartBut.place(x=340,y=180)
self.quitBut = Button(self.root,text="Quit",height=2,width=13,font=(18),command=self.isQuit)
self.quitBut.place(x=340,y=260)
self.scoreLabel1 = Label(self.root,text="Score:",font=(24))
self.scoreLabel1.place(x=340,y=600)
self.scoreLabel2 = Label(self.root,text="0",fg='red',font=(24))
self.scoreLabel2.place(x=410,y=600)
#按鍵交互
self.area.bind("<Up>",self.rotate)
self.area.bind("<Left>",self.moveLeft)
self.area.bind("<Right>",self.moveRight)
self.area.bind("<Down>",self.moveFaster)
self.area.bind("<Key-w>",self.rotate)
self.area.bind("<Key-a>",self.moveLeft)
self.area.bind("<Key-d>",self.moveRight)
self.area.bind("<Key-s>",self.moveFaster)
self.area.focus_set()
#菜單
self.menu = Menu(self.root)
self.root.config(menu=self.menu)
self.startMenu = Menu(self.menu)
self.menu.add_cascade(label='Start',menu=self.startMenu)
self.startMenu.add_command(label='New Game',command=self.isRestart)
self.startMenu.add_separator()
self.startMenu.add_command(label='Continue',command=self.play)
self.exitMenu = Menu(self.menu)
self.menu.add_cascade(label='Exit',command=self.isQuit)
self.helpMenu = Menu(self.root)
self.menu.add_cascade(label='Help',menu=self.helpMenu)
self.helpMenu.add_command(label='How to play',command=self.rule)
self.helpMenu.add_separator()
self.helpMenu.add_command(label='About...',command=self.about)
#先將核心塊的所在位置在map中的元素設為1,通過self.shapeDict獲取其余方塊位置,將map中對應元素設為1。
def getLocation(self):
map[(core[0],core[1])] = 1
for i in range(4):
map[((core[0]+getNew[i][0]),
(core[1]+getNew[i][1]))]=1
#判斷方塊下移一格后對應位置map中的元素是否為一,是,則不可移動,返回False;否,可以移動,返回True。
def canMove(self):
for i in range(4):
if map[(core[0]+getNew[i][0]),(core[1]+1+getNew[i][1])] == 1:
return False
return True
# 先用randRange獲取1~7中的隨機整數(shù),隨機到某一整數(shù),那么訪問self.shapeDict,獲取這種形狀方塊的核心塊及其他方塊的相對位置。
# 訪問顏色字典,獲取此方塊的顏色。建立循環(huán),當方塊可移動時(while self. canMove():),且暫停鍵未被摁下(if isPause:),
# 核心塊縱坐標加一,根據(jù)核心塊及其他方塊對于核心塊的相對位置,畫出四個方塊。用self.getLocation()函數(shù)獲取方塊的位置。
def drawNew(self):
global next
global getNew
global core
next = randrange(1,8)
#形狀
self.getNew = self.shapeDict[next]
getNew = self.getNew
core = [4,-2]
time = 0.2
while self.canMove():
if isPause:
core[1] += 1
self.drawSquare()
if self.isFaster:
sleep(time-0.15)
else:
sleep(time+0.22)
self.isFaster = False
else:
self.drawSquare()
sleep(time)
self.getLocation()
# 繪制當前方塊
def drawSquare(self):
self.area.delete("new")
for i in range(4):
self.area.create_rectangle((core[0]+self.getNew[i][0])*self.size,
(core[1]+self.getNew[i][1])*self.size,
(core[0]+self.getNew[i][0]+1)*self.size,
(core[1]+self.getNew[i][1]+1)*self.size,
fill=self.color[next-1],tags="new")
self.area.update()
# 給底部每行中方塊都加上標簽:bottom + str(j), j代表該塊所在行數(shù),每次遍歷map,建立對于range(self. height)的for循環(huán),刪去每一行,
# 若map什么地方的元素為1,畫出這一位置的方塊,不斷更新。這樣可以畫出底部方塊。
def drawBottom(self):
for j in range(self.height):
self.area.delete('bottom'+str(j))
for i in range(self.width):
if map[(i,j)] == 1:
self.area.create_rectangle(self.size*i,self.size*j,self.size*(i+1),
self.size*(j+1),fill='grey',tags='bottom'+str(j))
self.area.update()
# 判斷填滿遍歷map每一行的各個元素,若所有元素為1,則標簽中score值+10,將
# 此行所有元素改為0,行數(shù)map(i,j)=map(i-1,j)(即所有之上的行下移)
# ,那么后續(xù)畫底部方塊時,可實現(xiàn)消行。
def isFill(self):
for j in range(self.height):
t = 0
for i in range(self.width):
if map[(i,j)] == 1:
t = t + 1
if t == self.width:
self.getScore()
self.deleteLine(j)
# 加分
def getScore(self):
scoreValue = eval(self.scoreLabel2['text'])
scoreValue += 10
self.scoreLabel2.config(text=str(scoreValue))
# 消行
def deleteLine(self,j):
for t in range(j,2,-1):
for i in range(self.width):
map[(i,t)] = map[(i,t-1)]
for i in range(self.width):
map[(i,0)] = 0
self.drawBottom()
# 遍歷每一行,若從頂部到底部map每一行都有某一個元素或更多元素為1,
# 那么說明方塊以頂?shù)阶钌隙?,游戲結束。此處不可以簡單判定最上一行是否有元素為1就判定結束,
# 若這樣會產(chǎn)生頂部有新的方塊產(chǎn)生,然后導致頂部有元素為1,誤判為游戲結束。
def isOver(self):
t = 0
for j in range(self.height):
for i in range(self.width):
if self.map[(i,j)] == 1:
t += 1
break
if t >= self.height:
return False
else:
return True
# 先判斷方塊是否可以旋轉(針對其靠近邊界時)。先將其現(xiàn)在所在位置對應map中的元素改為0,判斷其旋
# 轉后位置對應map中的元素是否有一,若有,說明其旋轉后的位置已經(jīng)被占,是不能旋轉的,返回值為False
# 。否則為可旋轉,返回值True。若已判定可以旋轉,那么訪問self.rotateDict,得出旋轉以后所有小塊的位置
# 變換,將變換以后的位置對應map的元素設為1,旋轉便已完成。
def canRotate(self):
for i in range(4):
map[((core[0]+getNew[i][0]),
(core[1]+getNew[i][1]))] = 0
for i in range(4):
if map[((core[0]+self.rotateDict[getNew[i]][0]),
(core[1]+self.rotateDict[getNew[i]][1]))] == 1:
return False
return True
#旋轉
def rotate(self,event):
if next != 2:
if self.canRotate():
for i in range(4):
getNew[i] = self.rotateDict[getNew[i]]
self.drawSquare()
if not self.canMove():
for i in range(4):
map[((core[0]+getNew[i][0]),(core[1]+getNew[i][1]))] = 1
# 先判斷是否左移/右移,同樣,將方塊現(xiàn)在所處位置的map中元素設為0,看其移動后的位置上map的元素是否有1,
# 若有,說明這一位置已被占據(jù)或已到邊界,不可移動,返回False。若可移動,返回True。按下左鍵,若可
# 以移動,核心塊的橫坐標減1,由于我們只討論其他小塊對于核心塊的相對位置,所以其他小塊的位置自動隨
# 核心塊的位置移動而移動。將移動過后的位置對應map中的元素設為1。
def canLeft(self):
coreNow = core
for i in range(4):
map[((coreNow[0]+getNew[i][0]),(coreNow[1]+getNew[i][1]))] = 0
for i in range(4):
if map[((coreNow[0]+getNew[i][0]-1),(coreNow[1]+getNew[i][1]))] == 1:
return False
return True
#左移
def moveLeft(self,event):
if self.canLeft():
core[0] -= 1
self.drawSquare()
self.drawBottom()
if not self.canMove():
for i in range(4):
map[((core[0]+getNew[i][0]),(core[1]+getNew[i][1]))] = 1
# 判斷右移
def canRight(self):
for i in range(4):
map[((core[0]+getNew[i][0]),(core[1]+getNew[i][1]))] = 0
for i in range(4):
if map[((core[0]+getNew[i][0]+1),(core[1]+getNew[i][1]))] == 1:
return False
return True
# 右移
def moveRight(self,event):
if self.canRight():
core[0] += 1
self.drawSquare()
self.drawBottom()
if not self.canMove():
for i in range(4):
map[((core[0]+getNew[i][0]),(core[1]+getNew[i][1]))] = 1
# 初始化中有一self. isFaster 的變量被設為False,當其為False時,
# 程序中的sleep(time)中time的值為0.35,而按下下鍵,self. isFaster變?yōu)門rue,
# time變成0.05,通過調整sleep()中變量的大小可以調節(jié)方塊運動的速度。
# 此功能通過if語句實現(xiàn)。
def moveFaster(self,event):
self.isFaster = True
if not self.canMove():
for i in range(4):
map[((core[0]+getNew[i][0]),(core[1]+getNew[i][1]))] = 1
# run the programe
def run(self):
self.isFill()
self.drawNew()
self.drawBottom()
# play the game
def play(self):
self.startBut.config(state=DISABLED)
global isPause
isPause = True
global map
map = self.map
while True:
if self.isOver():
self.run()
else:
break
self.over()
# 重新開始游戲
def restart(self):
self.core = [4,-2]
self.map = {}
for i in range(self.width):
for j in range(-4,self.height):
self.map[(i,j)] = 0
for i in range(-1,self.width):
self.map[(i,self.height)] = 1
for j in range(-4,self.height+1):
self.map[(-1,j)] = 1
self.map[(self.width,j)] = 1
self.score = 0
self.t = 0.07
for j in range(self.height):
self.area.delete('bottom'+str(j))
self.play()
# 結束后告訴用戶失敗
def over(self):
feedback =messagebox.askquestion("You Lose!","You Lose!\nDo you want to restart?")
if feedback == 'yes':
self.restart()
else:
self.root.destroy()
# 退出
def isQuit(self):
askQuit =messagebox.askquestion("Quit","Are you sure to quit?")
if askQuit == 'yes':
self.root.destroy()
exit()
#判斷是否按下restart
def isRestart(self):
askRestart =messagebox.askquestion("Restart","Are you sure to restart?")
if askRestart == 'yes':
self.restart()
else:
return
# 每次一按下暫停鍵,isPause = not isPause,當isPause = True時,由于之前提到過的if isPause:語句,
# 方塊可以移動,游戲運行。當按下暫停鍵以后,isPause值為False,方塊將不可移動。同時,isPause值為False時
# ,暫停鍵變?yōu)殚_始鍵,即標簽由Pause 改為 Resume,當isPause值為True時,Resume改為Pause。這一功能由if語句實現(xiàn)。
def isPause(self):
global isPause
isPause=not isPause
if not isPause:
self.pauseBut["text"]="Resume"
else:
self.pauseBut["text"]="Pause"
#幫助
def rule(self):
ruleTop = Toplevel()
ruleTop.title('Help')
ruleTop.geometry('800x400')
rule ="Start: Press the start button or choose the option 'Continue' to start the game.\n%-s%-s%-s%-s%-s%-s%-s%-s%-s%-s%-s%-s%-s%-s"%("Restart: Press the restart button or choose the option 'New Game' to resatrt the game.\n", "Enjoy the Teris game! Have fun!")
ruleLabel = Label(ruleTop,text=rule,fg='blue',font=(18))
ruleLabel.place(x=50,y=50)
# 顯示有關信息
def about(self):
aboutTop = Toplevel()
aboutTop.title('About')
aboutTop.geometry('300x150')
about = "Teris.py\n\
By Programmer Lee\n\
All Rights Reserved."
aboutLabel = Label(aboutTop,font=('Curier',20),fg='darkblue',text=about)
aboutLabel.pack()
# Get into mainloop
def mainloop(self):
self.root.mainloop()
# TerisPlay.py
# Game Teris
# By programmer FYJ
from teris import *
def main():
teris = Teris()
teris.mainloop()
main()
運行結構如圖所示:

更多俄羅斯方塊精彩文章請點擊專題:俄羅斯方塊游戲集合 進行學習。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
Python中openpyxl實現(xiàn)vlookup函數(shù)的實例
在本篇文章里小編給大家整理的是關于Python中openpyxl實現(xiàn)vlookup函數(shù)的實例內容,有興趣的朋友們可以學習參考下。2020-10-10
解決Jupyter Notebook使用parser.parse_args出現(xiàn)錯誤問題
這篇文章主要介紹了解決Jupyter Notebook使用parser.parse_args出現(xiàn)錯誤問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-04-04
python的mysql數(shù)據(jù)庫建立表與插入數(shù)據(jù)操作示例
這篇文章主要介紹了python的mysql數(shù)據(jù)庫建立表與插入數(shù)據(jù)操作,結合實例形式分析了python操作mysql數(shù)據(jù)庫建立表與插入數(shù)據(jù)相關實現(xiàn)技巧,需要的朋友可以參考下2019-09-09

