pygame实现俄罗斯方块游戏(对战篇1)


Posted in Python onOctober 29, 2019

上篇更新到pygame实现俄罗斯方块游戏(AI篇2) ,原本应该继续做优化,不过考虑到完成游戏完整性,这张就先把对战做好。

一、对战的方块管理

定义一个BlockManage管理对战的方块

class BlockManage(object):
 pnum=1
 blocks = []
 def __init__(self,pnum):
 self.pnum=pnum
 self.blocks=[[] for i in range(self.pnum)]

 def get_block(self, pid=0):
 if len(self.blocks[pid]) == 0:
 block = create_block()
 for arr in self.blocks:
 arr.append(pickle.loads(pickle.dumps(block)))
 return self.blocks[pid].pop(0)

根据BlockManage根据传入的玩家id返回方块,保证每个玩家拿到的方块序列十一致的,所以在每次创建方块时存放了玩家数量相同的拷贝,拷贝是避免对象的引用造成对同一个方块对象操作混乱。

然后HintBox里加入block_manage的引用并且在take_block函数里将创建Block改为使用block_manage去取方块

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

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

分别定义一个VirtualHintBox和一个VirtualScoreBox,用于给右下角面板上的

class VirtualHintBox(object):
 pid = 0
 block_manage=None
 next_block=None
 def __init__(self, pid, block_manage):
 print pid
 self.pid=pid
 self.block_manage=block_manage

 def take_block(self):
 block = self.next_block
 if block is None: # make first block
 block = block_manage.get_block(self.pid)
 
 self.next_block = block_manage.get_block(self.pid)
 return block
class VirtualScoreBox(object):
 total_score = 0
 def __init__(self):
 pass

 def add_score(self, score):
 self.total_score += score

pygame实现俄罗斯方块游戏(对战篇1)

使用block_manage并分别传递给主面板的hint_box和右下角面板的VirtualHintBox,右下角面板的定义和初使设置完了以后,将下面的player改为player1和player2两个玩家。

pygame实现俄罗斯方块游戏(对战篇1)

在游戏主循环增加完相应的设置和操作,现在就可以玩人机对战了。

pygame实现俄罗斯方块游戏(对战篇1)

当然如果你把

player1 = HumanPlayer()
player2 = AIPlayer(ai_diff_ticks=350)

改成

player1 = AIPlayer(ai_diff_ticks=150)
player2 = AIPlayer(ai_diff_ticks=350)

当然就是一场机器人对机器人的战斗

pygame实现俄罗斯方块游戏(对战篇1)

二、记分和增加对抗性

增加记分显示比较容易,给VirtualScoreBox实现下paint就行。

class VirtualScoreBox(object):
 total_score = 0
 def __init__(self, bg, position):
 self._bg=bg;
 self._x,self._y,self._width,self._height=position
 self._bgcolor=[0,0,0]

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

 def add_score(self, score):
 self.total_score += score

增加对抗性的话先设置个规则,谁的分数满1000,就可以给另一方增加两层方块作为攻击,为便于计算,我们在Panel里增加一个数字,用于标记对对方攻击的次数。

Panel里增加一个添加障碍物的函数

def add_hinder(self):
 hinder_lines=2
 for tmp in self.rect_arr:
 tmp.y-=hinder_lines
 for y in range(hinder_lines):
 arr=range(10)
 for i in range(5):
 n = random.randint(0,len(arr)-1)
 arr.pop(n)
 for x in arr:
 self.rect_arr.append(RectInfo(x,19-y,[0,0,255]))

Panel里再添加一个获取是否有攻击触发的函数

def get_attach_num(self):
 if self.score_box.total_score /1000 > self.attack_num:
 self.attack_num+=1
 return 1
 else:
 return 0

主循环里再增加攻击的处理

pygame实现俄罗斯方块游戏(对战篇1)

好了,现在对战效果也完成了。

pygame实现俄罗斯方块游戏(对战篇1)

最后再给AIPlayer一个level属性,将level映射为时间间隔

pygame实现俄罗斯方块游戏(对战篇1)

以现在的机器人水平,试了下大概能战胜5级的AIPlayer。

最后附下目前的代码。

