[Python] 实现俄罗斯方块小游戏,可直接运行~

[Python] 实现俄罗斯方块小游戏,可直接运行~

大家好!

大家好! 先自我介绍一波,本人是嵌入式开发的萌新,工作不是很忙,所以会在空余时间学习一些其他方面的知识。在学习的过程中分享给大家

本篇是本人的第一篇文章,平时也很少用md,排版上有什么问题欢迎大家提出意见,我会及时更改的。

先上源码

运行结果查看

from pygame.locals import *
import pygame
from random import choice
import time
import sys
import copy

gridSize = (12, 17)		# 宽 * 高 
MinHeight = 2
GameStatus = list(enumerate(["Ready", "Gaming", "GameOver"]))
ColorList = [(250, 0, 0), (0, 250, 0), (0, 0, 250), (250, 250, 0), (0, 250, 250), (250, 0, 250), (250, 100, 0)]
IDList = list(range(7))
'''
1.		 □□□□   □      □      □    □□     □□       □□
				□□□   □□□   □□□     □□    □□      □□       
'''


def stuff_list(stuff_id):
    if stuff_id == 0:
        ptr = [[0, 0], [0, 1], [0, 2], [0, 3]]
    elif stuff_id == 1:
        ptr = [[0, 0], [0, 1], [0, 2], [1, 0]]
    elif stuff_id == 2:
        ptr = [[0, 1], [0, 0], [0, 2], [1, 1]]
    elif stuff_id == 3:
        ptr = [[0, 2], [0, 1], [0, 0], [1, 2]]
    elif stuff_id == 4:
        ptr = [[0, 0], [0, 1], [1, 0], [1, 1]]
    elif stuff_id == 5:
        ptr = [[0, 1], [0, 0], [1, 1], [1, 2]]
    else:
        ptr = [[0, 1], [0, 2], [1, 0], [1, 1]]
    return ptr


