python 基于pygame实现俄罗斯方块
一、简单说明
80、90后的小伙伴都玩过“俄罗斯方块”,那种“叱咤风云”场景偶尔闪现在脑海真的是太爽了;如果没有来得及玩过的同学,这次可以真正的自己做一个了
本实例用的是Python3(当然了Python3.53.63.7....都行)+pygame实现的
运行之前需要安装pygame模块,安装命令如下
pipinstallpygame-ihttps://mirrors.aliyun.com/pypi/simple/
二、运行效果
三、完整代码
文件main.py代码如下:
""" 作者:it项目实例网 更多项目实例,请访问:www.itprojects.cn """ importrandom importsys importtime importpygame fromblocksimportblock_s,block_i,block_j,block_l,block_o,block_t,block_z SCREEN_WIDTH,SCREEN_HEIGHT=450,750 BG_COLOR=(40,40,60)#背景色 BLOCK_COL_NUM=10#每行的方格数 SIZE=30#每个小方格大小 BLOCK_ROW_NUM=25#每列的方个数 BORDER_WIDTH=4#游戏区边框宽度 RED=(200,30,30)#红色,GAMEOVER的字体颜色 defjudge_game_over(stop_all_block_list): """ 判断游戏是否结束 """ if"O"instop_all_block_list[0]: returnTrue defchange_speed(score): speed_level=[("1",0.5,0,20),("2",0.4,21,50),("3",0.3,51,100),("4",0.2,101,200),("5",0.1,201,None)] forspeed_info,speed,score_start,score_stopinspeed_level: ifscore_stopandscore_start<=score<=score_stop: returnspeed_info,speed elifscore_stopisNoneandscore>=score_start: returnspeed_info,speed defjudge_lines(stop_all_block_list): """ 判断是否有同一行的方格,如果有则消除 """ #记录刚刚消除的行数 move_row_list=list() #消除满格的行 forrow,lineinenumerate(stop_all_block_list): if"."notinline: #如果这一行没有.那么就意味着全部是O,则消除这一行 stop_all_block_list[row]=['.'for_inrange(len(line))] move_row_list.append(row) #如果没有满格的行,则结束此函数 ifnotmove_row_list: return0 #移动剩余的行到下一行 forrowinmove_row_list: stop_all_block_list.pop(row) stop_all_block_list.insert(0,['.'for_inrange(len(line))]) returnlen(move_row_list)*10 defadd_to_stop_all_block_list(stop_all_block_list,current_block,current_block_start_row,current_block_start_col): """ 将当前已经停止移动的block添加到列表中 """ forrow,lineinenumerate(current_block): forcol,blockinenumerate(line): ifblock!='.': stop_all_block_list[current_block_start_row+row][current_block_start_col+col]="O" defchange_current_block_style(current_block): """ 改变图形的样式 """ #计算出,当前图形样式属于哪个图形 current_block_style_list=None forblock_style_listin[block_s,block_i,block_j,block_l,block_o,block_t,block_z]: ifcurrent_blockinblock_style_list: current_block_style_list=block_style_list #得到当前正在用的图形的索引(下标) index=current_block_style_list.index(current_block) #它的下一个图形的索引 index+=1 #防止越界 index=index%len(current_block_style_list) #返回下一个图形 returncurrent_block_style_list[index] defjudge_move_right(current_block,current_block_start_col): """ 判断是否可以向右移动 """ #先判断列的方式是从右到左 forcolinrange(len(current_block[0])-1,-1,-1): #得到1列的所有元素 col_list=[line[col]forlineincurrent_block] #判断是否碰到右边界 if'O'incol_listandcurrent_block_start_col+col>=BLOCK_COL_NUM: returnFalse returnTrue defjudge_move_left(current_block,current_block_start_col): """ 判断是否可以向左移动 """ #先判断列的方式是从左到右 forcolinrange(len(current_block[0])): #得到1列的所有元素 col_list=[line[col]forlineincurrent_block] #判断是否碰到右边界 if'O'incol_listandcurrent_block_start_col+col<0: returnFalse returnTrue defjudge_move_down(current_block,current_block_start_row,current_block_start_col,stop_all_block_list): """ 判断是否碰撞到其它图形或者底边界 """ #得到其它图形所有的坐标 stop_all_block_position=list() forrow,lineinenumerate(stop_all_block_list): forcol,blockinenumerate(line): ifblock!=".": stop_all_block_position.append((row,col)) #print(stop_all_block_position) #判断碰撞 forrow,lineinenumerate(current_block): if'O'inlineandcurrent_block_start_row+row>=BLOCK_ROW_NUM: #如果当前行有0,且从起始行开始算+当前显示的行,超过了总行数,那么就认为碰到了底部 returnFalse forcol,blockinenumerate(line): ifblock!="."and(current_block_start_row+row,current_block_start_col+col)instop_all_block_position: returnFalse returnTrue defget_block(): """ 创建一个图形 """ block_style_list=random.choice([block_s,block_i,block_j,block_l,block_o,block_t,block_z]) returnrandom.choice(block_style_list) defmain(): pygame.init() screen=pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT)) pygame.display.set_caption('俄罗斯方块') current_block=get_block()#当前图形 current_block_start_row=-2#当前图片从哪一行开始显示图形 current_block_start_col=4#当前图形从哪一列开始显示 next_block=get_block()#下一个图形 last_time=time.time() speed=0.5#降落的速度 speed_info='1'#显示的速度等级 #定义一个列表,用来存储所有的已经停止移动的形状 stop_all_block_list=[['.'foriinrange(BLOCK_COL_NUM)]forjinrange(BLOCK_ROW_NUM)] #字体 font=pygame.font.Font('yh.ttf',24)#黑体24 game_over_font=pygame.font.Font("yh.ttf",72) game_over_font_width,game_over_font_height=game_over_font.size('GAMEOVER') game_again_font_width,game_again_font_height=font.size('鼠标点击任意位置,再来一局') #得分 score=0 #标记游戏是否结束 game_over=False #创建计时器(防止while循环过快,占用太多CPU的问题) clock=pygame.time.Clock() whileTrue: foreventinpygame.event.get(): ifevent.type==pygame.QUIT: sys.exit() elifevent.type==pygame.KEYDOWN: ifevent.key==pygame.K_LEFT: ifjudge_move_left(current_block,current_block_start_col-1): current_block_start_col-=1 elifevent.key==pygame.K_RIGHT: ifjudge_move_right(current_block,current_block_start_col+1): current_block_start_col+=1 elifevent.key==pygame.K_UP: current_block_next_style=change_current_block_style(current_block) ifjudge_move_left(current_block_next_style,current_block_start_col)and\ judge_move_right(current_block_next_style,current_block_start_col)and\ judge_move_down(current_block,current_block_start_row,current_block_start_col,stop_all_block_list): #判断新的样式没有越界 current_block=current_block_next_style elifevent.key==pygame.K_DOWN: #判断是否可以向下移动,如果碰到底部或者其它的图形就不能移动了 ifjudge_move_down(current_block,current_block_start_row+1,current_block_start_col,stop_all_block_list): current_block_start_row+=1 elifevent.type==pygame.MOUSEBUTTONDOWNandevent.button: ifgame_over: #重置游戏用到的变量 current_block=get_block()#当前图形 current_block_start_row=-2#当前图片从哪一行开始显示图形 current_block_start_col=4#当前图形从哪一列开始显示 next_block=get_block()#下一个图形 stop_all_block_list=[['.'foriinrange(BLOCK_COL_NUM)]forjinrange(BLOCK_ROW_NUM)] score=0 game_over=False #判断是否修改当前图形显示的起始行 ifnotgame_overandtime.time()-last_time>speed: last_time=time.time() #判断是否可以向下移动,如果碰到底部或者其它的图形就不能移动了 ifjudge_move_down(current_block,current_block_start_row+1,current_block_start_col,stop_all_block_list): current_block_start_row+=1 else: #将这个图形存储到统一的列表中,这样便于判断是否成为一行 add_to_stop_all_block_list(stop_all_block_list,current_block,current_block_start_row,current_block_start_col) #判断是否有同一行的,如果有就消除,且加上分数 score+=judge_lines(stop_all_block_list) #判断游戏是否结束(如果第一行中间有O那么就表示游戏结束) game_over=judge_game_over(stop_all_block_list) #调整速度 speed_info,speed=change_speed(score) #创建新的图形 current_block=next_block next_block=get_block() #重置数据 current_block_start_col=4 current_block_start_row=-2 #画背景(填充背景色) screen.fill(BG_COLOR) #画游戏区域分隔线 pygame.draw.line(screen,(100,40,200),(SIZE*BLOCK_COL_NUM,0),(SIZE*BLOCK_COL_NUM,SCREEN_HEIGHT),BORDER_WIDTH) #显示当前图形 forrow,lineinenumerate(current_block): forcol,blockinenumerate(line): ifblock!='.': pygame.draw.rect(screen,(20,128,200),((current_block_start_col+col)*SIZE,(current_block_start_row+row)*SIZE,SIZE,SIZE),0) #显示所有停止移动的图形 forrow,lineinenumerate(stop_all_block_list): forcol,blockinenumerate(line): ifblock!='.': pygame.draw.rect(screen,(20,128,200),(col*SIZE,row*SIZE,SIZE,SIZE),0) #画网格线竖线 forxinrange(BLOCK_COL_NUM): pygame.draw.line(screen,(0,0,0),(x*SIZE,0),(x*SIZE,SCREEN_HEIGHT),1) #画网格线横线 foryinrange(BLOCK_ROW_NUM): pygame.draw.line(screen,(0,0,0),(0,y*SIZE),(BLOCK_COL_NUM*SIZE,y*SIZE),1) #显示右侧(得分、速度、下一行图形) #得分 score_show_msg=font.render('得分:',True,(255,255,255)) screen.blit(score_show_msg,(BLOCK_COL_NUM*SIZE+10,10)) score_show_msg=font.render(str(score),True,(255,255,255)) screen.blit(score_show_msg,(BLOCK_COL_NUM*SIZE+10,50)) #速度 speed_show_msg=font.render('速度:',True,(255,255,255)) screen.blit(speed_show_msg,(BLOCK_COL_NUM*SIZE+10,100)) speed_show_msg=font.render(speed_info,True,(255,255,255)) screen.blit(speed_show_msg,(BLOCK_COL_NUM*SIZE+10,150)) #下一个图形(文字提示) next_style_msg=font.render('下一个:',True,(255,255,255)) screen.blit(next_style_msg,(BLOCK_COL_NUM*SIZE+10,200)) #下一个图形(图形) forrow,lineinenumerate(next_block): forcol,blockinenumerate(line): ifblock!='.': pygame.draw.rect(screen,(20,128,200),(320+SIZE*col,(BLOCK_COL_NUM+row)*SIZE,SIZE,SIZE),0) #显示这个方格的4个边的颜色 #左 pygame.draw.line(screen,(0,0,0),(320+SIZE*col,(BLOCK_COL_NUM+row)*SIZE),(320+SIZE*col,(BLOCK_COL_NUM+row+1)*SIZE),1) #上 pygame.draw.line(screen,(0,0,0),(320+SIZE*col,(BLOCK_COL_NUM+row)*SIZE),(320+SIZE*(col+1),(BLOCK_COL_NUM+row)*SIZE),1) #下 pygame.draw.line(screen,(0,0,0),(320+SIZE*col,(BLOCK_COL_NUM+row+1)*SIZE),(320+SIZE*(col+1),(BLOCK_COL_NUM+row+1)*SIZE),1) #右 pygame.draw.line(screen,(0,0,0),(320+SIZE*(col+1),(BLOCK_COL_NUM+row)*SIZE),(320+SIZE*(col+1),(BLOCK_COL_NUM+row+1)*SIZE),1) #显示游戏结束画面 ifgame_over: game_over_tips=game_over_font.render('GAMEOVER',True,RED) screen.blit(game_over_tips,((SCREEN_WIDTH-game_over_font_width)//2,(SCREEN_HEIGHT-game_over_font_height)//2)) #显示"鼠标点击任意位置,再来一局" game_again=font.render('鼠标点击任意位置,再来一局',True,RED) screen.blit(game_again,((SCREEN_WIDTH-game_again_font_width)//2,(SCREEN_HEIGHT-game_again_font_height)//2+80)) #刷新显示(此时窗口才会真正的显示) pygame.display.update() #FPS(每秒钟显示画面的次数) clock.tick(60)#通过一定的延时,实现1秒钟能够循环60次 if__name__=='__main__': main()
文件blocks.py代码如下:
#S形方块 block_s=[['.OO', 'OO.', '...'], ['O..', 'OO.', '.O.']] #Z形方块 block_z=[['OO.', '.OO', '...'], ['.O.', 'OO.', 'O..']] #I型方块 block_i=[['.O..', '.O..', '.O..', '.O..'], ['....', '....', 'OOOO', '....']] #O型方块 block_o=[['OO', 'OO']] #J型方块 block_j=[['O..', 'OOO', '...'], ['.OO', '.O.', '.O.'], ['...', 'OOO', '..O'], ['.O.', '.O.', 'OO.']] #L型方块 block_l=[['..O', 'OOO', '...'], ['.O.', '.O.', '.OO'], ['...', 'OOO', 'O..'], ['OO.', '.O.', '.O.']] #T型方块 block_t=[['.O.', 'OOO', '...'], ['.O.', '.OO', '.O.'], ['...', 'OOO', '.O.'], ['.O.', 'OO.', '.O.']]
以上就是python基于pygame实现俄罗斯方块的详细内容,更多关于python俄罗斯方块的资料请关注毛票票其它相关文章!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。