python实现简单俄罗斯方块
本文实例为大家分享了python实现俄罗斯方块的具体代码,供大家参考,具体内容如下
#teris.py #Amoduleforgameteris. #ByprogrammerFYJ fromtkinterimport* fromtimeimportsleep fromrandomimport* fromtkinterimportmessagebox classTeris: def__init__(self): #方块颜色列表 self.color=['red','orange','yellow','purple','blue','green','pink'] #Setacoresqureandanyshapecanbedrawnbytherelativelocation. #字典存储形状对应7种形状元组存储坐标 self.shapeDict={1:[(0,0),(0,-1),(0,-2),(0,1)],#shapeI 2:[(0,0),(0,-1),(1,-1),(1,0)],#shapeO 3:[(0,0),(-1,0),(0,-1),(1,0)],#shapeTT型 4:[(0,0),(0,-1),(1,0),(2,0)],#shapeJ右长倒L盖子 5:[(0,0),(0,-1),(-1,0),(-2,0)],#shapeL 6:[(0,0),(0,-1),(-1,-1),(1,0)],#shapeZ 7:[(0,0),(-1,0),(0,-1),(1,-1)]}#shapeS #旋转坐标控制 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 #Mapcanrecordthelocationofeverysquare.i宽j高 self.map={} #全部置0 foriinrange(self.width): forjinrange(-4,self.height): self.map[(i,j)]=0 #添加边界 foriinrange(-4,self.width+4): self.map[(i,self.height)]=1 forjinrange(-4,self.height+4): foriinrange(-4,0): self.map[(i,j)]=1 forjinrange(-4,self.height+4): foriinrange(self.width,self.width+4): self.map[(i,j)]=1 #初始化分数0默认不加快按下时加快 self.score=0 self.isFaster=False #创建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("",self.rotate) self.area.bind(" ",self.moveLeft) self.area.bind(" ",self.moveRight) self.area.bind(" ",self.moveFaster) self.area.bind(" ",self.rotate) self.area.bind(" ",self.moveLeft) self.area.bind(" ",self.moveRight) self.area.bind(" ",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='NewGame',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='Howtoplay',command=self.rule) self.helpMenu.add_separator() self.helpMenu.add_command(label='About...',command=self.about) #先将核心块的所在位置在map中的元素设为1,通过self.shapeDict获取其余方块位置,将map中对应元素设为1。 defgetLocation(self): map[(core[0],core[1])]=1 foriinrange(4): map[((core[0]+getNew[i][0]), (core[1]+getNew[i][1]))]=1 #判断方块下移一格后对应位置map中的元素是否为一,是,则不可移动,返回False;否,可以移动,返回True。 defcanMove(self): foriinrange(4): ifmap[(core[0]+getNew[i][0]),(core[1]+1+getNew[i][1])]==1: returnFalse returnTrue #先用randRange获取1~7中的随机整数,随机到某一整数,那么访问self.shapeDict,获取这种形状方块的核心块及其他方块的相对位置。 #访问颜色字典,获取此方块的颜色。建立循环,当方块可移动时(whileself.canMove():),且暂停键未被摁下(ifisPause:), #核心块纵坐标加一,根据核心块及其他方块对于核心块的相对位置,画出四个方块。用self.getLocation()函数获取方块的位置。 defdrawNew(self): globalnext globalgetNew globalcore next=randrange(1,8) #形状 self.getNew=self.shapeDict[next] getNew=self.getNew core=[4,-2] time=0.2 whileself.canMove(): ifisPause: core[1]+=1 self.drawSquare() ifself.isFaster: sleep(time-0.15) else: sleep(time+0.22) self.isFaster=False else: self.drawSquare() sleep(time) self.getLocation() #绘制当前方块 defdrawSquare(self): self.area.delete("new") foriinrange(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代表该块所在行数,每次遍历map,建立对于range(self.height)的for循环,删去每一行, #若map什么地方的元素为1,画出这一位置的方块,不断更新。这样可以画出底部方块。 defdrawBottom(self): forjinrange(self.height): self.area.delete('bottom'+str(j)) foriinrange(self.width): ifmap[(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,行数map(i,j)=map(i-1,j)(即所有之上的行下移) #,那么后续画底部方块时,可实现消行。 defisFill(self): forjinrange(self.height): t=0 foriinrange(self.width): ifmap[(i,j)]==1: t=t+1 ift==self.width: self.getScore() self.deleteLine(j) #加分 defgetScore(self): scoreValue=eval(self.scoreLabel2['text']) scoreValue+=10 self.scoreLabel2.config(text=str(scoreValue)) #消行 defdeleteLine(self,j): fortinrange(j,2,-1): foriinrange(self.width): map[(i,t)]=map[(i,t-1)] foriinrange(self.width): map[(i,0)]=0 self.drawBottom() #遍历每一行,若从顶部到底部map每一行都有某一个元素或更多元素为1, #那么说明方块以顶到最上端,游戏结束。此处不可以简单判定最上一行是否有元素为1就判定结束, #若这样会产生顶部有新的方块产生,然后导致顶部有元素为1,误判为游戏结束。 defisOver(self): t=0 forjinrange(self.height): foriinrange(self.width): ifself.map[(i,j)]==1: t+=1 break ift>=self.height: returnFalse else: returnTrue #先判断方块是否可以旋转(针对其靠近边界时)。先将其现在所在位置对应map中的元素改为0,判断其旋 #转后位置对应map中的元素是否有一,若有,说明其旋转后的位置已经被占,是不能旋转的,返回值为False #。否则为可旋转,返回值True。若已判定可以旋转,那么访问self.rotateDict,得出旋转以后所有小块的位置 #变换,将变换以后的位置对应map的元素设为1,旋转便已完成。 defcanRotate(self): foriinrange(4): map[((core[0]+getNew[i][0]), (core[1]+getNew[i][1]))]=0 foriinrange(4): ifmap[((core[0]+self.rotateDict[getNew[i]][0]), (core[1]+self.rotateDict[getNew[i]][1]))]==1: returnFalse returnTrue #旋转 defrotate(self,event): ifnext!=2: ifself.canRotate(): foriinrange(4): getNew[i]=self.rotateDict[getNew[i]] self.drawSquare() ifnotself.canMove(): foriinrange(4): map[((core[0]+getNew[i][0]),(core[1]+getNew[i][1]))]=1 #先判断是否左移/右移,同样,将方块现在所处位置的map中元素设为0,看其移动后的位置上map的元素是否有1, #若有,说明这一位置已被占据或已到边界,不可移动,返回False。若可移动,返回True。按下左键,若可 #以移动,核心块的横坐标减1,由于我们只讨论其他小块对于核心块的相对位置,所以其他小块的位置自动随 #核心块的位置移动而移动。将移动过后的位置对应map中的元素设为1。 defcanLeft(self): coreNow=core foriinrange(4): map[((coreNow[0]+getNew[i][0]),(coreNow[1]+getNew[i][1]))]=0 foriinrange(4): ifmap[((coreNow[0]+getNew[i][0]-1),(coreNow[1]+getNew[i][1]))]==1: returnFalse returnTrue #左移 defmoveLeft(self,event): ifself.canLeft(): core[0]-=1 self.drawSquare() self.drawBottom() ifnotself.canMove(): foriinrange(4): map[((core[0]+getNew[i][0]),(core[1]+getNew[i][1]))]=1 #判断右移 defcanRight(self): foriinrange(4): map[((core[0]+getNew[i][0]),(core[1]+getNew[i][1]))]=0 foriinrange(4): ifmap[((core[0]+getNew[i][0]+1),(core[1]+getNew[i][1]))]==1: returnFalse returnTrue #右移 defmoveRight(self,event): ifself.canRight(): core[0]+=1 self.drawSquare() self.drawBottom() ifnotself.canMove(): foriinrange(4): map[((core[0]+getNew[i][0]),(core[1]+getNew[i][1]))]=1 #初始化中有一self.isFaster的变量被设为False,当其为False时, #程序中的sleep(time)中time的值为0.35,而按下下键,self.isFaster变为True, #time变成0.05,通过调整sleep()中变量的大小可以调节方块运动的速度。 #此功能通过if语句实现。 defmoveFaster(self,event): self.isFaster=True ifnotself.canMove(): foriinrange(4): map[((core[0]+getNew[i][0]),(core[1]+getNew[i][1]))]=1 #runtheprograme defrun(self): self.isFill() self.drawNew() self.drawBottom() #playthegame defplay(self): self.startBut.config(state=DISABLED) globalisPause isPause=True globalmap map=self.map whileTrue: ifself.isOver(): self.run() else: break self.over() #重新开始游戏 defrestart(self): self.core=[4,-2] self.map={} foriinrange(self.width): forjinrange(-4,self.height): self.map[(i,j)]=0 foriinrange(-1,self.width): self.map[(i,self.height)]=1 forjinrange(-4,self.height+1): self.map[(-1,j)]=1 self.map[(self.width,j)]=1 self.score=0 self.t=0.07 forjinrange(self.height): self.area.delete('bottom'+str(j)) self.play() #结束后告诉用户失败 defover(self): feedback=messagebox.askquestion("YouLose!","YouLose!\nDoyouwanttorestart?") iffeedback=='yes': self.restart() else: self.root.destroy() #退出 defisQuit(self): askQuit=messagebox.askquestion("Quit","Areyousuretoquit?") ifaskQuit=='yes': self.root.destroy() exit() #判断是否按下restart defisRestart(self): askRestart=messagebox.askquestion("Restart","Areyousuretorestart?") ifaskRestart=='yes': self.restart() else: return #每次一按下暂停键,isPause=notisPause,当isPause=True时,由于之前提到过的ifisPause:语句, #方块可以移动,游戏运行。当按下暂停键以后,isPause值为False,方块将不可移动。同时,isPause值为False时 #,暂停键变为开始键,即标签由Pause改为Resume,当isPause值为True时,Resume改为Pause。这一功能由if语句实现。 defisPause(self): globalisPause isPause=notisPause ifnotisPause: self.pauseBut["text"]="Resume" else: self.pauseBut["text"]="Pause" #帮助 defrule(self): ruleTop=Toplevel() ruleTop.title('Help') ruleTop.geometry('800x400') rule="Start:Pressthestartbuttonorchoosetheoption'Continue'tostartthegame.\n%-s%-s%-s%-s%-s%-s%-s%-s%-s%-s%-s%-s%-s%-s"%("Restart:Presstherestartbuttonorchoosetheoption'NewGame'toresatrtthegame.\n","EnjoytheTerisgame!Havefun!") ruleLabel=Label(ruleTop,text=rule,fg='blue',font=(18)) ruleLabel.place(x=50,y=50) #显示有关信息 defabout(self): aboutTop=Toplevel() aboutTop.title('About') aboutTop.geometry('300x150') about="Teris.py\n\ ByProgrammerLee\n\ AllRightsReserved." aboutLabel=Label(aboutTop,font=('Curier',20),fg='darkblue',text=about) aboutLabel.pack() #Getintomainloop defmainloop(self): self.root.mainloop() #TerisPlay.py #GameTeris #ByprogrammerFYJ fromterisimport* defmain(): teris=Teris() teris.mainloop() main()
运行结构如图所示:
更多俄罗斯方块精彩文章请点击专题:俄罗斯方块游戏集合进行学习。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。