最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Pygame用200行代碼實(shí)現(xiàn)俄羅斯方塊

 更新時(shí)間:2023年12月15日 09:10:18   作者:微小冷  
俄羅斯方塊的邏輯很簡單,就是幾個(gè)方塊組合在一起,然后下落,當(dāng)其碰到四周的墻壁后便無法移動(dòng),若某行被方塊所填滿,那么就刪除這一行,然后此行上面的所有方塊下降一行,本文給大家介紹了用Pygame實(shí)現(xiàn)俄羅斯方塊,文中代碼示例介紹的非常詳細(xì),需要的朋友可以參考下

邏輯設(shè)計(jì)

俄羅斯方塊的邏輯很簡單,就是幾個(gè)方塊組合在一起,然后下落,當(dāng)其碰到四周的墻壁后便無法移動(dòng)。若某行被方塊所填滿,那么就刪除這一行,然后此行上面的所有方塊下降一行。

為了將這個(gè)邏輯代碼化,可以用布爾矩陣來表示具體的方塊類型,比如長條形方塊可用如下矩陣表示。

BLOCK_I = [[0,1,0,0],
           [0,1,0,0],
           [0,1,0,0],
           [0,1,0,0]]

在實(shí)際操作時(shí),會(huì)經(jīng)常遇到旋轉(zhuǎn)操作,其基本邏輯是,將第i ii行變成第− i -i−i列,從而旋轉(zhuǎn)邏輯如下

def rotateBlock(block):
    newBlock = [[[] for _ in block] for b in block[0]]
    for i,row in enumerate(block, 1):
        for j,r in enumerate(row, 0):
            newBlock[j][-i] = r
    return newBlock

定義好所有的方塊,并將其封入列表BLOCK中,

BLOCK_S = [[0,1,1],
           [1,1,0],
           [0,0,0]]

BLOCK_Z = [[1,1,0],
     [0,1,1],
     [0,0,0]]

# I型方塊
BLOCK_I = [[0,1,0,0],
     [0,1,0,0],
     [0,1,0,0],
     [0,1,0,0]],

# O型方塊
BLOCK_O = [[1,1],
            [1,1]]
# J型方塊
BLOCK_J = [[1,0,0],
     [1,1,1],
     [0,0,0]]

# L型方塊
BLOCK_L = [[0,0,1],
     [1,1,1],
     [0,0,0]]

# T型方塊
BLOCK_T = [[0,1,0],
     [1,1,1],
     [0,0,0]]

BLOCKS = [BLOCK_S, BLOCK_I, BLOCK_J, BLOCK_L, BLOCK_O, BLOCK_T, BLOCK_Z]

有了這個(gè),就可以隨機(jī)生成其中某個(gè)方塊了,這個(gè)過程需要引入一點(diǎn)隨機(jī)性

import random
# 創(chuàng)建一個(gè)圖形
def newBlock():
    block = random.choice(BLOCKS)
    for _ in range(random.randint(0,4)):
        block = rotateBlock(block)
    return block

挪動(dòng)邏輯

原理十分簡單,但想要寫出一個(gè)可以玩的游戲,卻還需要注意一些細(xì)節(jié)問題。比如俄羅斯方塊在碰到墻壁時(shí)的行為;旋轉(zhuǎn)方塊的方法。在實(shí)現(xiàn)這些具體問題之前,先設(shè)置幾個(gè)常量

SCREEN_WIDTH, SCREEN_HEIGHT = 450, 750
BLOCK_COL_NUM = 10  # 每行的方格數(shù)
BLOCK_ROW_NUM = 25  # 每列的方個(gè)數(shù)
SIZE = 30  # 每個(gè)小方格大小
BG_COLOR = (40, 40, 60)  # 背景色
RED = (200, 30, 30)  # 紅色,GAME OVER 的字體顏色
WHITE = (255,255,255)   # 白色
BLACK = (0,0,0)         # 黑色
GREEN = (60, 128, 80)   # 綠色
STOP_LST = [[0 for _ in range(BLOCK_COL_NUM)]
               for _ in range(BLOCK_ROW_NUM)]


接下來逐個(gè)實(shí)現(xiàn)俄羅斯方塊的細(xì)節(jié),當(dāng)左右移動(dòng)方塊時(shí),若方塊碰到墻壁,則需要一個(gè)判定函數(shù),代碼如下。其中isR為True時(shí)表示向右移動(dòng),否則向左移動(dòng)。其判斷邏輯非常直觀,只需查看是否超出邊界。

