pygame实现俄罗斯方块游戏(AI篇2)


Posted in Python onOctober 29, 2019

继续pygame实现俄罗斯方块游戏(AI篇1)的代码更新

一、消除后才做评价

上一篇我们是对方块落下的位置和落下后出来的空洞进行了评价,但是这些评价都是没有计算消除的,以至于机器人现在不会考虑去进行那些完全不会留下空洞的消除,比如下面这种消除。
pygame实现俄罗斯方块游戏(AI篇2)

但我们知道这种消除是不会产生空洞的。
所以我们要在计算评价的时候最好计算消除以后的评价。
我们只要在Matrix的函数里加一个do_clear函数来进行消除

def do_clear(self):
 for i in range(self.rows-1,-1,-1):
 if sum(self.cols*i:self.cols*(i+1))==self.cols:
 self.matrix[self.cols:self.cols*(i+1)]=self.matrix[0:self.cols*i]

然后在clone_matrix.fill_block(center_shape, xdiff=xdiff, ydiff=max_yindex)之后加一行

clone_matrix.do_clear()

pygame实现俄罗斯方块游戏(AI篇2)

现在机器人比以前聪明了一点,但是还有问题,只要有下面两个问题:

1.当有更好的消除方案时,机器人并没有选择更好的方案(比如可以消除两行,但是机器人选择了消除一行)。
2.人玩的时候会避免空的列两边堆叠太高,而是优先在远离空的列附近填。

下面我们进行这些修改。

二、消除时考虑获得更高分

我们在Matrix的do_clear函数里增加一个clear_num来计算消除了多少行

def do_clear(self):
 clear_num = 0
 for i in range(self.rows-1,-1,-1):
 if sum(self.data[self.cols*i:self.cols*(i+1)])==self.cols:
 self.data[self.cols:self.cols*(i+1)]=self.data[0:self.cols*i]
 clear_num+=1
 return clear_num

在计算的地方加这样两行

clear_num=clone_matrix.do_clear()
score += clear_num * 5

这样每多消除一行会多得到5分,会激励机器人在单次消除中去寻找更好的消除方案。

三、避免空列附近的填塞

首先空列的定义,我们可以认为像下面的图中,1的位置还不能算完全的空列,因为列右侧高起的是两格,拯救的机会比2处大很多,2处两边都已经高起3格,再这样下去只有等长条了。

pygame实现俄罗斯方块游戏(AI篇2)

所以我们在Matrix里加一个空列的获取函数

def get_empty_col(self):
 miny_arr=[]
 for x in range(self.cols):
 miny=19
 for y in range(self.rows):
 miny=y
 if self.get_val(x,y) == 1:break
 miny_arr.append(miny)
 empty_arr=[]
 if miny_arr[1] - miny_arr[0] > 2: empty_arr.append((self.cols,miny_arr[1] - miny_arr[0]))
 if miny_arr[self.cols-2] - miny_arr[self.cols-1] > 2: empty_arr.append((miny_arr[self.cols-2] - miny_arr[self.cols-1],self.cols))
 for x in range(1,self.cols-1):
 if miny_arr[x-1]-miny_arr[x]>2 or miny_arr[x+1]-miny_arr[x]>2: empty_arr.append((miny_arr[x-1]-miny_arr[x],miny_arr[x+1]-miny_arr[x]))
 return empty_arr

在AIPlayer里增加一个get_cost_of_emptycol函数

def get_cost_of_emptycol(self, empty_arr):
 cost = 0
 for l,r in empty_arr:
 if l>2 and r>2: cost += (l+r)*2
 elif l>2: cost += l
 else: cost += r
 return cost

在计算分数的地方增加两行程序

empty_arr = clone_matrix.get_empty_col()
score -= self.get_cost_of_emptycol(empty_arr)

现在机器人又厉害了一些,基本上没有比较糟糕的情况下,机器人已经不会gameover了

pygame实现俄罗斯方块游戏(AI篇2)

四、已成空洞上方位置的避免

比如下图

pygame实现俄罗斯方块游戏(AI篇2)

我们一定会尽可能避免在红框的位置堆叠,因为这样有助于我们消除空洞上方的方块后可以尽快进入空洞进行新的消除,但是机器人现在还没有这个考虑,所以我们在Matrix里继续增加一个空洞上方方块数的计算。
函数实现如下: 

