溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

python實(shí)現(xiàn)俄羅斯方塊的方法

發(fā)布時(shí)間:2021-03-23 10:16:18 來源:億速云 閱讀:570 作者:小新 欄目:開發(fā)技術(shù)

這篇文章給大家分享的是有關(guān)python實(shí)現(xiàn)俄羅斯方塊的方法的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過來看看吧。

python實(shí)現(xiàn)俄羅斯方塊的具體代碼,具體內(nèi)容如下

# 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.
    #字典 存儲(chǔ)形狀對(duì)應(yīng)7種形狀 元組存儲(chǔ)坐標(biāo)
    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 右長(zhǎng)倒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
    #旋轉(zhuǎn)坐標(biāo)控制
    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

    # 初始化分?jǐn)?shù)0 默認(rèn)不加快 按下時(shí)加快
    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中的元素設(shè)為1,通過self.shapeDict獲取其余方塊位置,將map中對(duì)應(yīng)元素設(shè)為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

  #判斷方塊下移一格后對(duì)應(yīng)位置map中的元素是否為一,是,則不可移動(dòng),返回False;否,可以移動(dòng),返回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中的隨機(jī)整數(shù),隨機(jī)到某一整數(shù),那么訪問self.shapeDict,獲取這種形狀方塊的核心塊及其他方塊的相對(duì)位置。
  # 訪問顏色字典,獲取此方塊的顏色。建立循環(huán),當(dāng)方塊可移動(dòng)時(shí)(while self. canMove():),且暫停鍵未被摁下(if isPause:),
  # 核心塊縱坐標(biāo)加一,根據(jù)核心塊及其他方塊對(duì)于核心塊的相對(duì)位置,畫出四個(gè)方塊。用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()

  # 繪制當(dāng)前方塊
  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()
    

  # 給底部每行中方塊都加上標(biāo)簽:bottom + str(j), j代表該塊所在行數(shù),每次遍歷map,建立對(duì)于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每一行的各個(gè)元素,若所有元素為1,則標(biāo)簽中score值+10,將
  # 此行所有元素改為0,行數(shù)map(i,j)=map(i-1,j)(即所有之上的行下移)
  # ,那么后續(xù)畫底部方塊時(shí),可實(shí)現(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每一行都有某一個(gè)元素或更多元素為1,
  # 那么說明方塊以頂?shù)阶钌隙?,游戲結(jié)束。此處不可以簡(jiǎn)單判定最上一行是否有元素為1就判定結(jié)束,
  # 若這樣會(huì)產(chǎn)生頂部有新的方塊產(chǎn)生,然后導(dǎo)致頂部有元素為1,誤判為游戲結(jié)束。
  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

  # 先判斷方塊是否可以旋轉(zhuǎn)(針對(duì)其靠近邊界時(shí))。先將其現(xiàn)在所在位置對(duì)應(yīng)map中的元素改為0,判斷其旋
  # 轉(zhuǎn)后位置對(duì)應(yīng)map中的元素是否有一,若有,說明其旋轉(zhuǎn)后的位置已經(jīng)被占,是不能旋轉(zhuǎn)的,返回值為False
  # 。否則為可旋轉(zhuǎn),返回值True。若已判定可以旋轉(zhuǎn),那么訪問self.rotateDict,得出旋轉(zhuǎn)以后所有小塊的位置
  # 變換,將變換以后的位置對(duì)應(yīng)map的元素設(shè)為1,旋轉(zhuǎn)便已完成。
  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

  #旋轉(zhuǎn)
  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中元素設(shè)為0,看其移動(dòng)后的位置上map的元素是否有1,
  # 若有,說明這一位置已被占據(jù)或已到邊界,不可移動(dòng),返回False。若可移動(dòng),返回True。按下左鍵,若可
  # 以移動(dòng),核心塊的橫坐標(biāo)減1,由于我們只討論其他小塊對(duì)于核心塊的相對(duì)位置,所以其他小塊的位置自動(dòng)隨
  # 核心塊的位置移動(dòng)而移動(dòng)。將移動(dòng)過后的位置對(duì)應(yīng)map中的元素設(shè)為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 的變量被設(shè)為False,當(dāng)其為False時(shí),
  # 程序中的sleep(time)中time的值為0.35,而按下下鍵,self. isFaster變?yōu)門rue,
  # time變成0.05,通過調(diào)整sleep()中變量的大小可以調(diào)節(jié)方塊運(yùn)動(dòng)的速度。
  # 此功能通過if語句實(shí)現(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()

  # 結(jié)束后告訴用戶失敗
  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,當(dāng)isPause = True時(shí),由于之前提到過的if isPause:語句,
  # 方塊可以移動(dòng),游戲運(yùn)行。當(dāng)按下暫停鍵以后,isPause值為False,方塊將不可移動(dòng)。同時(shí),isPause值為False時(shí)
  # ,暫停鍵變?yōu)殚_始鍵,即標(biāo)簽由Pause 改為 Resume,當(dāng)isPause值為True時(shí),Resume改為Pause。這一功能由if語句實(shí)現(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)

  # 顯示有關(guān)信息
  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()

運(yùn)行結(jié)構(gòu)如圖所示:

python實(shí)現(xiàn)俄羅斯方塊的方法

感謝各位的閱讀!關(guān)于“python實(shí)現(xiàn)俄羅斯方塊的方法”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI