python实现俄罗斯方块


Posted in Python onJune 26, 2018

网上搜到一个Pygame写的俄罗斯方块(tetris),大部分看懂的前提下增加了注释,Fedora19下运行OK的

主程序:

#coding:utf8
#! /usr/bin/env python
# 注释说明:shape表示一个俄罗斯方块形状 cell表示一个小方块
import sys
from random import choice
import pygame
from pygame.locals import *
from block import O, I, S, Z, L, J, T

COLS = 16
ROWS = 20
CELLS = COLS * ROWS
CELLPX = 32 # 每个cell的像素宽度
POS_FIRST_APPEAR = COLS / 2
SCREEN_SIZE = (COLS * CELLPX, ROWS * CELLPX)
COLOR_BG = (0, 0, 0)


def draw(grid, pos=None):
 # grid是一个list,要么值为None,要么值为'Block'
 # 非空值在eval()的作用下,用于配置颜色
 if pos: # 6x5
  s = pos - 3 - 2 * COLS # upper left position
  for p in range(0, COLS):
   q = s + p * COLS
   for i in range(q, q + 6):
    if 0 <= i < CELLS:
     # 0 <=i < CELLS:表示i这个cell在board内部。
     c = eval(grid[i] + ".color") if grid[i] else COLOR_BG
     # 执行着色。shape的cell涂对应的class设定好的颜色,否则涂黑(背景色)
     a = i % COLS * CELLPX
     b = i / COLS * CELLPX
     screen.fill(c, (a, b, CELLPX, CELLPX))
 else: # all
  screen.fill(COLOR_BG)
  for i, occupied in enumerate(grid):
   if occupied:
    c = eval(grid[i] + ".color") # 获取方块对应的颜色
    a = i % COLS * CELLPX # 横向长度
    b = i / COLS * CELLPX # 纵向长度
    screen.fill(c, (a, b, CELLPX, CELLPX))
    # fill:为cell上色, 第二个参数表示rect
 pygame.display.flip()
 # 刷新屏幕


def phi(grid1, grid2, pos): # 4x4
# 两个grid之4*4区域内是否会相撞(冲突)
 s = pos - 2 - 1 * COLS # upper left position
 for p in range(0, 4):
  q = s + p * COLS
  for i in range(q, q + 4):
   try:
    if grid1[i] and grid2[i]:
     return False
   except:
    pass
 return True


def merge(grid1, grid2):
 # 合并两个grid
 grid = grid1[:]
 for i, c in enumerate(grid2):
  if c:
   grid[i] = c
 return grid


def complete(grid):
 # 减去满行
 n = 0
 for i in range(0, CELLS, COLS):
  # 步长为一行。
  if not None in grid[i:i + COLS]:
  #这一句很容易理解错误。
  #实际含义是:如果grid[i:i + COLS]都不是None,那么执行下面的语句
   grid = [None] * COLS + grid[:i] + grid[i + COLS:]
   n += 1
 return grid, n
#n表示减去的行数,用作统计分数

pygame.init()
pygame.event.set_blocked(None)
pygame.event.set_allowed((KEYDOWN, QUIT))
pygame.key.set_repeat(75, 0)
pygame.display.set_caption('Tetris')
screen = pygame.display.set_mode(SCREEN_SIZE)
pygame.display.update()

grid = [None] * CELLS
speed = 500
screen.fill(COLOR_BG)
while True: # spawn a block
 block = choice([O, I, S, Z, L, J, T])()
 pos = POS_FIRST_APPEAR
 if not phi(grid, block.grid(pos), pos): break # you lose
 pygame.time.set_timer(KEYDOWN, speed)
 # repeatedly create an event on the event queue
 # speed是时间间隔。。。speed越小,方块下落的速度越快。。。speed应该换为其他名字

 while True: # move the block
  draw(merge(grid, block.grid(pos)), pos)
  event = pygame.event.wait()
  if event.type == QUIT: sys.exit()
  try:
   aim = {
    K_UNKNOWN: pos+COLS,
    K_UP: pos,
    K_DOWN: pos+COLS,
    K_LEFT: pos-1,
    K_RIGHT: pos+1,
   }[event.key]
  except KeyError:
   continue
  if event.key == K_UP:
   # 变形
   block.rotate()

  elif event.key in (K_LEFT, K_RIGHT) and pos / COLS != aim / COLS:
   # pos/COLS表示当前位置所在行
   # aim/COLS表示目标位置所在行
   # 此判断表示,当shape在左边界时,不允许再向左移动(越界。。),在最右边时向右也禁止
   continue

  grid_aim = block.grid(aim)
  if grid_aim and phi(grid, grid_aim, aim):
   pos = aim
  else:
   if event.key == K_UP:
    block.rotate(times=3)
   elif not event.key in (K_LEFT, K_RIGHT):
    break

 grid = merge(grid, block.grid(pos))
 grid, n = complete(grid)
 if n:
  draw(grid)
  speed -= 5 * n
  if speed < 75: speed = 75

