python實(shí)現(xiàn)簡(jiǎn)單的俄羅斯方塊
本文實(shí)例為大家分享了python實(shí)現(xiàn)簡(jiǎn)單的俄羅斯方塊的具體代碼,供大家參考,具體內(nèi)容如下
1. 案例介紹
俄羅斯方塊是由 4 個(gè)小方塊組成不同形狀的板塊,隨機(jī)從屏幕上方落下,按方向鍵調(diào)整板塊的位置和方向,在底部拼出完整的一行或幾行。這些完整的橫條會(huì)消失,給新落下來(lái)的板塊騰出空間,并獲得分?jǐn)?shù)獎(jiǎng)勵(lì)。沒(méi)有被消除掉的方塊不斷堆積,一旦堆到頂端,便告輸,游戲結(jié)束。本例難度為高級(jí),適合具有 Python 進(jìn)階和 Pygame 編程技巧的用戶學(xué)習(xí)。
2. 設(shè)計(jì)要點(diǎn)
邊框――由 15*25 個(gè)空格組成,方塊就落在這里面。盒子――組成方塊的其中小方塊,是組成方塊的基本單元。方塊――從邊框頂?shù)粝碌臇|西,游戲者可以翻轉(zhuǎn)和改變位置。每個(gè)方塊由 4 個(gè)盒子組成。形狀――不同類型的方塊。這里形狀的名字被叫做 T, S, Z ,J, L, I , O。如下圖所示:
模版――用一個(gè)列表存放形狀被翻轉(zhuǎn)后的所有可能樣式。全部存放在變量里,變量名字如 S or J。著陸――當(dāng)一個(gè)方塊到達(dá)邊框的底部或接觸到在其他的盒子話,就說(shuō)這個(gè)方塊著陸了。那樣的話,另一個(gè)方塊就會(huì)開(kāi)始下落。
3. 示例效果
4. 示例源碼
import pygame import random import os ? pygame.init() ? GRID_WIDTH = 20 GRID_NUM_WIDTH = 15 GRID_NUM_HEIGHT = 25 WIDTH, HEIGHT = GRID_WIDTH * GRID_NUM_WIDTH, GRID_WIDTH * GRID_NUM_HEIGHT SIDE_WIDTH = 200 SCREEN_WIDTH = WIDTH + SIDE_WIDTH WHITE = (0xff, 0xff, 0xff) BLACK = (0, 0, 0) LINE_COLOR = (0x33, 0x33, 0x33) ? CUBE_COLORS = [ ? ? (0xcc, 0x99, 0x99), (0xff, 0xff, 0x99), (0x66, 0x66, 0x99), ? ? (0x99, 0x00, 0x66), (0xff, 0xcc, 0x00), (0xcc, 0x00, 0x33), ? ? (0xff, 0x00, 0x33), (0x00, 0x66, 0x99), (0xff, 0xff, 0x33), ? ? (0x99, 0x00, 0x33), (0xcc, 0xff, 0x66), (0xff, 0x99, 0x00) ] ? screen = pygame.display.set_mode((SCREEN_WIDTH, HEIGHT)) pygame.display.set_caption("俄羅斯方塊") clock = pygame.time.Clock() FPS = 30 ? score = 0 level = 1 ? screen_color_matrix = [[None] * GRID_NUM_WIDTH for i in range(GRID_NUM_HEIGHT)] ? # 設(shè)置游戲的根目錄為當(dāng)前文件夾 base_folder = os.path.dirname(__file__) ? ? def show_text(surf, text, size, x, y, color=WHITE): ? ? font_name = os.path.join(base_folder, 'font/font.ttc') ? ? font = pygame.font.Font(font_name, size) ? ? text_surface = font.render(text, True, color) ? ? text_rect = text_surface.get_rect() ? ? text_rect.midtop = (x, y) ? ? surf.blit(text_surface, text_rect) class CubeShape(object): ? ? SHAPES = ['I', 'J', 'L', 'O', 'S', 'T', 'Z'] ? ? I = [[(0, -1), (0, 0), (0, 1), (0, 2)], ? ? ? ? ?[(-1, 0), (0, 0), (1, 0), (2, 0)]] ? ? J = [[(-2, 0), (-1, 0), (0, 0), (0, -1)], ? ? ? ? ?[(-1, 0), (0, 0), (0, 1), (0, 2)], ? ? ? ? ?[(0, 1), (0, 0), (1, 0), (2, 0)], ? ? ? ? ?[(0, -2), (0, -1), (0, 0), (1, 0)]] ? ? L = [[(-2, 0), (-1, 0), (0, 0), (0, 1)], ? ? ? ? ?[(1, 0), (0, 0), (0, 1), (0, 2)], ? ? ? ? ?[(0, -1), (0, 0), (1, 0), (2, 0)], ? ? ? ? ?[(0, -2), (0, -1), (0, 0), (-1, 0)]] ? ? O = [[(0, 0), (0, 1), (1, 0), (1, 1)]] ? ? S = [[(-1, 0), (0, 0), (0, 1), (1, 1)], ? ? ? ? ?[(1, -1), (1, 0), (0, 0), (0, 1)]] ? ? T = [[(0, -1), (0, 0), (0, 1), (-1, 0)], ? ? ? ? ?[(-1, 0), (0, 0), (1, 0), (0, 1)], ? ? ? ? ?[(0, -1), (0, 0), (0, 1), (1, 0)], ? ? ? ? ?[(-1, 0), (0, 0), (1, 0), (0, -1)]] ? ? Z = [[(0, -1), (0, 0), (1, 0), (1, 1)], ? ? ? ? ?[(-1, 0), (0, 0), (0, -1), (1, -1)]] ? ? SHAPES_WITH_DIR = { ? ? ? ? 'I': I, 'J': J, 'L': L, 'O': O, 'S': S, 'T': T, 'Z': Z ? ? } ? ? def __init__(self): ? ? ? ? self.shape = self.SHAPES[random.randint(0, len(self.SHAPES) - 1)] ? ? ? ? # 骨牌所在的行列 ? ? ? ? self.center = (2, GRID_NUM_WIDTH // 2) ? ? ? ? self.dir = random.randint(0, len(self.SHAPES_WITH_DIR[self.shape]) - 1) ? ? ? ? self.color = CUBE_COLORS[random.randint(0, len(CUBE_COLORS) - 1)] ? ? def get_all_gridpos(self, center=None): ? ? ? ? curr_shape = self.SHAPES_WITH_DIR[self.shape][self.dir] ? ? ? ? if center is None: ? ? ? ? ? ? center = [self.center[0], self.center[1]] ? ? ? ? return [(cube[0] + center[0], cube[1] + center[1]) ? ? ? ? ? ? ? ? for cube in curr_shape] ? ? def conflict(self, center): ? ? ? ? for cube in self.get_all_gridpos(center): ? ? ? ? ? ? # 超出屏幕之外,說(shuō)明不合法 ? ? ? ? ? ? if cube[0] < 0 or cube[1] < 0 or cube[0] >= GRID_NUM_HEIGHT or \ ? ? ? ? ? ? ? ? ? ? cube[1] >= GRID_NUM_WIDTH: ? ? ? ? ? ? ? ? return True ? ? ? ? ? ? # 不為None,說(shuō)明之前已經(jīng)有小方塊存在了,也不合法 ? ? ? ? ? ? if screen_color_matrix[cube[0]][cube[1]] is not None: ? ? ? ? ? ? ? ? return True ? ? ? ? return False ? ? def rotate(self): ? ? ? ? new_dir = self.dir + 1 ? ? ? ? new_dir %= len(self.SHAPES_WITH_DIR[self.shape]) ? ? ? ? old_dir = self.dir ? ? ? ? self.dir = new_dir ? ? ? ? if self.conflict(self.center): ? ? ? ? ? ? self.dir = old_dir ? ? ? ? ? ? return False ? ? def down(self): ? ? ? ? # import pdb; pdb.set_trace() ? ? ? ? center = (self.center[0] + 1, self.center[1]) ? ? ? ? if self.conflict(center): ? ? ? ? ? ? return False ? ? ? ? self.center = center ? ? ? ? return True ? ? def left(self): ? ? ? ? center = (self.center[0], self.center[1] - 1) ? ? ? ? if self.conflict(center): ? ? ? ? ? ? return False ? ? ? ? self.center = center ? ? ? ? return True ? ? def right(self): ? ? ? ? center = (self.center[0], self.center[1] + 1) ? ? ? ? if self.conflict(center): ? ? ? ? ? ? return False ? ? ? ? self.center = center ? ? ? ? return True ? ? def draw(self): ? ? ? ? for cube in self.get_all_gridpos(): ? ? ? ? ? ? pygame.draw.rect(screen, self.color, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(cube[1] * GRID_WIDTH, cube[0] * GRID_WIDTH, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GRID_WIDTH, GRID_WIDTH)) ? ? ? ? ? ? pygame.draw.rect(screen, WHITE, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(cube[1] * GRID_WIDTH, cube[0] * GRID_WIDTH, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GRID_WIDTH, GRID_WIDTH), ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?1) def draw_grids(): ? ? for i in range(GRID_NUM_WIDTH): ? ? ? ? pygame.draw.line(screen, LINE_COLOR, ? ? ? ? ? ? ? ? ? ? ? ? ?(i * GRID_WIDTH, 0), (i * GRID_WIDTH, HEIGHT)) ? ? for i in range(GRID_NUM_HEIGHT): ? ? ? ? pygame.draw.line(screen, LINE_COLOR, ? ? ? ? ? ? ? ? ? ? ? ? ?(0, i * GRID_WIDTH), (WIDTH, i * GRID_WIDTH)) ? ? pygame.draw.line(screen, WHITE, ? ? ? ? ? ? ? ? ? ? ?(GRID_WIDTH * GRID_NUM_WIDTH, 0), ? ? ? ? ? ? ? ? ? ? ?(GRID_WIDTH * GRID_NUM_WIDTH, GRID_WIDTH * GRID_NUM_HEIGHT)) def draw_matrix(): ? ? for i, row in zip(range(GRID_NUM_HEIGHT), screen_color_matrix): ? ? ? ? for j, color in zip(range(GRID_NUM_WIDTH), row): ? ? ? ? ? ? if color is not None: ? ? ? ? ? ? ? ? pygame.draw.rect(screen, color, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(j * GRID_WIDTH, i * GRID_WIDTH, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GRID_WIDTH, GRID_WIDTH)) ? ? ? ? ? ? ? ? pygame.draw.rect(screen, WHITE, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(j * GRID_WIDTH, i * GRID_WIDTH, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GRID_WIDTH, GRID_WIDTH), 2) def draw_score(): ? ? show_text(screen, u'得分:{}'.format(score), 20, WIDTH + SIDE_WIDTH // 2, 100) def remove_full_line(): ? ? global screen_color_matrix ? ? global score ? ? global level ? ? new_matrix = [[None] * GRID_NUM_WIDTH for i in range(GRID_NUM_HEIGHT)] ? ? index = GRID_NUM_HEIGHT - 1 ? ? n_full_line = 0 ? ? for i in range(GRID_NUM_HEIGHT - 1, -1, -1): ? ? ? ? is_full = True ? ? ? ? for j in range(GRID_NUM_WIDTH): ? ? ? ? ? ? if screen_color_matrix[i][j] is None: ? ? ? ? ? ? ? ? is_full = False ? ? ? ? ? ? ? ? continue ? ? ? ? if not is_full: ? ? ? ? ? ? new_matrix[index] = screen_color_matrix[i] ? ? ? ? ? ? index -= 1 ? ? ? ? else: ? ? ? ? ? ? n_full_line += 1 ? ? score += n_full_line ? ? level = score // 20 + 1 ? ? screen_color_matrix = new_matrix def show_welcome(screen): ? ? show_text(screen, u'俄羅斯方塊', 30, WIDTH / 2, HEIGHT / 2) ? ? show_text(screen, u'按任意鍵開(kāi)始游戲', 20, WIDTH / 2, HEIGHT / 2 + 50) running = True gameover = True counter = 0 live_cube = None while running: ? ? clock.tick(FPS) ? ? for event in pygame.event.get(): ? ? ? ? if event.type == pygame.QUIT: ? ? ? ? ? ? running = False ? ? ? ? elif event.type == pygame.KEYDOWN: ? ? ? ? ? ? if gameover: ? ? ? ? ? ? ? ? gameover = False ? ? ? ? ? ? ? ? live_cube = CubeShape() ? ? ? ? ? ? ? ? break ? ? ? ? ? ? if event.key == pygame.K_LEFT: ? ? ? ? ? ? ? ? live_cube.left() ? ? ? ? ? ? elif event.key == pygame.K_RIGHT: ? ? ? ? ? ? ? ? live_cube.right() ? ? ? ? ? ? elif event.key == pygame.K_DOWN: ? ? ? ? ? ? ? ? live_cube.down() ? ? ? ? ? ? elif event.key == pygame.K_UP: ? ? ? ? ? ? ? ? live_cube.rotate() ? ? ? ? ? ? elif event.key == pygame.K_SPACE: ? ? ? ? ? ? ? ? while live_cube.down() == True: ? ? ? ? ? ? ? ? ? ? pass ? ? ? ? ? ? remove_full_line() ? ? # level 是為了方便游戲的難度,level 越高 FPS // level 的值越小 ? ? # 這樣屏幕刷新的就越快,難度就越大 ? ? if gameover is False and counter % (FPS // level) == 0: ? ? ? ? # down 表示下移骨牌,返回False表示下移不成功,可能超過(guò)了屏幕或者和之前固定的 ? ? ? ? # 小方塊沖突了 ? ? ? ? if live_cube.down() == False: ? ? ? ? ? ? for cube in live_cube.get_all_gridpos(): ? ? ? ? ? ? ? ? screen_color_matrix[cube[0]][cube[1]] = live_cube.color ? ? ? ? ? ? live_cube = CubeShape() ? ? ? ? ? ? if live_cube.conflict(live_cube.center): ? ? ? ? ? ? ? ? gameover = True ? ? ? ? ? ? ? ? score = 0 ? ? ? ? ? ? ? ? live_cube = None ? ? ? ? ? ? ? ? screen_color_matrix = [[None] * GRID_NUM_WIDTH for i in range(GRID_NUM_HEIGHT)] ? ? ? ? # 消除滿行 ? ? ? ? remove_full_line() ? ? counter += 1 ? ? # 更新屏幕 ? ? screen.fill(BLACK) ? ? draw_grids() ? ? draw_matrix() ? ? draw_score() ? ? if live_cube is not None: ? ? ? ? live_cube.draw() ? ? if gameover: ? ? ? ? show_welcome(screen) ? ? pygame.display.update()
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 用Python編寫(xiě)一個(gè)簡(jiǎn)單的俄羅斯方塊游戲的教程
- python實(shí)現(xiàn)俄羅斯方塊游戲
- python實(shí)現(xiàn)簡(jiǎn)單俄羅斯方塊
- python實(shí)現(xiàn)俄羅斯方塊
- python和pygame實(shí)現(xiàn)簡(jiǎn)單俄羅斯方塊游戲
- python實(shí)現(xiàn)俄羅斯方塊小游戲
- python實(shí)現(xiàn)俄羅斯方塊游戲(改進(jìn)版)
- python編寫(xiě)俄羅斯方塊
- Python實(shí)現(xiàn)簡(jiǎn)單的俄羅斯方塊游戲
- 利用python制作俄羅斯方塊詳細(xì)圖文教程
相關(guān)文章
最新Python?APScheduler?定時(shí)任務(wù)詳解
這篇文章主要介紹了Python使用apscheduler模塊設(shè)置定時(shí)任務(wù),APScheduler全稱Advanced?Python?Scheduler?作用為在指定的時(shí)間規(guī)則執(zhí)行指定的作業(yè),本文對(duì)Python?APScheduler?定時(shí)任務(wù)相關(guān)知識(shí)介紹的非常詳細(xì),需要的朋友參考下2022-05-05PyTorch之nn.ReLU與F.ReLU的區(qū)別介紹
這篇文章主要介紹了PyTorch之nn.ReLU與F.ReLU的區(qū)別介紹,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-06-06Python3.5內(nèi)置模塊之random模塊用法實(shí)例分析
這篇文章主要介紹了Python3.5內(nèi)置模塊之random模塊用法,結(jié)合實(shí)例形式分析了Python3.5 random模塊生成隨機(jī)數(shù)與隨機(jī)字符串相關(guān)操作技巧,需要的朋友可以參考下2019-04-04Visual Studio code 配置Python開(kāi)發(fā)環(huán)境
這篇文章主要介紹了Visual Studio code 配置Python開(kāi)發(fā)環(huán)境,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09