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中MySQLdb模块用法实例
Nov 10 Python
Python进行数据科学工作的简单入门教程
Apr 01 Python
python实现列表中由数值查到索引的方法
Jun 27 Python
在双python下设置python3为默认的方法
Oct 31 Python
Tensorflow分类器项目自定义数据读入的实现
Feb 05 Python
详解Python爬取并下载《电影天堂》3千多部电影
Apr 26 Python
numpy.random.shuffle打乱顺序函数的实现
Sep 10 Python
python多进程间通信代码实例
Sep 30 Python
Python计算不规则图形面积算法实现解析
Nov 22 Python
Python对Tornado请求与响应的数据处理
Feb 12 Python
如何在keras中添加自己的优化器(如adam等)
Jun 19 Python
pytorch 如何把图像数据集进行划分成train,test和val
May 31 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
天使彦史上最神还原,性别曝光的那一刻,百万网友恋爱了
2020/03/02 国漫
用PHP制作静态网站的模板框架
2006/10/09 PHP
比较好用的PHP防注入漏洞过滤函数代码
2012/04/11 PHP
PHP设计模式之解释器模式的深入解析
2013/06/13 PHP
使用PHP导出Word文档的原理和实例
2013/10/21 PHP
php可应用于面包屑导航的迭代寻找家谱树实现方法
2015/02/02 PHP
smarty模板引擎基础知识入门
2015/03/30 PHP
如何写php守护进程(Daemon)
2015/12/30 PHP
php中的单引号、双引号和转义字符详解
2017/02/16 PHP
浅析PHP类的反射来实现依赖注入过程
2018/02/06 PHP
jquery获取子节点和父节点的示例代码
2013/09/10 Javascript
jQuery封装的获取Url中的Get参数示例
2013/11/26 Javascript
jquery图形密码实现方法
2015/03/11 Javascript
JavaScript接口的实现三种方式(推荐)
2016/06/14 Javascript
jQuery ajax调用后台aspx后台文件的两种常见方法(不是ashx)
2016/06/28 Javascript
js入门之Function函数的使用方法【新手必看】
2016/11/22 Javascript
JavaScript定时器实现的原理分析
2016/12/06 Javascript
js控制文本框禁止输入特殊字符详解
2017/04/07 Javascript
用最少的JS代码写出贪吃蛇游戏
2018/01/12 Javascript
JavaScript+Canvas实现彩色图片转换成黑白图片的方法分析
2018/07/31 Javascript
Swiper.js实现移动端元素左右滑动
2019/09/08 Javascript
微信小程序 (地址选择1)--选取搜索地点并显示效果
2019/12/17 Javascript
JS实现长图上下滚动效果
2020/03/19 Javascript
vue 授权获取微信openId操作
2020/11/13 Javascript
PYTHON压平嵌套列表的简单实现
2016/06/08 Python
python模块导入的细节详解
2018/12/10 Python
python列表返回重复数据的下标
2020/02/10 Python
python中shell执行知识点
2020/05/06 Python
Python用SSH连接到网络设备
2021/02/18 Python
VSCode中autopep8无法运行问题解决方案(提示Error: Command failed,usage)
2021/03/02 Python
HTML5 transform三维立方体实现360无死角三维旋转效果
2014/08/22 HTML / CSS
兼职安全员岗位职责
2015/02/15 职场文书
死者家属慰问信
2015/03/24 职场文书
anaconda python3.8安装后降级
2021/06/11 Python
JavaScript实现简单的音乐播放器
2022/08/14 Javascript
SQLyog的下载、安装、破解、配置教程(MySQL可视化工具安装)
2022/09/23 MySQL