【Python】用Python寫一個俄羅斯方塊玩玩

【Python】用Python寫一個俄羅斯方塊玩玩

  • 一、引言
    • 1.成品效果展示
  • 二、思考準備
    • 1.思考設計
    • 2.代碼設計
      • 2.1 游戲頁面
      • 2.2 控件設計
        • 2.2.1 方塊生成
        • 2.2.2 方塊碰撞
        • 2.2.3 方塊消融
        • 2.2.4 游戲主循環
        • 2.2.5 游戲窗口
  • 三、游戲完整版

一、引言

  • 今日看到侄子在玩游戲,湊近一看,原來是俄羅斯方塊。熟悉又懷念,童年的記憶瞬間涌上心頭。小時候覺得這游戲老厲害了,現在想想,好像就是數組的組合和消融,便想著自己寫一個試試。說干就干,沖!

1.成品效果展示

俄羅斯方塊實現過程

二、思考準備

1.思考設計

在這里插入圖片描述

  • 俄羅斯方塊作為風靡一時的游戲,由俄羅斯人阿列克謝·帕基特諾夫于1984年6月發明的休閑游戲,主要是通過方塊的組合、消融完成的;
  • 所以得先設計有哪些方塊、方塊如何組合、完成一行時方塊消融并下降一行、方塊組合還得回旋轉,單次90°等等,考慮中ing…

2.代碼設計

2.1 游戲頁面

  • 游戲首先得有個操控頁面,所以得設計一個
# 設計游戲窗口尺寸
SCREEN_WIDTH, SCREEN_HEIGHT = 300, 600  
# 方塊大小
GRID_SIZE = 30     
# 各種圖形顏色 可自定義調整                    
COLORS = [            # 顏色配置(含背景色+7種方塊色)(0, 0, 0),        # 0: 黑色背景(255, 0, 0),      # 1: 紅色-I型(0, 255, 0),      # 2: 綠色-T型(0, 0, 255),      # 3: 藍色-J型(255, 165, 0),    # 4: 橙色-L型(255, 255, 0),    # 5: 黃色-O型(128, 0, 128),    # 6: 紫色-S型(0, 255, 255)     # 7: 青色-Z型
]

2.2 控件設計

2.2.1 方塊生成
  • 游戲開始最上方會有方塊掉落,隨機形狀和顏色