# 判斷是否可以向左右移動(dòng)
# isR為True,判斷能否向右移動(dòng);isR為False,判斷能否向左移動(dòng)
def judgeMoveLR(block, stCol, isR):
    nCol = len(block[0])
    cols = range(nCol-1, -1, -1) if isR else range(nCol)
    for col in cols:
        lstCol = [line[col] for line in block]
        if 1 not in lstCol:
            continue
        if not 0 <= stCol + col < BLOCK_COL_NUM:
            return False
    return True

如果判定成功,則需要移動(dòng)方塊,那么根據(jù)其輸入左移或者右移,可以構(gòu)造一個(gè)函數(shù)

# 相左或者向右移動(dòng)
def moveLR(block, stCol, key):
    isR = key == pygame.K_RIGHT
    stCol = stCol + 1 if isR else stCol - 1
    if judgeMoveLR(block ,stCol, isR):
        return 1 if isR else -1
    return 0

方塊在下落過程中若碰壁,則稍微有些麻煩,因?yàn)橄路娇赡芤呀?jīng)堆積了一些方塊,為此不僅需要知道當(dāng)前下落方塊的信息,還要知道已經(jīng)堆積的方塊的信息。

# 判斷是否可以繼續(xù)下落
def judgeMoveDown(block, stRow, stCol, stopLst):
    # 堆積方塊的位置
    stopPosition = list()
    for row, line in enumerate(stopLst):
        for col, b in enumerate(line):
            if b: stopPosition.append((row, col))
    # 判斷碰撞
    for row, line in enumerate(block):
        if 1 in line and stRow + row >= BLOCK_ROW_NUM:
            return False
        for col, b in enumerate(line):
            if b and (stRow + row, stCol + col) in stopPosition:
                return False
    return True

最后將三者合在一起,用于判斷方塊是否可以繼續(xù)移動(dòng)

def canMove(block, stRow, stCol, stopLst):
    flag = judgeMoveLR(block, stCol, False)
    flag &= judgeMoveLR(block, stCol, True)
    flag &= judgeMoveDown(block, stRow, stCol, stopLst)
    return flag

消除和堆積

其消除邏輯是,當(dāng)某行全為1的時(shí)候,就把這行刪掉,然后在頂端補(bǔ)充全0的列表。

def judgeLines(stopLst):
    # 記錄剛剛消除的行數(shù)
    i, N, count = 0, len(stopLst), 0
    for i in range(N):
        if 0 not in stopLst[i]:
            line = [0]*len(stopLst.pop(i))
            stopLst.insert(0, line)
            count += 10
    return count

堆積邏輯則相對(duì)簡單,只需將堆積部位置為1即可。

# 將停止移動(dòng)的block添加到堆積方塊
def addToStopLst(stopLst, block, stRow, stCol):
    for row, line in enumerate(block):
        for col, b in enumerate(line):
            if b: stopLst[stRow + row][stCol + col] = 1

至此,俄羅斯方塊的操作邏輯便設(shè)計(jì)完成,接下來是繪圖。

參數(shù)邏輯

俄羅斯方塊的下落速度可以區(qū)分不同關(guān)卡,下面是一種用分?jǐn)?shù)決定下落速度的方案,其速度值表示方塊下落的延時(shí)時(shí)間。

def changeSpeed(score):
    scores = [20, 50, 100, 200]
    infos = "12345"
    speeds = [0.5, 0.4, 0.3, 0.2, 0.1]
    ind = bisect(scores, score)
    return infos[ind], speeds[ind]

繪圖邏輯

首先是背景繪制,主要包括背景顏色和網(wǎng)格的繪制。

def drawBackground(screen):
    screen.fill(BG_COLOR)
    width = SIZE * BLOCK_COL_NUM
    pygame.draw.line(screen, BLACK, (width, 0), (width, SCREEN_HEIGHT), 4)
    for x in range(BLOCK_COL_NUM):
        pygame.draw.line(screen, BLACK, (x * SIZE, 0), (x * SIZE, SCREEN_HEIGHT), 1)
    for y in range(BLOCK_ROW_NUM):
        pygame.draw.line(screen, BLACK, (0, y * SIZE), (width, y * SIZE), 1)

這里僅采使用了左側(cè)窗口,其右側(cè)將用于存放提示信息,主要包括得分、速度等級(jí)以及接下來落下的方塊。

def drawRight(screen, score, speedInfo):
    fontPath = r'C:\Windows\Fonts\msyh.ttc'
    font = pygame.font.Font(fontPath, 24)  # 黑體24

    posDct = {
        '得分: ':10, str(score): 50,
        '速度: ':100, speedInfo: 150,
        '下一個(gè):':200
    }
    for k,v in posDct.items():
        msg = font.render(k, True, WHITE)
        screen.blit(msg, (BLOCK_COL_NUM * SIZE + 10, v))

然后是方塊繪制函數(shù),顧名思義,drawBlock繪制一個(gè)方塊,drawBlocks繪制一組方塊。