def get_block_above_hole(self):
 blocks=0
 for x in range(0,self.cols):
 for y in range(1,self.rows):
 if self.get_val(x,y) == 0 and self.get_val(x,y-1) == 1: 
 blocks += sum(self.data[x:(y*self.cols+x):self.cols])
 return blocks

在计算分数的地方我们再加一行

score -= clone_matrix.get_block_above_hole()

这样机器人就会考虑让空洞上方的方块尽可能少。

附下目前的完整程序。

# -*- coding=utf-8 -*-
import random
import pygame
from pygame.locals import KEYDOWN,K_LEFT,K_RIGHT,K_UP,K_DOWN,K_SPACE
import pickle,os

ROW_COUNT=20
COL_COUNT=10
SCORE_MAP=(100,300,800,1600)

class Matrix(object):
 rows = 0
 cols = 0
 data = []
 def __init__(self, rows, cols, data=None):
 self.rows = rows
 self.cols = cols 
 if data is None: data = [0 for i in range(rows*cols)]
 self.data = data

 def set_val(self, x, y, val):
 self.data[y*self.cols+x] = val

 def get_val(self, x, y):
 return self.data[y*self.cols+x]
 
 def cross_block(self, rect_arr, xdiff=0, ydiff=0):
 for x,y in rect_arr:
 #if x+xdiff>=0 and x+xdiff<self.cols and y+ydiff>=0 and y+ydiff<self.rows:
 if self.get_val(x+xdiff,y+ydiff) == 1: return True
 return False

 def get_block_above_hole(self):
 blocks=0
 for x in range(0,self.cols):
 for y in range(1,self.rows):
 if self.get_val(x,y) == 0 and self.get_val(x,y-1) == 1: 
 blocks += sum(self.data[x:(y*self.cols+x):self.cols])

 return blocks

 def get_hole_number(self):
 hole_num=0
 for x in range(0,self.cols):
 for y in range(1,self.rows):
 if self.get_val(x,y) == 0 and self.get_val(x,y-1) == 1: 
 hole_num+=1
 return hole_num

 def clone(self):
 clone_matrix=Matrix(self.rows, self.cols, list(self.data))
 return clone_matrix

 def fill_block(self, rect_arr, xdiff=0, ydiff=0):
 for x,y in rect_arr:
 self.set_val(x+xdiff,y+ydiff, 1)

 def do_clear(self):
 clear_num = 0
 for i in range(self.rows-1,-1,-1):
 if sum(self.data[self.cols*i:self.cols*(i+1)])==self.cols:
 self.data[self.cols:self.cols*(i+1)]=self.data[0:self.cols*i]
 clear_num+=1
 return clear_num

 def get_empty_col(self):
 miny_arr=[]
 for x in range(self.cols):
 miny=19
 for y in range(self.rows):
 miny=y
 if self.get_val(x,y) == 1:break
 miny_arr.append(miny)
 empty_arr=[]
 if miny_arr[1] - miny_arr[0] > 2: empty_arr.append((self.cols,miny_arr[1] - miny_arr[0]))
 if miny_arr[self.cols-2] - miny_arr[self.cols-1] > 2: empty_arr.append((miny_arr[self.cols-2] - miny_arr[self.cols-1],self.cols))
 for x in range(1,self.cols-1):
 if miny_arr[x-1]-miny_arr[x]>2 or miny_arr[x+1]-miny_arr[x]>2: empty_arr.append((miny_arr[x-1]-miny_arr[x],miny_arr[x+1]-miny_arr[x]))
 return empty_arr

 def print_matrix(self):
 for i in range(self.rows):
 print self.data[self.cols*i:self.cols*(i+1)]

class Player(object):
 auto_mode=False
 def __init__(self):
 pass
 def run(self, panel): 
 pass

class HumanPlayer(Player):
 def __init__(self):
 super(Player, self).__init__()

