日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > python >内容正文

python

python 数据逆时针旋转270度_Python自动耍俄罗斯方块

發(fā)布時(shí)間:2025/3/20 python 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python 数据逆时针旋转270度_Python自动耍俄罗斯方块 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

小笨聰前面的文章總是用 Python 來(lái)進(jìn)行爬蟲(chóng),今天就換一下口味,體驗(yàn)一下 Python 自動(dòng)耍俄羅斯方塊。

小游戲 | Python自動(dòng)玩俄羅斯方塊?mp.weixin.qq.com

俄羅斯方塊(Tetris) 規(guī)則:由小方塊組成的不同形狀的板塊陸續(xù)從屏幕上方落下來(lái),玩家通過(guò)調(diào)整板塊的位置和方向,使它們?cè)谄聊坏撞科闯鐾暾囊粭l或幾條。這些完整的橫條會(huì)隨即消失,給新落下來(lái)的板塊騰出空間,與此同時(shí),玩家得到分?jǐn)?shù)獎(jiǎng)勵(lì)。沒(méi)有被消除掉的方塊不斷堆積起來(lái),一旦堆到屏幕頂端,玩家便告輸,游戲結(jié)束。(來(lái)自百度百科)

俄羅斯方塊游戲界面

我們此次的任務(wù)就是在這條規(guī)則的基礎(chǔ)上,利用 Python 和簡(jiǎn)單的 AI 算法,實(shí)現(xiàn)自動(dòng)尋找最優(yōu)位置和調(diào)整方塊形態(tài),達(dá)到快速高效得分的目的。(最終效果見(jiàn)文末視頻)

