一、简单说明

80、90后的小伙伴都玩过“俄罗斯方块”,那种“叱咤风云”场景 偶尔闪现在脑海 真的是太爽了;如果没有来得及玩过的同学,这次可以真正的自己做一个了

本实例用的是Python3(当然了Python3.5 3.6 3.7....都行 )+ pygame实现的

运行之前需要安装pygame模块,安装命令如下

pip install pygame -i https://mirrors.aliyun.com/pypi/simple/

二、运行效果

三、完整代码

下面的代码,用到了字体文件yh.ttf,下载地址 https://www.itprojects.cn/detail.html?example_id=8bf48a0ac4cee29043d4122fe6e563cb

文件main.py代码如下:

"""
作者:it项目实例网
更多项目实例,请访问:www.itprojects.cn
""" import random
import sys
import time import pygame from blocks import block_s, block_i, block_j, block_l, block_o, block_t, block_z SCREEN_WIDTH, SCREEN_HEIGHT = 450, 750
BG_COLOR = (40, 40, 60) # 背景色
BLOCK_COL_NUM = 10 # 每行的方格数
SIZE = 30 # 每个小方格大小
BLOCK_ROW_NUM = 25 # 每列的方个数
BORDER_WIDTH = 4 # 游戏区边框宽度
RED = (200, 30, 30) # 红色,GAME OVER 的字体颜色 def judge_game_over(stop_all_block_list):
"""
判断游戏是否结束
"""
if "O" in stop_all_block_list[0]:
return True def change_speed(score):
speed_level = [("1", 0.5, 0, 20), ("2", 0.4, 21, 50), ("3", 0.3, 51, 100), ("4", 0.2, 101, 200), ("5", 0.1, 201, None)]
for speed_info, speed, score_start, score_stop in speed_level:
if score_stop and score_start <= score <= score_stop:
return speed_info, speed
elif score_stop is None and score >= score_start:
return speed_info, speed def judge_lines(stop_all_block_list):
"""
判断是否有同一行的方格,如果有则消除
"""
# 记录刚刚消除的行数
move_row_list = list()
# 消除满格的行
for row, line in enumerate(stop_all_block_list):
if "." not in line:
# 如果这一行没有. 那么就意味着全部是O,则消除这一行
stop_all_block_list[row] = ['.' for _ in range(len(line))]
move_row_list.append(row) # 如果没有满格的行,则结束此函数
if not move_row_list:
return 0 # 移动剩余的行到下一行
for row in move_row_list:
stop_all_block_list.pop(row)
stop_all_block_list.insert(0, ['.' for _ in range(len(line))]) return len(move_row_list) * 10 def add_to_stop_all_block_list(stop_all_block_list, current_block, current_block_start_row, current_block_start_col):
"""
将当前已经停止移动的block添加到列表中
"""
for row, line in enumerate(current_block):
for col, block in enumerate(line):
if block != '.':
stop_all_block_list[current_block_start_row + row][current_block_start_col + col] = "O" def change_current_block_style(current_block):
"""
改变图形的样式
"""
# 计算出,当前图形样式属于哪个图形
current_block_style_list = None
for block_style_list in [block_s, block_i, block_j, block_l, block_o, block_t, block_z]:
if current_block in block_style_list:
current_block_style_list = block_style_list # 得到当前正在用的图形的索引(下标)
index = current_block_style_list.index(current_block)
# 它的下一个图形的索引
index += 1
# 防止越界
index = index % len(current_block_style_list)
# 返回下一个图形
return current_block_style_list[index] def judge_move_right(current_block, current_block_start_col):
"""
判断是否可以向右移动
"""
# 先判断列的方式是从右到左
for col in range(len(current_block[0]) - 1, -1, -1):
# 得到1列的所有元素
col_list = [line[col] for line in current_block]
# 判断是否碰到右边界
if 'O' in col_list and current_block_start_col + col >= BLOCK_COL_NUM:
return False
return True def judge_move_left(current_block, current_block_start_col):
"""
判断是否可以向左移动
"""
# 先判断列的方式是从左到右
for col in range(len(current_block[0])):
# 得到1列的所有元素
col_list = [line[col] for line in current_block]
# 判断是否碰到右边界
if 'O' in col_list and current_block_start_col + col < 0:
return False
return True def judge_move_down(current_block, current_block_start_row, current_block_start_col, stop_all_block_list):
"""
判断是否碰撞到其它图形或者底边界
"""
# 得到其它图形所有的坐标
stop_all_block_position = list()
for row, line in enumerate(stop_all_block_list):
for col, block in enumerate(line):
if block != ".":
stop_all_block_position.append((row, col))
# print(stop_all_block_position) # 判断碰撞
for row, line in enumerate(current_block):
if 'O' in line and current_block_start_row + row >= BLOCK_ROW_NUM:
# 如果当前行有0,且从起始行开始算+当前显示的行,超过了总行数,那么就认为碰到了底部
return False
for col, block in enumerate(line):
if block != "." and (current_block_start_row + row, current_block_start_col + col) in stop_all_block_position:
return False return True def get_block():
"""
创建一个图形
"""
block_style_list = random.choice([block_s, block_i, block_j, block_l, block_o, block_t, block_z])
return random.choice(block_style_list) def main():
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption('俄罗斯方块') current_block = get_block() # 当前图形
current_block_start_row = -2 # 当前图片从哪一行开始显示图形
current_block_start_col = 4 # 当前图形从哪一列开始显示
next_block = get_block() # 下一个图形
last_time = time.time()
speed = 0.5 # 降落的速度
speed_info = '1' # 显示的速度等级 # 定义一个列表,用来存储所有的已经停止移动的形状
stop_all_block_list = [['.' for i in range(BLOCK_COL_NUM)] for j in range(BLOCK_ROW_NUM)] # 字体
font = pygame.font.Font('yh.ttf', 24) # 黑体24
game_over_font = pygame.font.Font("yh.ttf", 72)
game_over_font_width, game_over_font_height = game_over_font.size('GAME OVER')
game_again_font_width, game_again_font_height = font.size('鼠标点击任意位置,再来一局') # 得分
score = 0 # 标记游戏是否结束
game_over = False # 创建计时器(防止while循环过快,占用太多CPU的问题)
clock = pygame.time.Clock()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
if judge_move_left(current_block, current_block_start_col - 1):
current_block_start_col -= 1
elif event.key == pygame.K_RIGHT:
if judge_move_right(current_block, current_block_start_col + 1):
current_block_start_col += 1
elif event.key == pygame.K_UP:
current_block_next_style = change_current_block_style(current_block)
if judge_move_left(current_block_next_style, current_block_start_col) and \
judge_move_right(current_block_next_style, current_block_start_col) and \
judge_move_down(current_block, current_block_start_row, current_block_start_col, stop_all_block_list):
# 判断新的样式没有越界
current_block = current_block_next_style
elif event.key == pygame.K_DOWN:
# 判断是否可以向下移动,如果碰到底部或者其它的图形就不能移动了
if judge_move_down(current_block, current_block_start_row + 1, current_block_start_col, stop_all_block_list):
current_block_start_row += 1
elif event.type == pygame.MOUSEBUTTONDOWN and event.button:
if game_over:
# 重置游戏用到的变量
current_block = get_block() # 当前图形
current_block_start_row = -2 # 当前图片从哪一行开始显示图形
current_block_start_col = 4 # 当前图形从哪一列开始显示
next_block = get_block() # 下一个图形
stop_all_block_list = [['.' for i in range(BLOCK_COL_NUM)] for j in range(BLOCK_ROW_NUM)]
score = 0
game_over = False # 判断是否修改当前图形显示的起始行
if not game_over and time.time() - last_time > speed:
last_time = time.time()
# 判断是否可以向下移动,如果碰到底部或者其它的图形就不能移动了
if judge_move_down(current_block, current_block_start_row + 1, current_block_start_col, stop_all_block_list):
current_block_start_row += 1
else:
# 将这个图形存储到统一的列表中,这样便于判断是否成为一行
add_to_stop_all_block_list(stop_all_block_list, current_block, current_block_start_row, current_block_start_col)
# 判断是否有同一行的,如果有就消除,且加上分数
score += judge_lines(stop_all_block_list)
# 判断游戏是否结束(如果第一行中间有O那么就表示游戏结束)
game_over = judge_game_over(stop_all_block_list)
# 调整速度
speed_info, speed = change_speed(score)
# 创建新的图形
current_block = next_block
next_block = get_block()
# 重置数据
current_block_start_col = 4
current_block_start_row = -2 # 画背景(填充背景色)
screen.fill(BG_COLOR) # 画游戏区域分隔线
pygame.draw.line(screen, (100, 40, 200), (SIZE * BLOCK_COL_NUM, 0), (SIZE * BLOCK_COL_NUM, SCREEN_HEIGHT), BORDER_WIDTH) # 显示当前图形
for row, line in enumerate(current_block):
for col, block in enumerate(line):
if block != '.':
pygame.draw.rect(screen, (20, 128, 200), ((current_block_start_col + col) * SIZE, (current_block_start_row + row) * SIZE, SIZE, SIZE), 0) # 显示所有停止移动的图形
for row, line in enumerate(stop_all_block_list):
for col, block in enumerate(line):
if block != '.':
pygame.draw.rect(screen, (20, 128, 200), (col * SIZE, row * SIZE, SIZE, SIZE), 0) # 画网格线 竖线
for x in range(BLOCK_COL_NUM):
pygame.draw.line(screen, (0, 0, 0), (x * SIZE, 0), (x * SIZE, SCREEN_HEIGHT), 1)
# 画网格线 横线
for y in range(BLOCK_ROW_NUM):
pygame.draw.line(screen, (0, 0, 0), (0, y * SIZE), (BLOCK_COL_NUM * SIZE, y * SIZE), 1) # 显示右侧(得分、速度、下一行图形)
# 得分
score_show_msg = font.render('得分: ', True, (255, 255, 255))
screen.blit(score_show_msg, (BLOCK_COL_NUM * SIZE + 10, 10))
score_show_msg = font.render(str(score), True, (255, 255, 255))
screen.blit(score_show_msg, (BLOCK_COL_NUM * SIZE + 10, 50))
# 速度
speed_show_msg = font.render('速度: ', True, (255, 255, 255))
screen.blit(speed_show_msg, (BLOCK_COL_NUM * SIZE + 10, 100))
speed_show_msg = font.render(speed_info, True, (255, 255, 255))
screen.blit(speed_show_msg, (BLOCK_COL_NUM * SIZE + 10, 150))
# 下一个图形(文字提示)
next_style_msg = font.render('下一个: ', True, (255, 255, 255))
screen.blit(next_style_msg, (BLOCK_COL_NUM * SIZE + 10, 200))
# 下一个图形(图形)
for row, line in enumerate(next_block):
for col, block in enumerate(line):
if block != '.':
pygame.draw.rect(screen, (20, 128, 200), (320 + SIZE * col, (BLOCK_COL_NUM + row) * SIZE, SIZE, SIZE), 0)
# 显示这个方格的4个边的颜色
# 左
pygame.draw.line(screen, (0, 0, 0), (320 + SIZE * col, (BLOCK_COL_NUM + row) * SIZE), (320 + SIZE * col, (BLOCK_COL_NUM + row + 1) * SIZE), 1)
# 上
pygame.draw.line(screen, (0, 0, 0), (320 + SIZE * col, (BLOCK_COL_NUM + row) * SIZE), (320 + SIZE * (col + 1), (BLOCK_COL_NUM + row) * SIZE), 1)
# 下
pygame.draw.line(screen, (0, 0, 0), (320 + SIZE * col, (BLOCK_COL_NUM + row + 1) * SIZE), (320 + SIZE * (col + 1), (BLOCK_COL_NUM + row + 1) * SIZE), 1)
# 右
pygame.draw.line(screen, (0, 0, 0), (320 + SIZE * (col + 1), (BLOCK_COL_NUM + row) * SIZE), (320 + SIZE * (col + 1), (BLOCK_COL_NUM + row + 1) * SIZE), 1) # 显示游戏结束画面
if game_over:
game_over_tips = game_over_font.render('GAME OVER', True, RED)
screen.blit(game_over_tips, ((SCREEN_WIDTH - game_over_font_width) // 2, (SCREEN_HEIGHT - game_over_font_height) // 2))
# 显示"鼠标点击任意位置,再来一局"
game_again = font.render('鼠标点击任意位置,再来一局', True, RED)
screen.blit(game_again, ((SCREEN_WIDTH - game_again_font_width) // 2, (SCREEN_HEIGHT - game_again_font_height) // 2 + 80)) # 刷新显示(此时窗口才会真正的显示)
pygame.display.update()
# FPS(每秒钟显示画面的次数)
clock.tick(60) # 通过一定的延时,实现1秒钟能够循环60次 if __name__ == '__main__':
main()

文件blocks.py代码如下:

# S形方块
block_s = [['.OO',
'OO.',
'...'],
['O..',
'OO.',
'.O.']]
# Z形方块
block_z = [['OO.',
'.OO',
'...'],
['.O.',
'OO.',
'O..']]
# I型方块
block_i = [['.O..',
'.O..',
'.O..',
'.O..'],
['....',
'....',
'OOOO',
'....']]
# O型方块
block_o = [['OO',
'OO']]
# J型方块
block_j = [['O..',
'OOO',
'...'],
['.OO',
'.O.',
'.O.'],
['...',
'OOO',
'..O'],
['.O.',
'.O.',
'OO.']]
# L型方块
block_l = [['..O',
'OOO',
'...'],
['.O.',
'.O.',
'.OO'],
['...',
'OOO',
'O..'],
['OO.',
'.O.',
'.O.']]
# T型方块
block_t = [['.O.',
'OOO',
'...'],
['.O.',
'.OO',
'.O.'],
['...',
'OOO',
'.O.'],
['.O.',
'OO.',
'.O.']]

Python3+pygame实现的俄罗斯方块 代码完整 有演示效果的更多相关文章

  1. Python3+pygame实现的90坦克大战 代码完整 有演示效果

    我是一个典型的80后,年轻时玩过了特别多的游戏,所以这几天用Python3+pygame实现了一个另外小游戏"坦克大战"(其他的游戏,请翻阅我的博客) 本实例代码量有些多,完整的版 ...

  2. Python3+pygame实现的flappy bird游戏,代码完整,还有音乐

    之前一直在手机上玩flappy bird游戏,闲暇时间就编写了一个 是采用python3+pygame模块制作而成的,运行效果非常流畅,会让你大吃一惊哦哈哈 一.运行效果展示 下载游戏之后,注意在自己 ...

  3. python3+tkinter实现的黑白棋,代码完整 100%能运行

    今天分享给大家的是采用Python3+tkinter制作而成的小项目--黑白棋 tkinter是Python内置的图形化模块,简单易用,一般的小型UI程序可以快速用它实现,具体的tkinter相关知识 ...

  4. 吴裕雄--天生自然python学习笔记:python 用pygame模块开发俄罗斯方块游戏

    俄罗斯方块游戏 多年前,游戏机中最流行的游戏就是“俄罗斯方块”了.时至今日,虽然网络 游戏日新月异 ,但“俄罗斯方块”这款小游戏仍在许多人心中 占有一席之地.本例中, 我们将亲手设计一个简单的俄罗斯方 ...

  5. 在python3.x下使用如下代码: import cPickle as pk 报错

    在python3.x下使用如下代码: import cPickle as pk会报如下错误:ImportError: No module named 'cPickle' 原因:python2有cPic ...

  6. python3.6从含有html代码的json的中取出某个值

    python3.6从含有html代码的json的中取出某个值 之前在做接口测试的时候,网站的后端是用java写的,然后接口的response返回的都是json格式,json很简单,就是字典,类似这样子 ...

  7. CountDownTimer完整具体演示样例

    MainActivity例如以下: package cc.cv; import android.os.Bundle; import android.os.CountDownTimer; import ...

  8. [刘阳Java]_纯CSS代码实现内容过滤效果

    继续我们技术专题课,我们今天给大家带来的是一个比较酷炫的"纯CSS代码实现内容过滤效果",没有加入任何JS的效果.全部都是应用CSS3的新增选择器来实现的.先看效果截图 实现思路 ...

  9. 关于html5与jsp页面同样的html代码展示的页面效果不一样的问题

    原文:关于html5与jsp页面同样的html代码展示的页面效果不一样的问题 html5默认的声明为 <!DOCTYPE html> jsp默认的声明头部为 <%@ page con ...

随机推荐

  1. 2019 ICPC Asia Nanjing Regional

    2019 ICPC Asia Nanjing Regional A - Hard Problem 计蒜客 - 42395 若 n = 10,可以先取:6,7,8,9,10.然后随便从1,2,3,4,5 ...

  2. 牛客小白月赛30 J.小游戏 (DP)

    题意:给你一组数,每次可以选择拿走第\(i\)个数,得到\(a[i]\)的分数,然后对于分数值为\(a[i]-1\)和\(a[i]+1\)的值就会变得不可取,问能得到的最大分数是多少. 题解:\(a[ ...

  3. 找新朋友 HDU - 1286 欧拉函数模板题

    题意: 求出来区间[1,n]内与n互质的数的数量 题解: 典型的欧拉函数应用,具体见这里:Relatives POJ - 2407 欧拉函数 代码: 1 #include<stdio.h> ...

  4. 迷宫城堡 HDU - 1269 判断有向图是否是强连通图

    为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是单向的,就是说若称某通道连通了A房间和B房间,只说明可以 ...

  5. ZYB loves Xor I HDU - 5269 字典树

    题意: T组样例,给你n个数.你要找出来这n个数中任意两个数的二进制位中  最低位不同  的位置(假设是k),然后让所有2^k加起来就是结果 什么意思? 例如4 和 2 4的二进制是(100),2的二 ...

  6. HTTP笔记4--HTTP 状态码

    状态码作用.组成 HTTP 状态码负责表示客户端 HTTP 请求的返回结果.标记服务器端的处理是否正常.通知出现的错误等工作.状态码的职责是当客户端向服务器端发送请求时,描述返回的请求结果. 状态码如 ...

  7. Nginx基础 - 通用优化配置文件

    [root@localhost ~]# vim /etc/nginx/nginx.conf user nginx; worker_processes auto; worker_cpu_affinity ...

  8. spring再学习之简单测试

    一.spring是怎么工作的那,通过一个类装载进容器进行描述: 首先创建一个类user: package cn.itcast.bean; public class User { public User ...

  9. C# Dictionaries

    Dictionaries 字典 在C# 里是用接口 IDictionary来实现的,最常用的字典就是Dicrtionary<tkey,tvalue>,键值对的形式,和index,item ...

  10. springboot(四) rabbitMQ demo

    RabbitMQ 即一个消息队列,主要是用来实现应用程序的异步和解耦,同时也能起到消息缓冲,消息分发的作用. 消息中间件在互联网公司的使用中越来越多,刚才还看到新闻阿里将RocketMQ捐献给了apa ...