class AIPlayer(Player):
 cal_block_id=-1 
 ctl_arr=[] # control arr, 1=change、2=left、3=right、4=down
 auto_mode=True
 ai_diff_ticks = 100 #timespan between two controls
 
 def __init__(self):
 super(Player, self).__init__()
 self.ctl_ticks = pygame.time.get_ticks() + self.ai_diff_ticks

 def get_cost_of_emptycol(self, empty_arr):
 cost = 0
 for l,r in empty_arr:
 if l>2 and r>2: cost += (l+r)*2
 elif l>2: cost += l
 else: cost += r
 return cost

 def cal_best_arr(self, panel):
 matrix = panel.get_rect_matrix()
 cur_shape_id = panel.moving_block.shape_id
 shape_num = panel.moving_block.shape_num
 max_score = -10000
 best_arr = []
 for i in range(shape_num):
 tmp_shape_id = cur_shape_id + i
 if tmp_shape_id >= shape_num: tmp_shape_id = tmp_shape_id % shape_num
 tmp_shape = panel.moving_block.get_shape(sid=tmp_shape_id)
 center_shape = []
 for x,y in tmp_shape: center_shape.append((x+COL_COUNT/2-2,y-2))
 minx = COL_COUNT
 maxx = 0
 miny = ROW_COUNT
 maxy = -2
 for x,y in center_shape:
 if x<minx: minx = x
 if x>maxx: maxx = x
 if y<miny: miny = y
 if y>maxy: maxy = y

 for xdiff in range(-minx,COL_COUNT-maxx): 
 arr = [1 for _ in range(i)] 
 if xdiff < 0: [arr.append(2) for _ in range(-xdiff)]
 if xdiff > 0: [arr.append(3) for _ in range(xdiff)]

 max_yindex = -miny
 for yindex in range(-miny, ROW_COUNT-maxy):
 if matrix.cross_block(center_shape, xdiff=xdiff, ydiff=yindex):
 break
 max_yindex = yindex
 score = sum([y+max_yindex for x,y in center_shape])

 # clone matrix and fill new block to calculate holes
 clone_matrix = matrix.clone()
 clone_matrix.fill_block(center_shape, xdiff=xdiff, ydiff=max_yindex)
 clear_num = clone_matrix.do_clear()
 score -= clone_matrix.get_block_above_hole()
 empty_arr = clone_matrix.get_empty_col()
 score -= self.get_cost_of_emptycol(empty_arr)
 score += clear_num * 5
 score -= clone_matrix.get_hole_number() * COL_COUNT

 if score > max_score: 
 max_score = score
 best_arr = arr
 self.ctl_arr = best_arr+[4]

 def run(self, panel):
 if pygame.time.get_ticks() < self.ctl_ticks: return
 self.ctl_ticks += self.ai_diff_ticks
 if panel.block_id == self.cal_block_id: # block_id not change
 if len(self.ctl_arr)>0:
 ctl = self.ctl_arr.pop(0)
 if ctl == 1: panel.change_block()
 if ctl == 2: panel.control_block(-1,0)
 if ctl == 3: panel.control_block(1,0)
 if ctl == 4:
 flag = panel.move_block()
 while flag==1: 
 flag = panel.move_block()

 else: # block_id is new
 self.cal_block_id = panel.block_id
 self.cal_best_arr(panel)
 

class RectInfo(object):
 def __init__(self, x, y, color):
 self.x = x
 self.y = y
 self.color = color

class HintBox(object):
 next_block=None
 def __init__(self, bg, block_size, position):
 self._bg=bg;
 self._x,self._y,self._width,self._height=position
 self._block_size=block_size
 self._bgcolor=[0,0,0]

 def take_block(self):
 block = self.next_block
 if block is None: # make first block
 block = create_block()
 
 self.next_block = create_block()
 return block

 def paint(self):
 mid_x=self._x+self._width/2
 pygame.draw.line(self._bg,self._bgcolor,[mid_x,self._y],[mid_x,self._y+self._height],self._width) 
 bz=self._block_size
 
 if self.next_block:
 arr = self.next_block.get_rect_arr()
 minx,miny=arr[0]
 maxx,maxy=arr[0]
 for x,y in arr:
 if x<minx: minx=x
 if x>maxx: maxx=x
 if y<miny: miny=y
 if y>maxy: maxy=y
 w=(maxx-minx)*bz
 h=(maxy-miny)*bz
 
 cx=self._width/2-w/2-minx*bz-bz/2 
 cy=self._height/2-h/2-miny*bz-bz/2

 for rect in arr:
 x,y=rect
 pygame.draw.line(self._bg,self.next_block.color,[self._x+x*bz+cx+bz/2,self._y+cy+y*bz],[self._x+x*bz+cx+bz/2,self._y+cy+(y+1)*bz],bz)
 pygame.draw.rect(self._bg,[255,255,255],[self._x+x*bz+cx,self._y+y*bz+cy,bz+1,bz+1],1)