代碼分三部分:

  • utils.py:基礎(chǔ)設(shè)置和界面設(shè)計(jì)
  • ai.py:AI算法和具體方式
  • AITetris.py:實(shí)現(xiàn)游戲主循環(huán)
  • 一.基礎(chǔ)設(shè)置和界面設(shè)計(jì)

    1.定義一個(gè)俄羅斯方塊

    方塊共有7種形狀,每塊包含四個(gè)人小方塊,分別寫(xiě)出小方塊的相對(duì)坐標(biāo)、定義獲取小方塊旋轉(zhuǎn)角度、絕對(duì)坐標(biāo)和相對(duì)坐標(biāo)邊界的函數(shù)。

    1class tetrisShape():2 def __init__(self, shape=0):3 # 空塊4 self.shape_empty = 05 # 一字型塊6 self.shape_I = 17 # L型塊8 self.shape_L = 29 # 向左的L型塊 10 self.shape_J = 3 11 # T型塊 12 self.shape_T = 4 13 # 田字型塊 14 self.shape_O = 5 15 # 反向Z型塊 16 self.shape_S = 6 17 # Z型塊 18 self.shape_Z = 7 19 # 每種塊包含的四個(gè)小方塊相對(duì)坐標(biāo)分布 20 self.shapes_relative_coords = [ 21 [[0, 0], [0, 0], [0, 0], [0, 0]], 22 [[0, -1], [0, 0], [0, 1], [0, 2]], 23 [[0, -1], [0, 0], [0, 1], [1, 1]], 24 [[0, -1], [0, 0], [0, 1], [-1, 1]], 25 [[0, -1], [0, 0], [0, 1], [1, 0]], 26 [[0, 0], [0, -1], [1, 0], [1, -1]], 27 [[0, 0], [0, -1], [-1, 0], [1, -1]], 28 [[0, 0], [0, -1], [1, 0], [-1, -1]] 29 ] 30 self.shape = shape 31 self.relative_coords = self.shapes_relative_coords[self.shape] 32 '''獲得該形狀當(dāng)前旋轉(zhuǎn)狀態(tài)的四個(gè)小方塊的相對(duì)坐標(biāo)分布''' 33 def getRotatedRelativeCoords(self, direction): 34 # 初始分布 35 if direction == 0 or self.shape == self.shape_O: 36 return self.relative_coords 37 # 逆時(shí)針旋轉(zhuǎn)90度 38 if direction == 1: 39 return [[-y, x] for x, y in self.relative_coords] 40 # 逆時(shí)針旋轉(zhuǎn)180度 41 if direction == 2: 42 if self.shape in [self.shape_I, self.shape_Z, self.shape_S]: 43 return self.relative_coords 44 else: 45 return [[-x, -y] for x, y in self.relative_coords] 46 # 逆時(shí)針旋轉(zhuǎn)270度 47 if direction == 3: 48 if self.shape in [self.shape_I, self.shape_Z, self.shape_S]: 49 return [[-y, x] for x, y in self.relative_coords] 50 else: 51 return [[y, -x] for x, y in self.relative_coords]

    2.內(nèi)部板塊

    游戲主界面分為內(nèi)部版塊和外部板塊,將游戲進(jìn)行中的數(shù)據(jù)記錄與數(shù)據(jù)處理部分定義在內(nèi)部板塊類中,將游戲數(shù)據(jù)可視化定義在外部板塊類中。在內(nèi)部版塊類中,我們可以操作方塊向左、向右、順時(shí)針、逆時(shí)針、向下和墜落等運(yùn)動(dòng)。

    在方塊移動(dòng)時(shí),也要實(shí)時(shí)判斷方塊是否越界或落地并及時(shí)處理,如果落地則將方塊合并并整行消除,再創(chuàng)建新的方塊,以此循環(huán)。

    1class InnerBoard():2 def __init__(self, width=10, height=22):3 # 寬和長(zhǎng), 單位長(zhǎng)度為小方塊邊長(zhǎng)4 self.width = width5 self.height = height6 self.reset()7 '''判斷當(dāng)前俄羅斯方塊是否可以移動(dòng)到某位置'''8 def ableMove(self, coord, direction=None):9 assert len(coord) == 2 10 if direction is None: 11 direction = self.current_direction 12 for x, y in self.current_tetris.getAbsoluteCoords(direction, coord[0], coord[1]): 13 # 超出邊界 14 if x >= self.width or x < 0 or y >= self.height or y < 0: 15 return False 16 # 該位置有俄羅斯方塊了 17 if self.getCoordValue([x, y]) > 0: 18 return False 19 return True 20 '''向右移動(dòng)''' 21 def moveRight(self): 22 if self.ableMove([self.current_coord[0]+1, self.current_coord[1]]): 23 self.current_coord[0] += 1 24 '''向左移動(dòng)''' 25 def moveLeft(self): 26 if self.ableMove([self.current_coord[0]-1, self.current_coord[1]]): 27 self.current_coord[0] -= 1 28 '''順時(shí)針轉(zhuǎn)''' 29 def rotateClockwise(self): 30 if self.ableMove(self.current_coord, (self.current_direction-1) % 4): 31 self.current_direction = (self.current_direction-1) % 4 32 '''逆時(shí)針轉(zhuǎn)''' 33 def rotateAnticlockwise(self): 34 if self.ableMove(self.current_coord, (self.current_direction+1) % 4): 35 self.current_direction = (self.current_direction+1) % 4 36 '''向下移動(dòng)''' 37 def moveDown(self): 38 removed_lines = 0 39 if self.ableMove([self.current_coord[0], self.current_coord[1]+1]): 40 self.current_coord[1] += 1 41 else: 42 x_min, x_max, y_min, y_max = self.current_tetris.getRelativeBoundary(self.current_direction) 43 # 簡(jiǎn)單起見(jiàn), 有超出屏幕就判定游戲結(jié)束 44 if self.current_coord[1] + y_min < 0: 45 self.is_gameover = True 46 return removed_lines 47 self.mergeTetris() 48 removed_lines = self.removeFullLines() 49 self.createNewTetris() 50 return removed_lines

    3.外部板塊和側(cè)面板

    1class ExternalBoard(QFrame):2 score_signal = pyqtSignal(str)3 def __init__(self, parent, grid_size, inner_board):4 super().__init__(parent)5 self.grid_size = grid_size6 self.inner_board = inner_board7 self.setFixedSize(grid_size * inner_board.width, grid_size * inner_board.height)8 self.initExternalBoard()9 '''外部板塊初始化''' 10 def initExternalBoard(self): 11 self.score = 0 12 '''把內(nèi)部板塊結(jié)構(gòu)畫(huà)出來(lái)''' 13 def paintEvent(self, event): 14 painter = QPainter(self) 15 for x in range(self.inner_board.width): 16 for y in range(self.inner_board.height): 17 shape = self.inner_board.getCoordValue([x, y]) 18 drawCell(painter, x * self.grid_size, y * self.grid_size, shape, self.grid_size) 19 for x, y in self.inner_board.getCurrentTetrisCoords(): 20 shape = self.inner_board.current_tetris.shape 21 drawCell(painter, x * self.grid_size, y * self.grid_size, shape, self.grid_size) 22 painter.setPen(QColor(0x777777)) 23 painter.drawLine(0, self.height()-1, self.width(), self.height()-1) 24 painter.drawLine(self.width()-1, 0, self.width()-1, self.height()) 25 painter.setPen(QColor(0xCCCCCC)) 26 painter.drawLine(self.width(), 0, self.width(), self.height()) 27 painter.drawLine(0, self.height(), self.width(), self.height()) 28 '''數(shù)據(jù)更新''' 29 def updateData(self): 30 self.score_signal.emit(str(self.score)) 31 self.update() 32 33 34 ''' 35 側(cè)面板, 右邊顯示下一個(gè)俄羅斯方塊的形狀 36 ''' 37class SidePanel(QFrame): 38 def __init__(self, parent, grid_size, inner_board): 39 super().__init__(parent) 40 self.grid_size = grid_size 41 self.inner_board = inner_board 42 self.setFixedSize(grid_size * 5, grid_size * inner_board.height) 43 self.move(grid_size * inner_board.width, 0) 44 '''畫(huà)側(cè)面板''' 45 def paintEvent(self, event): 46 painter = QPainter(self) 47 x_min, x_max, y_min, y_max = self.inner_board.next_tetris.getRelativeBoundary(0) 48 dy = 3 * self.grid_size 49 dx = (self.width() - (x_max - x_min) * self.grid_size) / 2 50 shape = self.inner_board.next_tetris.shape 51 for x, y in self.inner_board.next_tetris.getAbsoluteCoords(0, 0, -y_min): 52 drawCell(painter, x * self.grid_size + dx, y * self.grid_size + dy, shape, self.grid_size) 53 '''更新數(shù)據(jù)''' 54 def updateData(self): 55 self.update()

    二、AI算法和具體方式

    此處AI 算法基本思想就是,遍歷當(dāng)前可操作的俄羅斯方塊和下一個(gè)可操作的俄羅斯方塊(根據(jù)不同的策略,即選擇不同的位置和旋轉(zhuǎn)角度)下落到底部后組成的所有可能的未來(lái)場(chǎng)景,從這些未來(lái)場(chǎng)景中選擇一個(gè)最優(yōu)的,其對(duì)應(yīng)的當(dāng)前可操作的俄羅斯方塊的行動(dòng)策略即為當(dāng)前解,具體的代碼實(shí)現(xiàn)如下:

    1# 簡(jiǎn)單的AI算法2for d_now in current_direction_range:3 x_now_min, x_now_max, y_now_min, y_now_max = self.inner_board.current_tetris.getRelativeBoundary(d_now)4 for x_now in range(-x_now_min, self.inner_board.width - x_now_max):5 board = self.getFinalBoardData(d_now, x_now)6 for d_next in next_direction_range:7 x_next_min, x_next_max, y_next_min, y_next_max = self.inner_board.next_tetris.getRelativeBoundary(d_next)8 distances = self.getDropDistances(board, d_next, range(-x_next_min, self.inner_board.width-x_next_max))9 for x_next in range(-x_next_min, self.inner_board.width-x_next_max): 10 score = self.calcScore(copy.deepcopy(board), d_next, x_next, distances) 11 if not action or action[2] < score: 12 action = [d_now, x_now, score] 13return action

    未來(lái)場(chǎng)景優(yōu)劣評(píng)定考慮的因素有:

    1)可消除的行數(shù);

    2)堆積后的俄羅斯方塊內(nèi)的虛洞數(shù)量;

    3)堆積后的俄羅斯方塊內(nèi)的小方塊數(shù)量;

    4)堆積后的俄羅斯方塊的最高點(diǎn);

    5)堆積后的俄羅斯方塊的高度(每一列都有一個(gè)高度)標(biāo)準(zhǔn)差;

    6)堆積后的俄羅斯方塊的高度一階前向差分;

    7)堆積后的俄羅斯方塊的高度一階前向差分的標(biāo)準(zhǔn)差;

    9)堆積后的俄羅斯方塊的最高點(diǎn)和最低點(diǎn)之差。

    代碼實(shí)現(xiàn)如下:

    1 # 下個(gè)俄羅斯方塊以某種方式模擬到達(dá)底部2 board = self.imitateDropDown(board, self.inner_board.next_tetris, d_next, x_next, distances[x_next])3 width, height = self.inner_board.width, self.inner_board.height4 # 下一個(gè)俄羅斯方塊以某方案行動(dòng)到達(dá)底部后的得分(可消除的行數(shù))5 removed_lines = 06# 空位統(tǒng)計(jì)7 hole_statistic_0 = [0] * width8 hole_statistic_1 = [0] * width9 # 方塊數(shù)量 10 num_blocks = 0 11 # 空位數(shù)量 12 num_holes = 0 13 # 每個(gè)x位置堆積俄羅斯方塊的最高點(diǎn) 14 roof_y = [0] * width 15 for y in range(height-1, -1, -1): 16 # 是否有空位 17 has_hole = False 18 # 是否有方塊 19 has_block = False 20 for x in range(width): 21 if board[x + y * width] == tetrisShape().shape_empty: 22 has_hole = True 23 hole_statistic_0[x] += 1 24 else: 25 has_block = True 26 roof_y[x] = height - y 27 if hole_statistic_0[x] > 0: 28 hole_statistic_1[x] += hole_statistic_0[x] 29 hole_statistic_0[x] = 0 30 if hole_statistic_1[x] > 0: 31 num_blocks += 1 32 if not has_block: 33 break 34 if not has_hole and has_block: 35 removed_lines += 1 36 ......

    三、實(shí)現(xiàn)游戲主循環(huán)

    定義俄羅斯方塊游戲類初始化(包括塊大小、下落速度、水平布局、AI控制等),并含有開(kāi)始、暫停、界面更新等事件。

    1class TetrisGame(QMainWindow):2 def __init__(self):3 super().__init__()4 # 是否暫停ing5 self.is_paused = False6 # 是否開(kāi)始ing7 self.is_started = False8 self.initUI()9 '''界面初始化''' 10 def initUI(self): 11 # 塊大小 12 self.grid_size = 22 13 # 游戲幀率 14 self.fps = 100 15 self.timer = QBasicTimer() 16 # 水平布局 17 layout_horizontal = QHBoxLayout() 18 self.inner_board = InnerBoard() 19 self.external_board = ExternalBoard(self, self.grid_size, self.inner_board) 20 21 . 22 . 23 . 24 25 '''按鍵事件''' 26 def keyPressEvent(self, event): 27 if not self.is_started or self.inner_board.current_tetris == tetrisShape().shape_empty: 28 super(TetrisGame, self).keyPressEvent(event) 29 return 30 key = event.key() 31 # P鍵暫停 32 if key == Qt.Key_P: 33 self.pause() 34 return 35 if self.is_paused: 36 return 37 else: 38 super(TetrisGame, self).keyPressEvent(event) 39 self.updateWindow() 40 41 42if __name__ == '__main__': 43 app = QApplication([])

    最終效果視頻展示

    Python自動(dòng)耍俄羅斯方塊https://www.zhihu.com/video/1158808534270595072

    以上就是本次Python自動(dòng)耍俄羅斯方塊的過(guò)程,微信公眾號(hào)“學(xué)編程的金融客”后臺(tái)回復(fù)“ 俄羅斯方塊 ”即可獲取源碼?!就辍?/p>小游戲 | Python自動(dòng)玩俄羅斯方塊?mp.weixin.qq.com

    往期推薦

    1.爬取流浪地球影評(píng)

    2.爬取《明日之子》評(píng)論和彈幕

    3.北上廣深租房圖鑒

    4.爬取抖音視頻

    5.母親節(jié)祝福代碼

    你的點(diǎn)贊和關(guān)注就是對(duì)我最大的支持!

    保存掃碼關(guān)注公眾號(hào)唄

    總結(jié)

    以上是生活随笔為你收集整理的python 数据逆时针旋转270度_Python自动耍俄罗斯方块的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。