# -*- 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
 level=None
 
 def __init__(self, level=None, ai_diff_ticks=100):
 super(Player, self).__init__()
 self.ai_diff_ticks=ai_diff_ticks
 self.level=level
 if level is not None:
 level=int(level)
 if level<1: level=1
 if level>10:level=10
 self.ai_diff_ticks=1000/level

 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 BlockManage(object):
 pnum=1
 blocks = []
 def __init__(self,pnum):
 self.pnum=pnum
 self.blocks=[[] for i in range(self.pnum)]

 def get_block(self, pid=0):
 if len(self.blocks[pid]) == 0:
 block = create_block()
 for arr in self.blocks:
 arr.append(pickle.loads(pickle.dumps(block)))
 return self.blocks[pid].pop(0)

class VirtualHintBox(object):
 pid = 0
 block_manage=None
 next_block=None
 def __init__(self, pid, block_manage):
 print pid
 self.pid=pid
 self.block_manage=block_manage

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

 def paint(self):
 pass

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

 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-10))
 textImage = myfont.render('Score:%06d'%(self.total_score), True, white)
 self._bg.blit(textImage, (self._x,self._y+20))

 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 VirtualScoreBox(object):
 total_score = 0
 def __init__(self, bg, position):
 self._bg=bg;
 self._x,self._y,self._width,self._height=position
 self._bgcolor=[0,0,0]

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

 def add_score(self, score):
 self.total_score += score

class Panel(object): 
 attack_num=0
 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]
 self.block_id=0
 self.rect_arr=[]
 self.moving_block=None
 
 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):
 print block.get_rect_arr()
 for x,y in block.get_rect_arr():
 self.rect_arr.append(RectInfo(x,y, block.color))
 print len(self.rect_arr)

 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 get_attach_num(self):
 if self.score_box.total_score /1000 > self.attack_num:
 self.attack_num+=1
 return 1
 else:
 return 0

 def add_hinder(self):
 hinder_lines=2
 for tmp in self.rect_arr:
 tmp.y-=hinder_lines
 for y in range(hinder_lines):
 arr=range(10)
 for i in range(5):
 n = random.randint(0,len(arr)-1)
 arr.pop(n)
 for x in arr:
 self.rect_arr.append(RectInfo(x,19-y,[0,0,255]))

 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.moving_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)


 self.score_box.paint() 
 self.hint_box.paint() 

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)

block_manage = BlockManage(2) # two players
def run():
 pygame.init()
 addition_width = 160
 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+addition_width+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,addition_width,addition_width],block_manage)
 score_box=ScoreBox(screen,main_block_size,[main_panel_width+space+space,addition_width+space*2,addition_width,addition_width])

 main_panel.hint_box=hint_box
 main_panel.score_box=score_box

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

 battle_panel_width=160
 battle_block_width=battle_panel_width/COL_COUNT
 battle_panel_height=battle_block_width*ROW_COUNT
 battle_panel_x = main_panel_width+space+space+(addition_width-battle_panel_width)
 battle_panel_y = main_panel_height+space-battle_panel_height
 battle_panel=Panel(screen,battle_block_width,[battle_panel_x,battle_panel_y,battle_panel_width,battle_panel_height])
 battle_panel.hint_box=VirtualHintBox(1,block_manage)
 battle_panel.score_box=VirtualScoreBox(screen,[battle_panel_x,battle_panel_y-16,addition_width,16])
 battle_panel.create_move_block()


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

 player1 = HumanPlayer()
 #player1 = AIPlayer(ai_diff_ticks=100)
 player2 = AIPlayer(level=5)

 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 player1.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
 if main_panel.get_attach_num()>0: battle_panel.add_hinder()
 
 screen.fill((100,100,100)) # make background gray
 main_panel.paint() 
 battle_panel.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))
 if game_state == 3:
 myfont = pygame.font.Font(None,30)
 white = 255,255,255
 textImage = myfont.render("Player1 win", True, white)
 screen.blit(textImage, (160,190))

 pygame.display.update() 

 if pause==1: continue
 if game_state == 1: 
 player1.run(main_panel)
 player2.run(battle_panel)
 if game_state == 1 and pygame.time.get_ticks() >= ticks:
 ticks+=diff_ticks
 if main_panel.move_block()==9: game_state = 2 # gameover
 if main_panel.get_attach_num()>0: battle_panel.add_hinder()
 if battle_panel.move_block()==9: game_state = 3 # gameover
 if battle_panel.get_attach_num()>0: main_panel.add_hinder()