class ScoreBox(object):
 total_score = 0
 high_score = 0
 db_file = 'tetris.db'
 def __init__(self, bg, block_size, position):
 self._bg=bg;
 self._x,self._y,self._width,self._height=position
 self._block_size=block_size
 self._bgcolor=[0,0,0]
 
 if os.path.exists(self.db_file): self.high_score = pickle.load(open(self.db_file,'rb'))

 def paint(self):
 myfont = pygame.font.Font(None,36)
 white = 255,255,255
 textImage = myfont.render('High: %06d'%(self.high_score), True, white)
 self._bg.blit(textImage, (self._x,self._y))
 textImage = myfont.render('Score:%06d'%(self.total_score), True, white)
 self._bg.blit(textImage, (self._x,self._y+40))

 def add_score(self, score):
 self.total_score += score
 if self.total_score > self.high_score:
 self.high_score=self.total_score
 pickle.dump(self.high_score, open(self.db_file,'wb+'))

class Panel(object): 
 block_id=0
 rect_arr=[] 
 moving_block=None 
 hint_box=None
 score_box=None
 def __init__(self,bg, block_size, position):
 self._bg=bg;
 self._x,self._y,self._width,self._height=position
 self._block_size=block_size
 self._bgcolor=[0,0,0]
 
 def get_rect_matrix(self):
 matrix = Matrix(ROW_COUNT, COL_COUNT)
 for rect_info in self.rect_arr:
 matrix.set_val(rect_info.x, rect_info.y, 1)
 return matrix

 def add_block(self,block):
 for x,y in block.get_rect_arr():
 self.rect_arr.append(RectInfo(x,y, block.color))

 def create_move_block(self):
 self.block_id+=1
 block = self.hint_box.take_block()
 #block = create_block()
 block.move(COL_COUNT/2-2,-2) # move block to top center
 self.moving_block=block

 def check_overlap(self, diffx, diffy, check_arr=None):
 if check_arr is None: check_arr = self.moving_block.get_rect_arr()
 for x,y in check_arr:
 for rect_info in self.rect_arr:
 if x+diffx==rect_info.x and y+diffy==rect_info.y:
 return True
 return False

 def control_block(self, diffx, diffy):
 if self.moving_block.can_move(diffx,diffy) and not self.check_overlap(diffx, diffy):
 self.moving_block.move(diffx,diffy)

 def change_block(self):
 if self.moving_block:
 new_arr = self.moving_block.change()
 if new_arr and not self.check_overlap(0, 0, check_arr=new_arr): 
 self.moving_block.rect_arr=new_arr


 def move_block(self):
 if self.moving_block is None: create_move_block()
 if self.moving_block.can_move(0,1) and not self.check_overlap(0,1): 
 self.moving_block.move(0,1)
 return 1
 else:
 self.add_block(self.moving_block)
 self.check_clear()

 for rect_info in self.rect_arr:
 if rect_info.y<0: return 9 # gameover
 self.create_move_block()
 return 2

 def check_clear(self):
 tmp_arr = [[] for i in range(20)]
 
 for rect_info in self.rect_arr:
 if rect_info.y<0: return
 tmp_arr[rect_info.y].append(rect_info)

 clear_num=0
 clear_lines=set([])
 y_clear_diff_arr=[[] for i in range(20)]
 
 for y in range(19,-1,-1):
 if len(tmp_arr[y])==10:
 clear_lines.add(y)
 clear_num += 1
 y_clear_diff_arr[y] = clear_num

 if clear_num>0:
 new_arr=[]
 
 for y in range(19,-1,-1):
 if y in clear_lines: continue
 tmp_row = tmp_arr[y]
 y_clear_diff=y_clear_diff_arr[y]
 for rect_info in tmp_row:
 #new_arr.append([x,y+y_clear_diff])
 new_arr.append(RectInfo(rect_info.x, rect_info.y+y_clear_diff, rect_info.color))
 
 self.rect_arr = new_arr
 score = SCORE_MAP[clear_num-1]
 self.score_box.add_score(score)


 def paint(self):
 mid_x=self._x+self._width/2
 pygame.draw.line(self._bg,self._bgcolor,[mid_x,self._y],[mid_x,self._y+self._height],self._width) # 用一个粗线段来填充背景
 
 bz=self._block_size
 for rect_info in self.rect_arr:
 x=rect_info.x
 y=rect_info.y
 pygame.draw.line(self._bg,rect_info.color,[self._x+x*bz+bz/2,self._y+y*bz],[self._x+x*bz+bz/2,self._y+(y+1)*bz],bz)
 pygame.draw.rect(self._bg,[255,255,255],[self._x+x*bz,self._y+y*bz,bz+1,bz+1],1)
 
 if self.move_block:
 for rect in self.moving_block.get_rect_arr():
 x,y=rect
 pygame.draw.line(self._bg,self.moving_block.color,[self._x+x*bz+bz/2,self._y+y*bz],[self._x+x*bz+bz/2,self._y+(y+1)*bz],bz)
 pygame.draw.rect(self._bg,[255,255,255],[self._x+x*bz,self._y+y*bz,bz+1,bz+1],1)