调用的模块:

#coding:utf-8
#! /usr/bin/env python
COLS = 16
ROWS = 20

class Block():
 color = (255,255,255)
 def __init__(self):
  self._state = 0
 def __str__(self):
  return self.__class__.__name__
 def _orientations(self):
  raise NotImplementedError()
 def rotate(self, times=1):
  for i in range(times):
   if len(self._orientations())-1 == self._state:
    self._state = 0
    #只要_state比_orientations长度-1还要小,就让_state加1

   else:
    self._state += 1
 def blades(self):
  # 返回对应形状的一种旋转形状。(返回一个list,list中每个元素是一个(x,y))
  return self._orientations()[self._state]

 def grid(self, pos, cols=COLS, rows=ROWS):
  # grid()函数:对于一个形状,从它的cell中的pos位置,按照orientations的位置提示,把所有cell涂色
  # pos表示的是shape中的一个cell,也就是(0,0)
  if cols*rows <= pos:
   return None
  # 这种情况应该不可能出现吧。如果出现<=的情况
  # 那么,pos都跑到界外了。。

  grid = [None] * cols * rows
  grid[pos] = str(self)
  for b in self.blades():
   x, y = b
   # pos/cols表示pos处于board的第几行
   if pos/cols != (pos+x)/cols:
    return None
   i = pos + x + y * cols
   if i < 0:
    continue
   elif cols*rows <= i:
    return None
   grid[i] = str(self)
   # 给相应的其他位置都“涂色”,比如对于方块,是O型的,那么pos肯定是有值的,pos位于有上角。。
  return grid

# 以下每个形状class,_orientations()都返回形状的列表。(0,0)一定被包含在其中,为了省略空间所以都没有写出.
class O(Block):
 color = (207,247,0)
 def _orientations(self):
  return (
   [(-1,0), (-1,1), (0,1)],
   )
class I(Block):
 color = (135,240,60)
 def _orientations(self):
  return (
   [(-2,0), (-1,0), (1,0)],
   [(0,-1), (0,1), (0,2)],
   )
class S(Block):
 color = (171,252,113)
 def _orientations(self):
  return (
   [(1,0), (-1,1), (0,1)],
   [(0,-1), (1,0), (1,1)],
   )
class Z(Block):
 color = (243,61,110)
 def _orientations(self):
  return (
   [(-1,0), (0,1), (1,1)],
   [(1,-1), (1,0), (0,1)],
   )
class L(Block):
 color = (253,205,217)
 def _orientations(self):
  return (
   [(-1,1), (-1,0), (1,0)],
   [(0,-1), (0,1), (1,1)],
   [(-1,0), (1,0), (1,-1)],
   [(-1,-1), (0,-1), (0,1)],
   )
class J(Block):
 color = (140,180,225)
 def _orientations(self):
  return (
   [(-1,0), (1,0), (1,1)],
   [(0,1), (0,-1), (1,-1)],
   [(-1,-1), (-1,0), (1,0)],
   [(-1,1), (0,1), (0,-1)],
   )
class T(Block):
 color = (229,251,113)
 def _orientations(self):
  return (
   [(-1,0), (0,1), (1,0)],
   [(0,-1), (0,1), (1,0)],
   [(-1,0), (0,-1), (1,0)],
   [(-1,0), (0,-1), (0,1)],
   )