class Stuff:
    def __init__(self, stuff_id):
        self.space = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],		# 记录已固定的方块
                      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
        self.id = stuff_id
        self.ptr = []
        self.new_stuff(stuff_id)

    def new_stuff(self, stuff_id):
        self.id = stuff_id
        if self.id == 0:
            self.ptr = [[0, 4], [0, 3], [0, 5], [0, 6]]
        elif self.id == 1:
            self.ptr = [[0, 4], [0, 3], [0, 5], [1, 3]]
        elif self.id == 2:
            self.ptr = [[0, 4], [0, 3], [0, 5], [1, 4]]
        elif self.id == 3:
            self.ptr = [[0, 4], [0, 5], [0, 3], [1, 5]]
        elif self.id == 4:
            self.ptr = [[0, 4], [0, 3], [1, 3], [1, 4]]
        elif self.id == 5:
            self.ptr = [[0, 4], [0, 3], [1, 4], [1, 5]]
        else:
            self.ptr = [[0, 4], [0, 5], [1, 3], [1, 4]]

    def crash(self):
        """
        return:     0: no crash
                    1: down crash
                    2: up crash
                    3: left crash
                    4: right crash
                    5: note crash
        """
        for i in range(4):
            if self.ptr[i][0] > gridSize[1]-1:
                return 1
            elif self.ptr[i][0] < 0:
                return 2
            elif self.ptr[i][1] > gridSize[0]-1:
                return 3
            elif self.ptr[i][1] < 0:
                return 4
            elif self.space[self.ptr[i][0]][self.ptr[i][1]] != 0:
                return 5
        return 0

    def fix_stuff(self):		# 固定
        for ptr in self.ptr:
            self.space[ptr[0]][ptr[1]] = self.id + 1
        del_list = []
        for i in range(len(self.space)):	# 判断是否满行
            flag = True
            for g in self.space[i]:
                if g == 0:
                    flag = False
                    break
            if flag:
                del_list.append(i)
        for i in del_list:
            del self.space[i]
            self.space.insert(0, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
        # return len(del_list)		此处可加一个返回,用于方便计算分数

    def down(self):
        temp_ptr = copy.deepcopy(self.ptr)
        for i in range(4):
            self.ptr[i][0] += 1
        crash_result = self.crash()
        if crash_result != 0:
            self.ptr = copy.deepcopy(temp_ptr)
            return False
        return True

    def up(self):
        temp_ptr = copy.deepcopy(self.ptr)
        for i in range(4):
            self.ptr[i][0] -= 1
        crash_result = self.crash()
        if crash_result != 0:
            self.ptr = copy.deepcopy(temp_ptr)
            return False
        return True

    def left(self):
        temp_ptr = copy.deepcopy(self.ptr)
        for i in range(4):
            self.ptr[i][1] -= 1
        crash_result = self.crash()
        if crash_result != 0:
            self.ptr = copy.deepcopy(temp_ptr)
            return False
        return True

    def right(self):
        temp_ptr = copy.deepcopy(self.ptr)
        for i in range(4):
            self.ptr[i][1] += 1
        crash_result = self.crash()
        if crash_result != 0:
            self.ptr = copy.deepcopy(temp_ptr)
            return False
        return True

    def rotate(self):		# 旋转方块
        temp_ptr = copy.deepcopy(self.ptr)
        for i in range(1, 4):
            temp_y, temp_x = temp_ptr[0][0], temp_ptr[0][1]
            i_y, i_x = temp_ptr[i][0], temp_ptr[i][1]
            self.ptr[i] = [temp_ptr[0][0] - temp_ptr[i][1] + temp_ptr[0][1],		# 逆时针旋转
                           temp_ptr[0][1] + temp_ptr[i][0] - temp_ptr[0][0]]
            # self.ptr[i][0] = temp_ptr[0][0] + temp_ptr[i][1] - temp_ptr[0][1]
        crash_result = self.crash()
        if crash_result == 0:
            return True
        elif crash_result == 1:
            if self.up():
                return True
        elif crash_result == 2:
            if self.down():
                return True
        elif crash_result == 3:
            if self.left():
                return True
        elif crash_result == 4:
            if self.right():
                return True
        self.ptr = copy.deepcopy(temp_ptr)
        return False

    def over(self):		#游戏结束判断
        for i in range(1):
            for value in self.space[i]:
                if value != 0:
                    return True
        return False


def show_text(screen, pos, text, text_color, font_bold=False, font_size=60, font_italic=False, font_mediate=True):
    # 获取系统字体,并设置文字大小
    cur_font = pygame.font.SysFont("宋体", font_size)
    # 设置是否加粗属性
    cur_font.set_bold(font_bold)
    # 设置是否斜体属性
    cur_font.set_italic(font_italic)
    # 设置文字内容
    text_fmt = cur_font.render(text, 1, text_color)
    text_pos = text_fmt.get_rect()
    text_pos.midtop = pos
    # 绘制文字
    if font_mediate:
    # 判断是否居中
        screen.blit(text_fmt, text_pos)
    else:
        screen.blit(text_fmt, pos)


def main():
    pygame.init()
    ftpsClock = pygame.time.Clock()
    screen = pygame.display.set_mode((800, 800))
    pygame.display.set_caption("Tetris")
    GAME_STATUS = 0
    next_stuff = choice(IDList)
    curr_stuff = choice(IDList)
    stuff = Stuff(curr_stuff)
    next_ptr = stuff_list(next_stuff)
    gamingTime = time.time()
    while True:
        screen.fill((150, 150, 150))
        pygame.draw.rect(screen, (50, 50, 50), (50, 50, 500, 700))
        pygame.draw.rect(screen, (100, 100, 100), (60, 60, 480, 80))
        if GAME_STATUS == 0:	# Ready
            for event in pygame.event.get():	# 事件遍历
                if event.type == QUIT:
                    pygame.quit()
                    sys.exit()
                if event.type == KEYDOWN:		# 按键按下
                    if event.key in [K_RETURN, K_KP_ENTER]:
                        GAME_STATUS = 1
            show_text(screen, (400, 400), "Press enter to start game", (250, 250, 0), font_size=80)
        elif GAME_STATUS == 1:		# gaming
            for event in pygame.event.get():
                if event.type == QUIT:
                    pygame.quit()
                    sys.exit()
                if event.type == KEYDOWN:
                    if event.key in [K_UP, K_w, K_SPACE]:
                        stuff.rotate()
                    if event.key in [K_LEFT, K_a]:
                        stuff.left()
                    if event.key in [K_RIGHT, K_d]:
                        stuff.right()
                    if event.key in [K_DOWN, K_s]:	# 这里因为只判断了KEYDOWN,所以无论你按多久,都只会触发一次
                        stuff.down()				# 如果想实现长按快速下落这个效果可以和KEYUP事件一起食用
            if time.time() - gamingTime > 0.5:
                gamingTime = time.time()
                if not stuff.down():
                    stuff.fix_stuff()
                    curr_stuff = next_stuff
                    next_stuff = choice(IDList)
                    stuff.new_stuff(curr_stuff)
                    next_ptr = stuff_list(next_stuff)
            for pos in next_ptr:
                pygame.draw.rect(screen, ColorList[next_stuff], (601 + 50 * pos[1], 101 + 50 * pos[0], 48, 48))
            for i in range(gridSize[1]):
                for j in range(gridSize[0]):
                    ID = stuff.space[i][j]
                    if ID != 0:
                        pygame.draw.rect(screen, ColorList[ID - 1], (61 + 40 * j, 61 + 40 * i, 38, 38))
            for pos in stuff.ptr:
                pygame.draw.rect(screen, ColorList[stuff.id], (61 + 40 * pos[1], 61 + 40 * pos[0], 38, 38))
            if stuff.over():
                GAME_STATUS = 2
        elif GAME_STATUS == 2:	# Game over
            for event in pygame.event.get():
                if event.type == QUIT:
                    pygame.quit()
                    sys.exit()
                if event.type == KEYDOWN:
                    if event.key in [K_RETURN, K_KP_ENTER]:
                        GAME_STATUS = 0
                        next_stuff = choice(IDList)
                        curr_stuff = choice(IDList)
                        stuff = Stuff(curr_stuff)
                        next_ptr = stuff_list(next_stuff)
            show_text(screen, (400, 350), "GameOver", (250, 250, 0), font_size=80)
            show_text(screen, (400, 450), "Press enter to start game", (250, 250, 0), font_size=80)
        pygame.display.flip()
        ftpsClock.tick(20)	# 每秒20帧


if __name__ == '__main__':
    main()

介绍

代码方面我也不知道要怎么介绍,逻辑不是很难,也很难讲出个花来,只能是尽量多加写注释,方便大家理解

pygame

这个是库是这个程序的关键,具体食用方式可以自行去查查,或者看看其他大佬们的介绍,反正我食用起来是挺香的

copy

python 里面list这个数据结构实际上是一个指针,在使用过程中的赋值等操作也一直是对其地址进行操作,所以常用的

a = list(b)
a = b
a = b[:]

等复制方式,都是对其地址进行的复制,也就是浅复制,所以在复制完成后,对b进行改动后,a的值也会同步变化。若想对链表实现深复制,本案例中可遍历链表里面所有的元素,放进新的链表中。但这种方式只是使复制的深度加深一层而已,若链表的元素依旧有链表这类本质是指针的数据类型,则依旧会产生bug (就本案例而言是够了)
所以,我选择使用copy库里面的deepcopy函数。(自己写多累啊)

结尾

Ok,终于完成了,虽然只写了三四百字,但居然花了我一个小时。累~~~,还是打代码轻松,以后还是尽量少点字比较好 T . T

  • 18
    点赞
  • 149
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
实现俄罗斯方块游戏PYTHON代码,可以按照以下步骤: 1. 导入所需的模块:首先,我们需要导入`pygame`模块来创建游戏窗口和处理游戏逻辑。 2. 初始化游戏窗口:使用`pygame`模块创建一个游戏窗口,设置窗口的大小和标题。 3. 定义游戏元素:定义游戏中的方块、方块的形状、方块的颜色等元素。 4. 创建游戏循环:创建一个游戏循环,不断更新游戏状态和绘制游戏画面。 5. 处理用户输入:在游戏循环中,监听用户的键盘输入,并根据输入来移动和旋转方块。 6. 更新游戏状态:在游戏循环中,更新方块的位置和状态,检查是否有方块需要固定在底部。 7. 检查游戏结束:在游戏循环中,检查游戏是否结束,即方块堆积到达游戏区域的顶部。 8. 绘制游戏画面:在游戏循环中,使用`pygame`模块的绘图函数,将游戏元素绘制到游戏窗口中。 9. 循环更新游戏:在游戏循环中,不断更新游戏状态和绘制游戏画面,使游戏运行流畅。 以上是一个基本的思路,具体实现时可以根据需要添加更多的功能,例如计分、下落速度逐渐加快等。可以参考中提供的资料来更深入了解俄罗斯方块游戏的历史和开发背景。<span class="em">1</span><span class="em">2</span> #### 引用[.reference_title] - *1* *2* [俄罗斯方块游戏Python实现)](https://blog.csdn.net/weixin_46039719/article/details/123284718)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值