class Block(object):
 sx=0
 sy=0
 def __init__(self):
 self.rect_arr=[]

 def get_rect_arr(self): 
 return self.rect_arr

 def move(self,xdiff,ydiff):
 self.sx+=xdiff
 self.sy+=ydiff
 self.new_rect_arr=[]
 for x,y in self.rect_arr:
 self.new_rect_arr.append((x+xdiff,y+ydiff))
 self.rect_arr=self.new_rect_arr

 def can_move(self,xdiff,ydiff):
 for x,y in self.rect_arr:
 if y+ydiff>=20: return False
 if x+xdiff<0 or x+xdiff>=10: return False
 return True

 def change(self):
 self.shape_id+=1 
 if self.shape_id >= self.shape_num: 
 self.shape_id=0

 arr = self.get_shape()
 new_arr = []
 for x,y in arr:
 if x+self.sx<0 or x+self.sx>=10: 
 self.shape_id -= 1
 if self.shape_id < 0: self.shape_id = self.shape_num - 1
 return None 

 new_arr.append([x+self.sx,y+self.sy])

 return new_arr

class LongBlock(Block):
 shape_id=0
 shape_num=2
 def __init__(self, n=None): 
 super(LongBlock, self).__init__()
 if n is None: n=random.randint(0,1)
 self.shape_id=n
 self.rect_arr=self.get_shape()
 self.color=(50,180,50)

 def get_shape(self, sid=None):
 if sid is None: sid = self.shape_id
 return [(1,0),(1,1),(1,2),(1,3)] if sid==0 else [(0,2),(1,2),(2,2),(3,2)]

class SquareBlock(Block): 
 shape_id=0
 shape_num=1
 def __init__(self, n=None):
 super(SquareBlock, self).__init__()
 self.rect_arr=self.get_shape()
 self.color=(0,0,255)

 def get_shape(self, sid=None):
 if sid is None: sid = self.shape_id
 return [(1,1),(1,2),(2,1),(2,2)]

class ZBlock(Block): 
 shape_id=0
 shape_num=2
 def __init__(self, n=None):
 super(ZBlock, self).__init__()
 if n is None: n=random.randint(0,1)
 self.shape_id=n
 self.rect_arr=self.get_shape()
 self.color=(30,200,200)

 def get_shape(self, sid=None):
 if sid is None: sid = self.shape_id
 return [(2,0),(2,1),(1,1),(1,2)] if sid==0 else [(0,1),(1,1),(1,2),(2,2)]

class SBlock(Block):
 shape_id=0
 shape_num=2
 def __init__(self, n=None):
 super(SBlock, self).__init__()
 if n is None: n=random.randint(0,1)
 self.shape_id=n
 self.rect_arr=self.get_shape()
 self.color=(255,30,255)

 def get_shape(self, sid=None):
 if sid is None: sid = self.shape_id
 return [(1,0),(1,1),(2,1),(2,2)] if sid==0 else [(0,2),(1,2),(1,1),(2,1)]

class LBlock(Block): 
 shape_id=0
 shape_num=4
 def __init__(self, n=None):
 super(LBlock, self).__init__()
 if n is None: n=random.randint(0,3)
 self.shape_id=n
 self.rect_arr=self.get_shape()
 self.color=(200,200,30)

 def get_shape(self, sid=None):
 if sid is None: sid = self.shape_id
 if sid==0: return [(1,0),(1,1),(1,2),(2,2)]
 elif sid==1: return [(0,1),(1,1),(2,1),(0,2)]
 elif sid==2: return [(0,0),(1,0),(1,1),(1,2)]
 else: return [(0,1),(1,1),(2,1),(2,0)]