def new_piece(self):"""生成新方塊,隨機形狀和顏色"""shape = random.choice(SHAPES)return {'shape': shape,                                        # 方塊形狀矩陣'x': (SCREEN_WIDTH//GRID_SIZE - len(shape[0])) // 2,   # 初始水平居中'y': 0,                                                # 初始垂直位置'color': random.randint(1, len(COLORS)-1)              # 隨機顏色(排除背景色)}
2.2.2 方塊碰撞
  • 方塊會一直下降,碰撞,下降時還要符合可以多次旋轉

def check_collision(self, dx=0, dy=0, rotate=False):"""碰撞檢測函數:param dx: 水平移動偏移量:param dy: 垂直移動偏移量:param rotate: 是否正在旋轉:return: 是否發生碰撞"""shape = self.current_piece['shape']# 旋轉時生成臨時形狀if rotate:         shape = [list(row[::-1]) for row in zip(*shape)]  # 矩陣旋轉算法:先轉置再反轉每行(順時針90度)for y, row in enumerate(shape):for x, cell in enumerate(row):if cell:                        # 僅檢測實體方塊new_x = self.current_piece['x'] + x + dxnew_y = self.current_piece['y'] + y + dy# 邊界檢測(左右越界/觸底/與其他方塊重疊)if not (0 <= new_x < len(self.grid[0])) or new_y >= len(self.grid):return Trueif new_y >=0 and self.grid[new_y][new_x]:return Truereturn False
2.2.3 方塊消融
  • 方塊接觸時,合適的會消融、不合適的會疊加,消融了計算分數,消融的還要剔除
def merge_piece(self):"""將當前方塊合并到游戲網格,并觸發消行檢測"""for y, row in enumerate(self.current_piece['shape']):for x, cell in enumerate(row):if cell:# 將方塊顏色寫入網格對應位置self.grid[self.current_piece['y']+y][self.current_piece['x']+x] = self.current_piece['color']# 消行并更新分數lines = self.clear_lines()self.score += lines * 100def clear_lines(self):"""消除滿行并返回消除行數"""lines = 0# 從底部向上掃描for i, row in enumerate(self.grid):if all(cell !=0 for cell in row):       # 檢測整行填滿del self.grid[i]                    # 刪除該行self.grid.insert(0, [0]*len(row))   # 在頂部插入新空行lines +=1return lines
2.2.4 游戲主循環
  • 游戲主體邏輯寫入,方塊的處理時間、操作事項和刷新等

def run(self):"""游戲主循環"""fall_time = 0       # 下落時間累計器while True:self.screen.fill(COLORS[0])            # 用背景色清屏# 計時系統(控制自動下落速度)fall_time += self.clock.get_rawtime()self.clock.tick()        # 保持幀率穩定# 自動下落邏輯(每800ms下落一格)if fall_time >= 800:if not self.check_collision(dy=1):self.current_piece['y'] +=1                 # 正常下落else:self.merge_piece()                          # 觸底合并self.current_piece = self.new_piece()       # 生成新方塊# 游戲結束檢測(新方塊無法放置)if self.check_collision():print("Game Over 你完蛋啦! Score:", self.score)returnfall_time =0   # 重置計時器# 事件處理(適配Mac鍵盤布局)for event in pygame.event.get():if event.type == QUIT:pygame.quit()returnif event.type == KEYDOWN:# 左右移動(帶碰撞檢測)if event.key == K_LEFT and not self.check_collision(dx=-1):self.current_piece['x'] -=1elif event.key == K_RIGHT and not self.check_collision(dx=1):self.current_piece['x'] +=1# 軟下落(手動加速)elif event.key == K_DOWN:if not self.check_collision(dy=1):self.current_piece['y'] +=1# 旋轉方塊(帶碰撞檢測)elif event.key == K_UP and not self.check_collision(rotate=True):self.current_piece['shape'] = [list(row[::-1]) for row in zip(*self.current_piece['shape'])]# 硬下落(空格鍵一鍵到底)    elif event.key == K_SPACE:  while not self.check_collision(dy=1):self.current_piece['y'] +=1# 繪制邏輯,游戲網格for y, row in enumerate(self.grid):for x, color in enumerate(row):if color:# 繪制已落下方塊(留1像素間隙)pygame.draw.rect(self.screen, COLORS[color], (x*GRID_SIZE, y*GRID_SIZE, GRID_SIZE-1, GRID_SIZE-1))# 繪制當前操作方塊for y, row in enumerate(self.current_piece['shape']):for x, cell in enumerate(row):if cell:pygame.draw.rect(self.screen, COLORS[self.current_piece['color']],((self.current_piece['x']+x)*GRID_SIZE, (self.current_piece['y']+y)*GRID_SIZE, GRID_SIZE-1, GRID_SIZE-1))# 刷新畫面pygame.display.flip()  
2.2.5 游戲窗口
  • 最后,游戲設計好了,必須有個游戲窗口來展示

def __init__(self):# 初始化游戲窗口self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))pygame.display.set_caption("Mac M1俄羅斯方塊")self.clock = pygame.time.Clock()   # 游戲時鐘控制幀率# 游戲狀態初始化self.grid = [[0]*(SCREEN_WIDTH//GRID_SIZE) for _ in range(SCREEN_HEIGHT//GRID_SIZE)]              # 20x10游戲網格self.current_piece = self.new_piece()     # 當前操作方塊self.score = 0                           

三、游戲完整版


# 俄羅斯方塊設計
# -*- coding: utf-8 -*-  
"""
功能:俄羅斯方塊,童年的回憶
作者:看海的四叔
最后更新:2025-04-16
"""import pygame
import random
from pygame.locals import *# 初始化配置
pygame.init()                           
SCREEN_WIDTH, SCREEN_HEIGHT = 300, 600  
GRID_SIZE = 30                          
COLORS = [            (0, 0, 0),        (255, 0, 0),      (0, 255, 0),      (0, 0, 255),      (255, 165, 0),    (255, 255, 0),    (128, 0, 128),    (0, 255, 255)     
]SHAPES = [[[1,1,1,1]],                [[1,1],[1,1]],              [[0,1,0], [1,1,1]],         [[1,1,1], [1,0,0]],         [[1,1,1], [0,0,1]],         [[0,1,1], [1,1,0]],         [[1,1,0], [0,1,1]]          
]class Tetris:"""游戲主控制類,處理游戲邏輯與渲染"""def __init__(self):self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))pygame.display.set_caption("Mac M1俄羅斯方塊")self.clock = pygame.time.Clock()  self.grid = [[0]*(SCREEN_WIDTH//GRID_SIZE) for _ in range(SCREEN_HEIGHT//GRID_SIZE)] self.current_piece = self.new_piece()    self.score = 0                           def new_piece(self):"""生成新方塊(隨機形狀和顏色)"""shape = random.choice(SHAPES)return {'shape': shape,                                        'x': (SCREEN_WIDTH//GRID_SIZE - len(shape[0])) // 2,   'y': 0,                                                'color': random.randint(1, len(COLORS)-1)              }def check_collision(self, dx=0, dy=0, rotate=False):"""碰撞檢測函數:param dx: 水平移動偏移量:param dy: 垂直移動偏移量:param rotate: 是否正在旋轉:return: 是否發生碰撞"""shape = self.current_piece['shape']if rotate:         shape = [list(row[::-1]) for row in zip(*shape)]  for y, row in enumerate(shape):for x, cell in enumerate(row):if cell:                       new_x = self.current_piece['x'] + x + dxnew_y = self.current_piece['y'] + y + dyif not (0 <= new_x < len(self.grid[0])) or new_y >= len(self.grid):return Trueif new_y >=0 and self.grid[new_y][new_x]:return Truereturn Falsedef merge_piece(self):"""將當前方塊合并到游戲網格,并觸發消行檢測"""for y, row in enumerate(self.current_piece['shape']):for x, cell in enumerate(row):if cell:self.grid[self.current_piece['y']+y][self.current_piece['x']+x] = self.current_piece['color']lines = self.clear_lines()self.score += lines * 100def clear_lines(self):"""消除滿行并返回消除行數"""lines = 0for i, row in enumerate(self.grid):if all(cell !=0 for cell in row):       del self.grid[i]                    self.grid.insert(0, [0]*len(row))   lines +=1return linesdef run(self):"""游戲主循環"""fall_time = 0      while True:self.screen.fill(COLORS[0])           fall_time += self.clock.get_rawtime()self.clock.tick()       if fall_time >= 800:if not self.check_collision(dy=1):self.current_piece['y'] +=1                 # 正常下落else:self.merge_piece()                          self.current_piece = self.new_piece()       # 游戲結束檢測(新方塊無法放置)if self.check_collision():print("Game Over 你完蛋啦! Score:", self.score)returnfall_time =0   # 重置計時器for event in pygame.event.get():if event.type == QUIT:pygame.quit()returnif event.type == KEYDOWN:if event.key == K_LEFT and not self.check_collision(dx=-1):self.current_piece['x'] -=1elif event.key == K_RIGHT and not self.check_collision(dx=1):self.current_piece['x'] +=1elif event.key == K_DOWN:if not self.check_collision(dy=1):self.current_piece['y'] +=1elif event.key == K_UP and not self.check_collision(rotate=True):self.current_piece['shape'] = [list(row[::-1]) for row in zip(*self.current_piece['shape'])]elif event.key == K_SPACE:  while not self.check_collision(dy=1):self.current_piece['y'] +=1for y, row in enumerate(self.grid):for x, color in enumerate(row):if color:pygame.draw.rect(self.screen, COLORS[color], (x*GRID_SIZE, y*GRID_SIZE, GRID_SIZE-1, GRID_SIZE-1))for y, row in enumerate(self.current_piece['shape']):for x, cell in enumerate(row):if cell:pygame.draw.rect(self.screen, COLORS[self.current_piece['color']],((self.current_piece['x']+x)*GRID_SIZE, (self.current_piece['y']+y)*GRID_SIZE, GRID_SIZE-1, GRID_SIZE-1))pygame.display.flip()  if __name__ == "__main__":game = Tetris()game.run()

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/901858.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/901858.shtml
英文地址,請注明出處:http://en.pswp.cn/news/901858.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

維港首秀!沃飛長空AE200亮相香港特別行政區

4月13日-16日&#xff0c;第三屆香港國際創科展在香港會議展覽中心盛大舉辦。 作為國內領先、國際一流的eVTOL主機廠&#xff0c;沃飛長空攜旗下AE200批產構型登陸國際舞臺&#xff0c;以前瞻性的創新技術與商業化應用潛力&#xff0c;吸引了來自全球17個國家及地區的行業領袖…

Openfein實現遠程調用的方法(實操)

文章目錄 環境準備一、URL中接收參數二、接收一個參數三、接收多個參數四、傳遞對象五、傳遞JSON格式數據 環境準備 下面的配置&#xff0c;服務調用方加入即可。 依賴導入&#xff1a; <!-- openfeign依賴--><dependency><groupId>org.springframe…

Bright+Data網頁解鎖器:旅游行業數據革命的“隱形引擎”

在數字經濟浪潮中&#xff0c;旅游行業正經歷前所未有的變革。當消費者指尖滑動間完成跨國酒店預訂&#xff0c;當航空公司每秒調整萬次艙位價格&#xff0c;背后是一場無聲的數據戰爭。而在這場戰爭中&#xff0c;BrightData網頁解鎖器正成為旅游企業破局的關鍵武器——它像一…

OpenCV 圖形API(38)圖像濾波-----Sobel 算子操作函數Sobel()

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 算法描述 cv::gapi::Sobel 函數是 OpenCV 的 G-API 模塊中用于執行 Sobel 算子操作的一個函數&#xff0c;主要用于圖像的邊緣檢測。Sobel 算子通過計算圖…

CS5346 - Interactivity in Visualization 可視化中的交互

文章目錄 Visualization representation interactionInteraction &#xff08;交互&#xff09;Benefits (好處)Typical Interaction Techniques&#xff08;交互技術&#xff09;SelectFilteringAbstract / Elaborate幾何放縮&#xff08;Geometric zoom)語義放縮&#xff0…

第十六屆藍橋杯大賽軟件賽省賽 C++ 大學 B 組 部分題解

賽時參加的是Python組&#xff0c;這是賽后寫的題解&#xff0c;還有兩題暫時還不會&#xff0c;待更新 題目鏈接題目列表 - 洛谷 | 計算機科學教育新生態 A 移動距離 答案&#xff1a;1576 C 可分解的正整數 Python3 import itertools from functools import cmp_to_ke…

Vue 解決 Error: please transfer a valid prop path to form item!

在 Vue.js 中使用表單驗證庫&#xff08;如 VeeValidate 或 Element UI 的表單組件時&#xff09;&#xff0c;遇到錯誤信息 "please transfer a valid prop path to form item!" 通常指的是在表單項的屬性綁定中&#xff0c;路徑&#xff08;prop path&#xff09;不…

在 Visual Studio Code 中安裝通義靈碼 - 智能編碼助手

高效的編碼工具對于提升開發效率和代碼質量至關重要。 通義靈碼作為一款智能編碼助手&#xff0c;為開發者提供了全方位的支持。 本文將詳細介紹如何在 Visual Studio Code&#xff08;簡稱 VSCode&#xff09;中安裝通義靈碼&#xff0c;以及如何進行相關配置以開啟智能編碼…

SQL 解析 with as dual sysdate level

目錄 sql的運行順序 with as EXTRACT ?編輯 dual sysdate level ?編輯 ?編輯 Oracle中的日期存儲 核心部分 拆解字符串并計算最小值 關聯子查詢 NVL 函數 REGEXP_SUBSTR() sql的運行順序 <select id="getTrendList" parameterType="java.uti…

快手OneRec 重構推薦系統:從檢索排序到生成統一的躍遷

文章目錄 1. 背景2. 方法2.1 OneRec框架2.2 Preliminary2.3 生成會話列表2.4 利用獎勵模型進行迭代偏好對齊2.4.1 訓練獎勵模型2.4.2 迭代偏好對齊 3. 總結 昨天面試的時候聊到了OneRec&#xff0c;但是由于上次看這篇文章已經是一個月之前&#xff0c;忘得差不多了&#xff0c…

軟考高級系統架構設計師-第11章 系統架構設計

【本章學習建議】 根據考試大綱&#xff0c;本章不僅考查系統架構設計師單選題&#xff0c;預計考12分左右&#xff0c;而且案例分析和論文寫作也是必考&#xff0c;對應第二版教材第7章&#xff0c;屬于重點學習的章節。 軟考高級系統架構設計師VIP課程https://edu.csdn.net/…

selenium之文件下載

Selenium 自動化測試&#xff1a;輕松搞定文件下載 在 Web 自動化測試中&#xff0c;經常會遇到需要驗證文件下載功能的場景。例如&#xff0c;測試報告的導出、用戶上傳文件的下載、PDF 文檔的生成與下載等等。Selenium 本身并沒有直接處理文件下載的內置方法&#xff0c;但我…

基于遷移學習實現肺炎X光片診斷分類

大家好&#xff0c;我是帶我去滑雪&#xff01; 肺炎是全球范圍內致死率較高的疾病之一&#xff0c;尤其是在老年人、免疫系統較弱的患者群體中&#xff0c;更容易引發嚴重并發癥。傳統上&#xff0c;肺炎的診斷依賴于醫生的臨床經驗以及影像學檢查&#xff0c;尤其是X光片&…

工業數據治理范式革新:時序數據庫 TDengine虛擬表技術解析

小T導讀&#xff1a;在工業數字化過程中&#xff0c;數據如何從設備采集順利“爬坡”到上層應用&#xff0c;一直是個難題。傳統“單列模型”雖貼合設備協議&#xff0c;卻讓上層分析舉步維艱。TDengine 用一種更聰明的方法打通了這條數據通路&#xff1a;不強求建模、不手動轉…

Redis面試——日志

一、RDB&#xff08;Redis DataBase&#xff09; RDB 全程是 Redis DataBase&#xff0c;它是一種將 Redis 在某一時刻內存中的數據以快照形式保存到磁盤的機制 &#xff0c;相當于給執行save/bgsave命令時刻的內存數據庫數據拍了一張快照我們如果通過save命令來執行快照&…

【Android】常用參數實踐 用戶界面UI 布局文件XML

本文將系統總結 Android XML 布局的通用參數和常用布局類型的專屬規則 一、通用布局參數 這些參數適用于所有 View 和 ViewGroup&#xff0c;是布局設計的基石。 1. 尺寸控制 android:layout_width 與 android:layout_height 定義視圖的寬度和高度&#xff0c;可選值&#xf…

解決 VSCode 中 NVM 配置后無法識別 Node 和 NPM 的問題

在開發中&#xff0c;我們經常需要使用 Node.js 和 NPM 來管理 JavaScript 項目依賴&#xff0c;而 NVM&#xff08;Node Version Manager&#xff09;是開發者在本地環境中管理多個 Node.js 版本的得力工具。不過&#xff0c;有時候在 VSCode 中配置完 NVM 后&#xff0c;可能…

BGP分解實驗·23——BGP選路原則之路由器標識

在選路原則需要用到Router-ID做選路決策時&#xff0c;其對等體Router-ID較小的路由將被優選&#xff1b;其中&#xff0c;當路由被反射時&#xff0c;包含起源器ID屬性時&#xff0c;該屬性將代替router-id做比較。 實驗拓撲如下&#xff1a; 實驗通過調整路由器R1和R2的rout…

Linux: 線程同步

目錄 一 前言 二 線程饑餓 三 線程同步 四 條件變量 1. cond &#xff08; condition&#xff09; 2. pthread_cond_wait() &#xff1a; 3. pthread_cond_signal() 五 條件變量的使用 一 前言 在上篇文章Linux : 多線程互斥-CSDN博客我們講解了線程互斥的概念&#xff…

MyBatisPlus-QueryWrapper的exists方法拼接SQL中的EXISTS子句

在 MyBatis-Plus 中,QueryWrapper 的 exists 方法用于拼接 SQL 中的 EXISTS 子句,通常用于構 建子查詢條件。以下是具體用法和示例: ??1. 基本語法?? // 判斷是否存在符合條件的記錄 queryWrapper.exists(String existsSql); queryWrapper.notExists(String existsSq…