def drawBlock(screen, row, col, stRow, stCol):
    stRow += row * SIZE
    stCol += SIZE * col
    rect = pygame.Rect(stCol, stRow, SIZE, SIZE)
    pygame.draw.rect(screen, GREEN, rect, 0)
    pygame.draw.rect(screen, BLACK, rect, 1)

def drawBlocks(screen, block, stRow, stCol):
    for row, line in enumerate(block):
        for col, b in enumerate(line):
            if not b: continue
            drawBlock(screen, row, col, stRow, stCol)

最后,若游戲失敗,則彈出失敗信息

def drawGamerOver(screen):
    fontPath = r'C:\Windows\Fonts\msyh.ttc'
    font = pygame.font.Font(fontPath, 72)

    w, h = font.size('GAME OVER')
    msg = font.render('GAME OVER', True, RED)
    screen.blit(msg, ((SCREEN_WIDTH - w) // 2, (SCREEN_HEIGHT - h) // 2))

    # 顯示"鼠標(biāo)點(diǎn)擊任意位置,再來一局"
    font = pygame.font.Font(fontPath, 24)
    w, h = font.size('點(diǎn)擊任意位置,再來一局')
    msg = font.render('點(diǎn)擊任意位置,再來一局', True, RED)
    screen.blit(msg, ((SCREEN_WIDTH - w) // 2, (SCREEN_HEIGHT - h) // 2 + 80))

主程序

主程序內(nèi)容如下,其中initBlock用于初始化方塊。由于大家對(duì)俄羅斯方塊都很熟悉,且所有調(diào)用的子函數(shù)均已說明,所以就不再細(xì)說其流程了。

def initBlock(nextBlock=None):
    stRow, stCol = -2, 4
    nowBlock = nextBlock if nextBlock else newBlock()
    nextBlock = newBlock()
    return stRow, stCol, nowBlock, nextBlock

def main():
    pygame.init()
    screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
    pygame.display.set_caption('俄羅斯方塊')

    # 初始化當(dāng)前圖形的位置,當(dāng)前圖形,以及下一個(gè)圖形
    stRow, stCol, nowBlock, nextBlock = initBlock()
    last_time = time.time()
    speed, speedInfo = 0.5, '1'
    score, gameOver = 0, False
    stopLst = deepcopy(STOP_LST)
    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 in [pygame.K_LEFT, pygame.K_RIGHT]:
                    stCol += moveLR(nowBlock, stCol, event.key)
                elif event.key == pygame.K_UP:
                    rotBlock = rotateBlock(nowBlock)
                    if canMove(rotBlock, stRow, stCol, stopLst):
                        nowBlock = rotBlock
                elif event.key == pygame.K_DOWN:
                    # 判斷是否可以向下移動(dòng),如果碰到底部或者其它的圖形就不能移動(dòng)了
                    while judgeMoveDown(nowBlock, stRow + 1, stCol, stopLst):
                        stRow += 1
            if gameOver:
                stRow, stCol, nowBlock, nextBlock = initBlock()
                stopLst = deepcopy(STOP_LST)
                score = 0
                gameOver = False

        # 判斷是否修改當(dāng)前圖形顯示的起始行
        if not gameOver and time.time() - last_time > speed:
            last_time = time.time()
            # 可以向下移動(dòng)的情形
            if judgeMoveDown(nowBlock, stRow + 1, stCol, stopLst):
                stRow += 1
            else:
                # 不可向下移動(dòng),則需新建一個(gè)block然后下落
                addToStopLst(stopLst, nowBlock, stRow, stCol)
                score += judgeLines(stopLst)
                gameOver =  1 in stopLst[0]             # 第一行中間有1則游戲結(jié)束
                speedInfo, speed = changeSpeed(score)   # 調(diào)整速度
                stRow, stCol, nowBlock, nextBlock = initBlock(nextBlock)

        drawBackground(screen)
        drawRight(screen, score, speedInfo)
        drawBlocks(screen, nowBlock, stRow*SIZE, stCol*SIZE)    # 當(dāng)前方塊
        drawBlocks(screen, stopLst, 0, 0)                       # 堆積方塊
        drawBlocks(screen, nextBlock, 300, 320)                 # 下一個(gè)方塊

        # 顯示游戲結(jié)束畫面
        if gameOver:
            drawGamerOver(screen)

        pygame.display.update()
        clock.tick(60)  # 通過一定的延時(shí),實(shí)現(xiàn)1秒鐘能夠循環(huán)60次

最終游戲效果如下

以上就是Pygame用200行代碼實(shí)現(xiàn)俄羅斯方塊的詳細(xì)內(nèi)容,更多關(guān)于Pygame俄羅斯方塊的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 基于Python+PyQt5實(shí)現(xiàn)漢字轉(zhuǎn)拼音的智能轉(zhuǎn)換工具

    基于Python+PyQt5實(shí)現(xiàn)漢字轉(zhuǎn)拼音的智能轉(zhuǎn)換工具

    在中文自然語言處理和學(xué)習(xí)中,漢字轉(zhuǎn)拼音是一個(gè)基礎(chǔ)但至關(guān)重要的功能,本文將詳細(xì)介紹如何使用Python開發(fā)一個(gè)功能全面的漢字轉(zhuǎn)拼音工具,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下
    2026-03-03
  • Python安裝OpenCV庫超時(shí)失敗解決

    Python安裝OpenCV庫超時(shí)失敗解決

    使用pip?installopencv-python安裝時(shí),安裝速度很慢,本文主要介紹了Python安裝OpenCV庫超時(shí)失敗,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-05-05
  • python 機(jī)器學(xué)習(xí)的標(biāo)準(zhǔn)化、歸一化、正則化、離散化和白化

    python 機(jī)器學(xué)習(xí)的標(biāo)準(zhǔn)化、歸一化、正則化、離散化和白化

    這篇文章主要介紹了聊聊機(jī)器學(xué)習(xí)的標(biāo)準(zhǔn)化、歸一化、正則化、離散化和白化,幫助大家更好的理解和學(xué)習(xí)使用python進(jìn)行機(jī)器學(xué)習(xí),感興趣的朋友可以了解下
    2021-04-04
  • 談?wù)勅绾问謩?dòng)釋放Python的內(nèi)存

    談?wù)勅绾问謩?dòng)釋放Python的內(nèi)存

    Python不會(huì)自動(dòng)清理這些內(nèi)存,這篇文章主要介紹了談?wù)勅绾问謩?dòng)釋放Python的內(nèi)存,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2016-12-12
  • Pycharm-community-2021版安裝和配置

    Pycharm-community-2021版安裝和配置

    pycharm-community-PyCharm是一種Python IDE,帶有一整套可以幫助用戶在使用Python語言開發(fā)時(shí)提高其效率的工具,本文就來介紹一下Pycharm-community-2021版安裝和配置,感興趣的可以了解一下
    2023-11-11
  • python包管理工具pip全面解析

    python包管理工具pip全面解析

    這篇文章主要為大家介紹了python包管理工具pip的全面解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • Python 中 fuzzywuzzy 進(jìn)行字符串模糊匹配的全過程

    Python 中 fuzzywuzzy 進(jìn)行字符串模糊匹配的全過程

    fuzzywuzzy是一個(gè)用于字符串模糊匹配的Python庫,基于Levenshtein距離算法,提供多種核心函數(shù)來計(jì)算字符串相似度,庫廣泛應(yīng)用于數(shù)據(jù)清洗、拼寫糾錯(cuò)、文本挖掘和用戶輸入處理等領(lǐng)域,本文給大家介紹Python中fuzzywuzzy字符串模糊匹配的全過程,感興趣的朋友跟隨小編一起看看吧
    2026-01-01
  • Python之LRU緩存應(yīng)用與實(shí)例

    Python之LRU緩存應(yīng)用與實(shí)例

    LRU(最近最少使用)是高效緩存淘汰算法,通過OrderedDict維護(hù)訪問順序,實(shí)現(xiàn)O(1)時(shí)間復(fù)雜度的get/put操作,適用于Web應(yīng)用和配置管理,但不適用于強(qiáng)一致性場景或超大數(shù)據(jù)集
    2025-10-10
  • qpython3 讀取安卓lastpass Cookies

    qpython3 讀取安卓lastpass Cookies

    這篇文章主要介紹了qpython3 讀取安卓lastpass Cookies的相關(guān)資料,需要的朋友可以參考下
    2016-06-06
  • 利用Python編寫一個(gè)簡單的聊天機(jī)器人

    利用Python編寫一個(gè)簡單的聊天機(jī)器人

    這篇文章主要為大家詳細(xì)介紹了如何利用Python編寫一個(gè)簡單的聊天機(jī)器人,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-01-01

最新評(píng)論

朝阳县| 高平市| 克山县| 福建省| 宝清县| 西平县| 武鸣县| 沙雅县| 汤阴县| 乐业县| 兴海县| 商都县| 清远市| 丹凤县| 色达县| 新源县| 平罗县| 曲沃县| 滦平县| 合作市| 林西县| 宜良县| 余江县| 彭水| 崇明县| 平谷区| 盐津县| 陕西省| 吴旗县| 宝山区| 禄丰县| 绥芬河市| 五峰| 新竹县| 阿勒泰市| 武功县| 朝阳市| 东莞市| 斗六市| 鄂托克前旗| 高陵县|