class JBlock(Block):
 shape_id=0
 shape_num=4
 def __init__(self, n=None):
 super(JBlock, self).__init__()
 if n is None: n=random.randint(0,3)
 self.shape_id=n
 self.rect_arr=self.get_shape()
 self.color=(200,100,0)

 def get_shape(self, sid=None):
 if sid is None: sid = self.shape_id
 if sid==0: return [(1,0),(1,1),(1,2),(0,2)]
 elif sid==1: return [(0,1),(1,1),(2,1),(0,0)]
 elif sid==2: return [(2,0),(1,0),(1,1),(1,2)]
 else: return [(0,1),(1,1),(2,1),(2,2)]

class TBlock(Block):
 shape_id=0
 shape_num=4
 def __init__(self, n=None):
 super(TBlock, self).__init__()
 if n is None: n=random.randint(0,3)
 self.shape_id=n
 self.rect_arr=self.get_shape()
 self.color=(255,0,0)

 def get_shape(self, sid=None):
 if sid is None: sid = self.shape_id
 if sid==0: return [(0,1),(1,1),(2,1),(1,2)]
 elif sid==1: return [(1,0),(1,1),(1,2),(0,1)]
 elif sid==2: return [(0,1),(1,1),(2,1),(1,0)]
 else: return [(1,0),(1,1),(1,2),(2,1)]

def create_block():
 n = random.randint(0,18)
 if n==0: return SquareBlock(n=0)
 elif n==1 or n==2: return LongBlock(n=n-1)
 elif n==3 or n==4: return ZBlock(n=n-3)
 elif n==5 or n==6: return SBlock(n=n-5)
 elif n>=7 and n<=10: return LBlock(n=n-7)
 elif n>=11 and n<=14: return JBlock(n=n-11)
 else: return TBlock(n=n-15)

def run():
 pygame.init()
 space=30
 main_block_size=30
 main_panel_width=main_block_size*COL_COUNT
 main_panel_height=main_block_size*ROW_COUNT
 screencaption = pygame.display.set_caption('Tetris')
 screen = pygame.display.set_mode((main_panel_width+160+space*3,main_panel_height+space*2)) 
 main_panel=Panel(screen,main_block_size,[space,space,main_panel_width,main_panel_height])
 hint_box=HintBox(screen,main_block_size,[main_panel_width+space+space,space,160,160])
 score_box=ScoreBox(screen,main_block_size,[main_panel_width+space+space,160+space*2,160,160])
 
 main_panel.hint_box=hint_box
 main_panel.score_box=score_box

 pygame.key.set_repeat(200, 30)
 main_panel.create_move_block()

 diff_ticks = 300 
 ticks = pygame.time.get_ticks() + diff_ticks

 player = AIPlayer()

 pause=0
 game_state = 1 # game status 1.normal 2.gameover
 while True:
 for event in pygame.event.get():
 if event.type == pygame.QUIT:
 pygame.quit()
 exit()
 if event.type == KEYDOWN:
 if event.key==97: pause=1-pause # press a to pause
 if event.key==112: # for debug where press p
 main_panel.get_rect_matrix().print_matrix()
 if player.auto_mode:continue
 if event.type == KEYDOWN:
 if event.key == K_LEFT: main_panel.control_block(-1,0)
 if event.key == K_RIGHT: main_panel.control_block(1,0)
 if event.key == K_UP: main_panel.change_block()
 if event.key == K_DOWN: main_panel.control_block(0,1)
 if event.key == K_SPACE:
 flag = main_panel.move_block()
 while flag==1: 
 flag = main_panel.move_block()
 if flag == 9: game_state = 2
 
 screen.fill((100,100,100)) # make background gray
 main_panel.paint() 
 hint_box.paint() 
 score_box.paint() 

 if game_state == 2:
 myfont = pygame.font.Font(None,30)
 white = 255,255,255
 textImage = myfont.render("Game over", True, white)
 screen.blit(textImage, (160,190))

 pygame.display.update() 

 if pause==1: continue
 if game_state == 1: player.run(main_panel)
 if game_state == 1 and pygame.time.get_ticks() >= ticks:
 ticks+=diff_ticks
 if main_panel.move_block()==9: game_state = 2 # gameover

