Python写的俄罗斯方块

2020-01-09 18:16:50 浏览数 (1)

在公司实习。公司推崇Python和Django框架,所以也得跟着学点。

简单瞅了下Tkinter,和Canvas配合在一起,还算是简洁的界面开发API。threading.Thread创建新的线程,其多线程机制也算是方便。

只是canvas.create_rectangle居然不是绘制矩形,而是新建了矩形控件这点让人大跌眼镜。先开始,在线程里每次都重绘多个矩形(随数组变化),其实是每次都新建了N个矩形,结果内存暴增。原来,对矩形进行变更时,只需用canvas.itemconfig即可。

下面就是截图(时间太晚,明日还得上班,做得非常粗糙...没事时再慢慢修正)。

而代码如下:

代码语言:javascript复制
#coding=utf-8
from Tkinter import *;
from random import *;
import thread;   
from tkMessageBox import showinfo;
import threading;
from time import sleep;
class BrickGame(object):
  
  #是否开始
  start = True;
  #是否到达底部
  isDown = True;
  
  #窗体
  window = None;
  #frame
  frame1 = None;
  
  #绘图类
  canvas = None;
  
  #标题
  title = "BrickGame";
  #宽和高
  width = 350;
  height = 670;
  
  #行和列
  rows = 20;
  cols = 10;
  
  #几种方块
  brick = [
    
    [
         [
             [1,1,1],
             [0,0,1],
             [0,0,0]
         ],
         [
              [0,0,1],
              [0,0,1],
              [0,1,1]
         ],
         [
              [0,0,0],
              [1,0,0],
              [1,1,1]
         ],
         [
              [1,1,0],
              [1,0,0],
              [1,0,0]
         ]
    ],
    [
         [
               [0,0,0],
               [0,1,1],
               [0,1,1]
         ],
         [
                [0,0,0],
                [0,1,1],
                [0,1,1]
         ],
         [
                [0,0,0],
                [0,1,1],
                [0,1,1]
         ],
         [
                [0,0,0],
                [0,1,1],
                [0,1,1]
         ]         
    ],
    [
         [
                [1,1,1],
                [0,1,0],
                [0,1,0]
         ],
         [
                [0,0,1],
                [1,1,1],
                [0,0,1]
         ],
         [
                [0,1,0],
                [0,1,0],
                [1,1,1]
         ],
         [
                [1,0,0],
                [1,1,1],
                [1,0,0]
         ]
    ],
    [
         [
                [0,1,0],
                [0,1,0],
                [0,1,0]
         ],
         [
                [0,0,0],
                [1,1,1],
                [0,0,0]
         ],
         [
                [0,1,0],
                [0,1,0],
                [0,1,0]
         ],
         [
                [0,0,0],
                [1,1,1],
                [0,0,0]
         ]
    ]
  ];
  
  #当前的方块
  curBrick = None;
  #当前方块数组
  arr = None;
  #当前方块形状
  shape = -1;
  #当前方块的行和列(最左上角)
  curRow = -10;
  curCol = -10;
  
  #背景
  back = list();
  #格子
  gridBack = list();
  
  #初始化
  def init(self):
    
    for i in range(0,self.rows):
      
      self.back.insert(i,list());
      self.gridBack.insert(i,list());
    
    for i in range(0,self.rows):
      
      for j in range(0,self.cols):
        
        self.back[i].insert(j,0);
        self.gridBack[i].insert(j,self.canvas.create_rectangle(30*j,30*i,30*(j 1),30*(i 1),fill="black"));

  #绘制游戏的格子
  def drawRect(self):
    
    for i in range(0,self.rows):
          
          for j in range(0,self.cols):
            
          
            if self.back[i][j]==1:
              
              self.canvas.itemconfig(self.gridBack[i][j],fill="blue",outline="white");
              
            elif self.back[i][j]==0:
              
              self.canvas.itemconfig(self.gridBack[i][j],fill="black",outline="white");
  
              
    #绘制当前正在运动的方块
    if self.curRow!=-10 and self.curCol!=-10:
      
      for i in range(0,len(self.arr)):
        
        for j in range(0,len(self.arr[i])):
          
          if self.arr[i][j]==1:          
            
            self.canvas.itemconfig(self.gridBack[self.curRow i][self.curCol j],fill="blue",outline="white");
            
    #判断方块是否已经运动到达底部
    if self.isDown:
      
      for i in range(0,3):
        
        for j in range(0,3):
          
          if self.arr[i][j]!=0:
            
            self.back[self.curRow i][self.curCol j] = self.arr[i][j];
            
      #判断整行消除
      self.removeRow();
        
      #获得下一个方块  
      self.getCurBrick();

  #判断是否有整行需要消除
  def removeRow(self):
    
    for i in range(0,self.rows):

      tag1 = True;      
      for j in range(0,self.cols):
        
        if self.back[i][j]==0:
          
          tag1 = False;
          break;
      
      if tag1==True:
        
        #从上向下挪动
        for m in xrange(i-1,0,-1):
          
          for n in range(0,self.cols):
            
            self.back[m 1][n] = self.back[m][n];
      
  #获得当前的方块
  def getCurBrick(self):
    
    self.curBrick = randint(0,len(self.brick)-1);
    self.shape = 0;
    #当前方块数组
    self.arr = self.brick[self.curBrick][self.shape];
    
    self.curRow = 0;
    self.curCol = 1;
    
    #是否到底部为False
    self.isDown = False;
    
  #监听键盘输入
  def onKeyboardEvent(self,event):
    
    #未开始,不必监听键盘输入
    if self.start == False:
      
      return;
    
    #记录原来的值
    tempCurCol = self.curCol;
    tempCurRow = self.curRow;
    tempShape = self.shape;
    tempArr = self.arr;
    direction = -1;
    
    if event.keycode==37:
      
      #左移
      self.curCol-=1;
      direction = 1;
    elif event.keycode==38:
      #变化方块的形状
      self.shape =1;
      direction = 2;
      
      if self.shape>=4:
        
        self.shape=0;
      self.arr = self.brick[self.curBrick][self.shape];
    elif event.keycode==39:
      
      direction = 3;
      #右移
      self.curCol =1;
    elif event.keycode==40:
      
      direction = 4;
      #下移
      self.curRow =1;
      
    if self.isEdge(direction)==False:
      
      self.curCol = tempCurCol;
      self.curRow = tempCurRow;
      self.shape = tempShape;
      self.arr = tempArr;
        
    self.drawRect();
      
    return True;
  
  #判断当前方块是否到达边界
  def isEdge(self,direction):
    
    tag = True;
  
    #向左,判断边界
    if direction==1:
      
      for i in range(0,3):
        
        for j in range(0,3):
          
          if self.arr[j][i]!=0 and (self.curCol i<0 or self.back[self.curRow j][self.curCol i]!=0):
            
            tag = False;
            break;
    #向右,判断边界
    elif direction==3:
      
      for i in range(0,3):
        
        for j in range(0,3):
          
          if self.arr[j][i]!=0 and (self.curCol i>=self.cols or self.back[self.curRow j][self.curCol i]!=0):
            
            tag = False;
            break;
    #向下,判断底部
    elif direction==4:
      
      for i in range(0,3):
        
        for j in range(0,3):
          
          if self.arr[i][j]!=0 and (self.curRow i>=self.rows or self.back[self.curRow i][self.curCol j]!=0):
            
            tag = False;
            self.isDown = True;
            break;
    #进行变形,判断边界
    elif direction==2:
      
      if self.curCol<0:
        
        self.curCol=0;
      
      if self.curCol 2>=self.cols:
        
        self.curCol = self.cols-3;
        
      if self.curRow 2>=self.rows:
        
        self.curRow = self.curRow-3;
    
    
    return tag;
  
  #方块向下移动
  def brickDown(self):
    
    while True:
      
      if self.start==False:
        
        print("exit thread");
        break;
      
      tempRow = self.curRow;
      self.curRow =1;
      
      if self.isEdge(4)==False:
        
        self.curRow = tempRow;
        
      self.drawRect();
         
      #每一秒下降一格
      sleep(1);  
      
  #运行
  def __init__(self):
    
    self.window = Tk();
    self.window.title(self.title);
    self.window.minsize(self.width,self.height);
    self.window.maxsize(self.width,self.height);        
    
    self.frame1 = Frame(self.window,width=300,height=600,bg="black");
    self.frame1.place(x=20,y=30);
    
    self.canvas = Canvas(self.frame1,width=300,height=600,bg="black");
    
    self.init();
    
    #获得当前的方块
    self.getCurBrick();
    
    #按照数组,绘制格子
    self.drawRect();    
          
    self.canvas.pack();
    
    #监听键盘事件
    self.window.bind("<KeyPress>",self.onKeyboardEvent); 
    
    #启动方块下落线程
    downThread = threading.Thread(target=self.brickDown,args=());
    downThread.start();    
    
    self.window.mainloop(); 
    
    self.start=False;
    
  pass;

if __name__=='__main__':
  
  brickGame = BrickGame();

估计用图形界面会很少,因为俺是WEB开发。不过,怎样也抑制不住这颗喜欢写游戏的心啊!

0 人点赞