更多俄罗斯方块精彩文章请点击专题:俄罗斯方块游戏集合 进行学习。

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

Python 相关文章推荐
python实现爬虫统计学校BBS男女比例之数据处理(三)
Dec 31 Python
深入解析Python中的线程同步方法
Jun 14 Python
Python 实现数据库(SQL)更新脚本的生成方法
Jul 09 Python
Python数据类型中的“冒号“[::]——分片与步长操作示例
Jan 24 Python
Python3.7中安装openCV库的方法
Jul 11 Python
pygame游戏之旅 创建游戏窗口界面
Nov 20 Python
python的一些加密方法及python 加密模块
Jul 11 Python
python自动化测试无法启动谷歌浏览器问题
Oct 10 Python
python实现WebSocket服务端过程解析
Oct 18 Python
python如何使用Redis构建分布式锁
Jan 16 Python
Python3如何在服务器打印资产信息
Aug 27 Python
深度学习小工程练习之垃圾分类详解
Apr 14 Python
解决python报错MemoryError的问题
Jun 26 #Python
pygame实现俄罗斯方块游戏
Jun 26 #Python
python和pygame实现简单俄罗斯方块游戏
Feb 19 #Python
解决python读取几千万行的大表内存问题
Jun 26 #Python
详解Python3的TFTP文件传输
Jun 26 #Python
python3爬取数据至mysql的方法
Jun 26 #Python
python清除函数占用的内存方法
Jun 25 #Python
You might like
php通过COM类调用组件的实现代码
2012/01/11 PHP
windows7下安装php的imagick和imagemagick扩展教程
2014/07/04 PHP
PHP调试函数和日志记录函数分享
2015/01/31 PHP
php版微信自动登录并获取昵称的方法
2016/09/23 PHP
PHP基于XMLWriter操作xml的方法分析
2017/07/17 PHP
PHP crypt()函数的用法讲解
2019/02/15 PHP
php使用pthreads v3多线程实现抓取新浪新闻信息操作示例
2020/02/21 PHP
javascript 面向对象编程 聊聊对象的事
2009/09/17 Javascript
JavaScript取得鼠标绝对位置程序代码介绍
2012/09/16 Javascript
js 使FORM表单的所有元素不可编辑的示例代码
2013/10/17 Javascript
window.location.href IE下跳转失效的解决方法
2014/03/27 Javascript
JavaScript中的类数组对象介绍
2014/12/30 Javascript
JS实现模拟百度搜索“2012世界末日”网页地震撕裂效果代码
2015/10/31 Javascript
微信小程序 textarea 组件详解及简单实例
2017/01/10 Javascript
mint-ui的search组件在键盘显示搜索按钮的实现方法
2017/10/27 Javascript
详解使用vuex进行菜单管理
2017/12/21 Javascript
使用Vue动态生成form表单的实例代码
2018/04/26 Javascript
垃圾回收器的相关知识点总结
2018/05/13 Javascript
解决axios会发送两次请求,有个OPTIONS请求的问题
2018/10/25 Javascript
35个最好用的Vue开源库(史上最全)
2019/01/03 Javascript
新手快速入门微信小程序组件库 iView Weapp
2019/06/24 Javascript
layui实现checkbox的目录树tree的例子
2019/09/12 Javascript
JavaScript实现tab栏切换效果
2020/03/16 Javascript
详解Python中的元组与逻辑运算符
2015/10/13 Python
理解生产者消费者模型及在Python编程中的运用实例
2016/06/26 Python
numpy找出array中的最大值,最小值实例
2018/04/03 Python
numpy中实现ndarray数组返回符合特定条件的索引方法
2018/04/17 Python
python实现名片管理系统项目
2019/04/26 Python
python3 pygame实现接小球游戏
2019/05/14 Python
python实现淘宝购物系统
2019/10/25 Python
Python判断字符串是否为空和null方法实例
2020/04/26 Python
幼儿园消防安全制度
2014/01/26 职场文书
第一批党的群众路线教育实践活动总结报告
2014/07/03 职场文书
小石潭记导游词
2015/02/03 职场文书
超市员工管理制度
2015/08/06 职场文书
MongoDB数据库部署环境准备及使用介绍
2022/03/21 MongoDB