run()

这篇先到这里,下篇继续优化。

更多关于俄罗斯方块的文章,请点击查看专题:《俄罗斯方块》

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python中文件变化监控示例(watchdog)
Oct 16 Python
Python线性回归实战分析
Feb 01 Python
python3利用venv配置虚拟环境及过程中的小问题小结
Aug 01 Python
pygame游戏之旅 调用按钮实现游戏开始功能
Nov 21 Python
Python中shapefile转换geojson的示例
Jan 03 Python
详解Python中pandas的安装操作说明(傻瓜版)
Apr 08 Python
利用Python产生加密表和解密表的实现方法
Oct 15 Python
将matplotlib绘图嵌入pyqt的方法示例
Jan 08 Python
pytorch 模型的train模式与eval模式实例
Feb 20 Python
Python 窗体(tkinter)下拉列表框(Combobox)实例
Mar 04 Python
jupyter notebook oepncv 显示一张图像的实现
Apr 24 Python
python如何修改文件时间属性
Feb 05 Python
pygame实现俄罗斯方块游戏(AI篇1)
Oct 29 #Python
基于Django统计博客文章阅读量
Oct 29 #Python
pygame实现俄罗斯方块游戏(基础篇3)
Oct 29 #Python
python安装gdal的两种方法
Oct 29 #Python
pygame实现俄罗斯方块游戏(基础篇2)
Oct 29 #Python
pygame实现俄罗斯方块游戏(基础篇1)
Oct 29 #Python
pygame实现五子棋游戏
Oct 29 #Python
You might like
PHP的拦截器实例分析
2014/11/03 PHP
Yii入门教程之Yii安装及hello world
2014/11/25 PHP
基于jquery的当鼠标滚轮到最底端继续加载新数据思路分享(多用于微博、空间、论坛 )
2011/10/10 Javascript
javascript面向对象入门基础详细介绍
2012/09/05 Javascript
Javascript 命名空间模式
2013/11/01 Javascript
PHP中CURL的几个经典应用实例
2015/01/23 Javascript
JavaScript判断IE版本型号
2015/07/27 Javascript
jquery实现移动端点击图片查看大图特效
2020/09/11 Javascript
JS组件Bootstrap实现弹出框和提示框效果代码
2015/12/08 Javascript
AngularJs  Creating Services详解及示例代码
2016/09/02 Javascript
JavaScript中的子窗口与父窗口的互相调用问题
2017/02/08 Javascript
作为老司机使用 React 总结的 11 个经验教训
2017/04/08 Javascript
js制作简单的音乐播放器的示例代码
2017/08/28 Javascript
老生常谈JavaScript面向对象基础与this指向问题
2017/10/16 Javascript
为什么使用koa2搭建微信第三方公众平台的原因
2018/05/16 Javascript
python MNIST手写识别数据调用API的方法
2018/08/08 Python
Python生成器的使用方法和示例代码
2019/03/04 Python
Python实现的对一个数进行因式分解操作示例
2019/06/27 Python
django多个APP的urls设置方法(views重复问题解决)
2019/07/19 Python
Pytorch抽取网络层的Feature Map(Vgg)实例
2019/08/20 Python
Python networkx包的实现
2020/02/14 Python
Python *args和**kwargs用法实例解析
2020/03/02 Python
最新PyCharm从安装到PyCharm永久激活再到PyCharm官方中文汉化详细教程
2020/11/17 Python
VSCode中autopep8无法运行问题解决方案(提示Error: Command failed,usage)
2021/03/02 Python
SteelSeries赛睿官网:游戏外设和配件的领先制造商(耳机、键盘、鼠标和鼠标垫)
2018/06/17 全球购物
技校生自我鉴定范文
2013/09/26 职场文书
给医务人员表扬信
2014/01/12 职场文书
同学会主持词
2014/03/18 职场文书
寄语是什么意思
2014/04/10 职场文书
《桃林那间小木屋》教学反思
2014/05/01 职场文书
平安工地建设方案
2014/05/06 职场文书
保护环境的标语
2014/06/09 职场文书
2014年人大工作总结
2014/12/10 职场文书
2016年119消防宣传日活动总结
2016/04/05 职场文书
最美劳动诗,致敬所有的劳动者!
2019/07/12 职场文书
vue+elementUI实现表格列的显示与隐藏
2022/04/13 Vue.js