run()

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

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

Python 相关文章推荐
Python写的Socks5协议代理服务器
Aug 06 Python
python使用PyGame绘制图像并保存为图片文件的方法
Apr 24 Python
讲解Python中运算符使用时的优先级
May 14 Python
Python 实现简单的shell sed替换功能(实例讲解)
Sep 29 Python
python2.7安装图文教程
Mar 13 Python
Python输入二维数组方法
Apr 13 Python
浅谈DataFrame和SparkSql取值误区
Jun 09 Python
利用Python实现微信找房机器人实例教程
Mar 10 Python
解决pycharm debug时界面下方不出现step等按钮及变量值的问题
Jun 09 Python
python 多线程中join()的作用
Oct 29 Python
python爬虫看看虎牙女主播中谁最“顶”步骤详解
Dec 01 Python
Python实现FTP文件定时自动下载的步骤
Dec 19 Python
Numpy中对向量、矩阵的使用详解
Oct 29 #Python
pygame实现俄罗斯方块游戏(AI篇2)
Oct 29 #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
You might like
如何将一个表单同时提交到两个地方处理
2006/10/09 PHP
ThinkPHP无限级分类原理实现留言与回复功能实例
2014/10/31 PHP
使用PHP访问RabbitMQ消息队列的方法示例
2018/06/06 PHP
PHP常见字符串操作函数与用法总结
2019/03/04 PHP
Laravel框架控制器,视图及模型操作图文详解
2019/12/04 PHP
使用jQuery轻松实现Ajax的实例代码
2010/08/16 Javascript
js+ajax实现获取文件大小的方法
2015/12/08 Javascript
javascript中Date format(js日期格式化)方法小结
2015/12/17 Javascript
关于JS中match() 和 exec() 返回值和属性的测试
2016/03/21 Javascript
jQuery 如何给Carousel插件添加新的功能
2016/04/18 Javascript
当jquery ajax遇上401请求的解决方法
2016/05/19 Javascript
js精准的倒计时函数分享
2016/06/29 Javascript
javascript中replace使用方法总结
2017/03/01 Javascript
微信小程序画布圆形进度条显示效果
2020/11/17 Javascript
详解ES6 系列之异步处理实战
2018/10/26 Javascript
angularjs实现table表格td单元格单击变输入框/可编辑状态示例
2019/02/21 Javascript
微信公众号网页分享功能开发的示例代码
2020/05/27 Javascript
Vue——解决报错 Computed property &quot;****&quot; was assigned to but it has no setter.
2020/12/19 Vue.js
[02:23]1个至宝=115个英雄特效 最“绿”至宝拉比克“魔导师密钥”登场
2018/12/29 DOTA
使用python解析xml成对应的html示例分享
2014/04/02 Python
零基础写python爬虫之抓取百度贴吧代码分享
2014/11/06 Python
pygame学习笔记(5):游戏精灵
2015/04/15 Python
scrapy自定义pipeline类实现将采集数据保存到mongodb的方法
2015/04/16 Python
Python实现线程状态监测简单示例
2018/03/28 Python
Python爬虫抓取代理IP并检验可用性的实例
2018/05/07 Python
树莓派极简安装OpenCv的方法步骤
2019/10/10 Python
Django静态资源部署404问题解决方案
2020/05/11 Python
Python Unittest原理及基本使用方法
2020/11/06 Python
土木工程应届生自荐信
2013/09/24 职场文书
民族团结先进个人材料
2014/02/05 职场文书
批评与自我批评材料
2014/02/15 职场文书
师范教师专业大学生职业生涯规划范文
2014/03/02 职场文书
2015年教师自我评价范文
2015/03/04 职场文书
地道战观后感2000字
2015/06/04 职场文书
CSS3点击按钮圆形进度打钩效果的实现代码
2021/03/30 HTML / CSS
SQL Server代理:理解SQL代理错误日志处理方法
2021/06/30 SQL Server