python反編譯教程之2048小游戲?qū)嵗?/h1>
更新時間:2021年03月03日 09:57:52 作者:meteor_yh
這篇文章主要給大家介紹了關于python反編譯教程之2048小游戲的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
一.背景
一道ctf題,通過破解2048游戲獲得flag
游戲的規(guī)則很簡單,需要控制所有方塊向同一個方向運動,兩個相同數(shù)字方塊撞在一起之后合并成為他們的和,每次操作之后會隨機生成一個2或者4,最終得到一個“2048”的方塊就算勝利了。


二.工具準備
1.pyinstxtractor.py腳本用于反編譯python
腳本內(nèi)容如下
from __future__ import print_function
import os
import struct
import marshal
import zlib
import sys
import imp
import types
from uuid import uuid4 as uniquename
class CTOCEntry:
def __init__(self, position, cmprsdDataSize, uncmprsdDataSize, cmprsFlag, typeCmprsData, name):
self.position = position
self.cmprsdDataSize = cmprsdDataSize
self.uncmprsdDataSize = uncmprsdDataSize
self.cmprsFlag = cmprsFlag
self.typeCmprsData = typeCmprsData
self.name = name
class PyInstArchive:
PYINST20_COOKIE_SIZE = 24 # For pyinstaller 2.0
PYINST21_COOKIE_SIZE = 24 + 64 # For pyinstaller 2.1+
MAGIC = b'MEI\014\013\012\013\016' # Magic number which identifies pyinstaller
def __init__(self, path):
self.filePath = path
def open(self):
try:
self.fPtr = open(self.filePath, 'rb')
self.fileSize = os.stat(self.filePath).st_size
except:
print('[*] Error: Could not open {0}'.format(self.filePath))
return False
return True
def close(self):
try:
self.fPtr.close()
except:
pass
def checkFile(self):
print('[*] Processing {0}'.format(self.filePath))
# Check if it is a 2.0 archive
self.fPtr.seek(self.fileSize - self.PYINST20_COOKIE_SIZE, os.SEEK_SET)
magicFromFile = self.fPtr.read(len(self.MAGIC))
if magicFromFile == self.MAGIC:
self.pyinstVer = 20 # pyinstaller 2.0
print('[*] Pyinstaller version: 2.0')
return True
# Check for pyinstaller 2.1+ before bailing out
self.fPtr.seek(self.fileSize - self.PYINST21_COOKIE_SIZE, os.SEEK_SET)
magicFromFile = self.fPtr.read(len(self.MAGIC))
if magicFromFile == self.MAGIC:
print('[*] Pyinstaller version: 2.1+')
self.pyinstVer = 21 # pyinstaller 2.1+
return True
print('[*] Error : Unsupported pyinstaller version or not a pyinstaller archive')
return False
def getCArchiveInfo(self):
try:
if self.pyinstVer == 20:
self.fPtr.seek(self.fileSize - self.PYINST20_COOKIE_SIZE, os.SEEK_SET)
# Read CArchive cookie
(magic, lengthofPackage, toc, tocLen, self.pyver) = \
struct.unpack('!8siiii', self.fPtr.read(self.PYINST20_COOKIE_SIZE))
elif self.pyinstVer == 21:
self.fPtr.seek(self.fileSize - self.PYINST21_COOKIE_SIZE, os.SEEK_SET)
# Read CArchive cookie
(magic, lengthofPackage, toc, tocLen, self.pyver, pylibname) = \
struct.unpack('!8siiii64s', self.fPtr.read(self.PYINST21_COOKIE_SIZE))
except:
print('[*] Error : The file is not a pyinstaller archive')
return False
print('[*] Python version: {0}'.format(self.pyver))
# Overlay is the data appended at the end of the PE
self.overlaySize = lengthofPackage
self.overlayPos = self.fileSize - self.overlaySize
self.tableOfContentsPos = self.overlayPos + toc
self.tableOfContentsSize = tocLen
print('[*] Length of package: {0} bytes'.format(self.overlaySize))
return True
def parseTOC(self):
# Go to the table of contents
self.fPtr.seek(self.tableOfContentsPos, os.SEEK_SET)
self.tocList = []
parsedLen = 0
# Parse table of contents
while parsedLen < self.tableOfContentsSize:
(entrySize, ) = struct.unpack('!i', self.fPtr.read(4))
nameLen = struct.calcsize('!iiiiBc')
(entryPos, cmprsdDataSize, uncmprsdDataSize, cmprsFlag, typeCmprsData, name) = \
struct.unpack( \
'!iiiBc{0}s'.format(entrySize - nameLen), \
self.fPtr.read(entrySize - 4))
name = name.decode('utf-8').rstrip('\0')
if len(name) == 0:
name = str(uniquename())
print('[!] Warning: Found an unamed file in CArchive. Using random name {0}'.format(name))
self.tocList.append( \
CTOCEntry( \
self.overlayPos + entryPos, \
cmprsdDataSize, \
uncmprsdDataSize, \
cmprsFlag, \
typeCmprsData, \
name \
))
parsedLen += entrySize
print('[*] Found {0} files in CArchive'.format(len(self.tocList)))
def extractFiles(self):
print('[*] Beginning extraction...please standby')
extractionDir = os.path.join(os.getcwd(), os.path.basename(self.filePath) + '_extracted')
if not os.path.exists(extractionDir):
os.mkdir(extractionDir)
os.chdir(extractionDir)
for entry in self.tocList:
basePath = os.path.dirname(entry.name)
if basePath != '':
# Check if path exists, create if not
if not os.path.exists(basePath):
os.makedirs(basePath)
self.fPtr.seek(entry.position, os.SEEK_SET)
data = self.fPtr.read(entry.cmprsdDataSize)
if entry.cmprsFlag == 1:
data = zlib.decompress(data)
# Malware may tamper with the uncompressed size
# Comment out the assertion in such a case
assert len(data) == entry.uncmprsdDataSize # Sanity Check
with open(entry.name, 'wb') as f:
f.write(data)
if entry.typeCmprsData == b's':
print('[+] Possible entry point: {0}'.format(entry.name))
elif entry.typeCmprsData == b'z' or entry.typeCmprsData == b'Z':
self._extractPyz(entry.name)
def _extractPyz(self, name):
dirName = name + '_extracted'
# Create a directory for the contents of the pyz
if not os.path.exists(dirName):
os.mkdir(dirName)
with open(name, 'rb') as f:
pyzMagic = f.read(4)
assert pyzMagic == b'PYZ\0' # Sanity Check
pycHeader = f.read(4) # Python magic value
if imp.get_magic() != pycHeader:
print('[!] Warning: The script is running in a different python version than the one used to build the executable')
print(' Run this script in Python{0} to prevent extraction errors(if any) during unmarshalling'.format(self.pyver))
(tocPosition, ) = struct.unpack('!i', f.read(4))
f.seek(tocPosition, os.SEEK_SET)
try:
toc = marshal.load(f)
except:
print('[!] Unmarshalling FAILED. Cannot extract {0}. Extracting remaining files.'.format(name))
return
print('[*] Found {0} files in PYZ archive'.format(len(toc)))
# From pyinstaller 3.1+ toc is a list of tuples
if type(toc) == list:
toc = dict(toc)
for key in toc.keys():
(ispkg, pos, length) = toc[key]
f.seek(pos, os.SEEK_SET)
fileName = key
try:
# for Python > 3.3 some keys are bytes object some are str object
fileName = key.decode('utf-8')
except:
pass
# Make sure destination directory exists, ensuring we keep inside dirName
destName = os.path.join(dirName, fileName.replace("..", "__"))
destDirName = os.path.dirname(destName)
if not os.path.exists(destDirName):
os.makedirs(destDirName)
try:
data = f.read(length)
data = zlib.decompress(data)
except:
print('[!] Error: Failed to decompress {0}, probably encrypted. Extracting as is.'.format(fileName))
open(destName + '.pyc.encrypted', 'wb').write(data)
continue
with open(destName + '.pyc', 'wb') as pycFile:
pycFile.write(pycHeader) # Write pyc magic
pycFile.write(b'\0' * 4) # Write timestamp
if self.pyver >= 33:
pycFile.write(b'\0' * 4) # Size parameter added in Python 3.3
pycFile.write(data)
def main():
if len(sys.argv) < 2:
print('[*] Usage: pyinstxtractor.py <filename>')
else:
arch = PyInstArchive(sys.argv[1])
if arch.open():
if arch.checkFile():
if arch.getCArchiveInfo():
arch.parseTOC()
arch.extractFiles()
arch.close()
print('[*] Successfully extracted pyinstaller archive: {0}'.format(sys.argv[1]))
print('')
print('You can now use a python decompiler on the pyc files within the extracted directory')
return
arch.close()
if __name__ == '__main__':
main()
2.winhex用于編輯16進制的軟件
壓縮包已上傳至博主資源,下載地址:https://blog.csdn.net/qq_50216270?type=download
三.反編譯
1.放置腳本
將腳本和待編譯的exe文件放在同一路徑下后,在路徑框中輸入cmd打開終端

2.運行腳本
在終端中輸入python后輸入腳本名和待反編譯exe文件名

編譯成功后會在原路徑生成如下文件夾

3.找到軟件名文件和struct文件

4.托入winhex進行對比


5.將struct多出的那一行復制到puzzle前面

6.更改其后綴為.pyc

7.安裝第三方庫uncompyle

8.python版本為3.8以下可以調(diào)用uncompyle
對應路徑終端輸入uncompyle6 puzzle.pyc > puzzle.py
9.python版本為3.8以上可以選擇在線工具(.pyc>.py)
10.最后可以得到puzzle.py文件
代碼如下
#!/usr/bin/env python
# visit http://tool.lu/pyc/ for more information
import random
from tkinter import Frame, Label, CENTER
import logic
import constants as c
class GameGrid(Frame):
def __init__(self):
Frame.__init__(self)
self.grid()
self.master.title('C1CTF2019')
self.master.bind('<Key>', self.key_down)
self.commands = {
c.KEY_J: logic.down,
c.KEY_K: logic.up,
c.KEY_L: logic.right,
c.KEY_H: logic.left,
c.KEY_RIGHT_ALT: logic.right,
c.KEY_LEFT_ALT: logic.left,
c.KEY_DOWN_ALT: logic.down,
c.KEY_UP_ALT: logic.up,
c.KEY_RIGHT: logic.right,
c.KEY_LEFT: logic.left,
c.KEY_DOWN: logic.down,
c.KEY_UP: logic.up }
self.grid_cells = []
self.init_grid()
self.init_matrix()
self.update_grid_cells()
self.mainloop()
def init_grid(self):
background = Frame(self, c.BACKGROUND_COLOR_GAME, c.SIZE, c.SIZE, **('bg', 'width', 'height'))
background.grid()
for i in range(c.GRID_LEN):
grid_row = []
for j in range(c.GRID_LEN):
cell = Frame(background, c.BACKGROUND_COLOR_CELL_EMPTY, c.SIZE / c.GRID_LEN, c.SIZE / c.GRID_LEN, **('bg', 'width', 'height'))
cell.grid(i, j, c.GRID_PADDING, c.GRID_PADDING, **('row', 'column', 'padx', 'pady'))
t = Label(cell, '', c.BACKGROUND_COLOR_CELL_EMPTY, CENTER, c.FONT, 5, 2, **('master', 'text', 'bg', 'justify', 'font', 'width', 'height'))
t.grid()
grid_row.append(t)
self.grid_cells.append(grid_row)
def gen(self):
return random.randint(0, c.GRID_LEN - 1)
def init_matrix(self):
self.matrix = logic.new_game(4)
self.history_matrixs = list()
self.matrix = logic.add_two(self.matrix)
self.matrix = logic.add_two(self.matrix)
def update_grid_cells(self):
for i in range(c.GRID_LEN):
for j in range(c.GRID_LEN):
new_number = self.matrix[i][j]
if new_number == 0:
self.grid_cells[i][j].configure('', c.BACKGROUND_COLOR_CELL_EMPTY, **('text', 'bg'))
continue
self.grid_cells[i][j].configure(str(new_number), c.BACKGROUND_COLOR_DICT[new_number], c.CELL_COLOR_DICT[new_number], **('text', 'bg', 'fg'))
self.update_idletasks()
def key_down(self, event):
key = repr(event.char)
if key == c.KEY_BACK and len(self.history_matrixs) > 1:
self.matrix = self.history_matrixs.pop()
self.update_grid_cells()
print('back on step total step:', len(self.history_matrixs))
elif key in self.commands:
(self.matrix, done) = self.commands[repr(event.char)](self.matrix)
if done:
self.matrix = logic.add_two(self.matrix)
self.history_matrixs.append(self.matrix)
self.update_grid_cells()
done = False
if logic.game_state(self.matrix) == 'win':
self.grid_cells[1][0].configure('C1CTF', c.BACKGROUND_COLOR_CELL_EMPTY, **('text', 'bg'))
self.grid_cells[1][1].configure('{2048', c.BACKGROUND_COLOR_CELL_EMPTY, **('text', 'bg'))
self.grid_cells[1][2].configure('_1s_', c.BACKGROUND_COLOR_CELL_EMPTY, **('text', 'bg'))
self.grid_cells[1][3].configure('fun}', c.BACKGROUND_COLOR_CELL_EMPTY, **('text', 'bg'))
if logic.game_state(self.matrix) == 'lose':
self.grid_cells[1][1].configure('You', c.BACKGROUND_COLOR_CELL_EMPTY, **('text', 'bg'))
self.grid_cells[1][2].configure('Lost!', c.BACKGROUND_COLOR_CELL_EMPTY, **('text', 'bg'))
def generate_next(self):
index = (self.gen(), self.gen())
while self.matrix[index[0]][index[1]] != 0:
index = (self.gen(), self.gen())
self.matrix[index[0]][index[1]] = 2
gamegrid = GameGrid()
11.找到flag大公告成

總結
到此這篇關于python反編譯教程之2048小游戲?qū)嵗奈恼戮徒榻B到這了,更多相關python反編譯2048小游戲內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
-
Python基于釘釘監(jiān)控發(fā)送消息提醒的實現(xiàn)
本文主要介紹了Python基于釘釘監(jiān)控發(fā)送消息提醒的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
2022-06-06
-
python 3調(diào)用百度OCR API實現(xiàn)剪貼板文字識別
這篇文章主要為大家詳細介紹了python 3調(diào)用百度OCR API實現(xiàn)剪貼板文字識別,具有一定的參考價值,感興趣的小伙伴們可以參考一下 2018-09-09
最新評論
一.背景
一道ctf題,通過破解2048游戲獲得flag
游戲的規(guī)則很簡單,需要控制所有方塊向同一個方向運動,兩個相同數(shù)字方塊撞在一起之后合并成為他們的和,每次操作之后會隨機生成一個2或者4,最終得到一個“2048”的方塊就算勝利了。
二.工具準備
1.pyinstxtractor.py腳本用于反編譯python
腳本內(nèi)容如下
from __future__ import print_function import os import struct import marshal import zlib import sys import imp import types from uuid import uuid4 as uniquename class CTOCEntry: def __init__(self, position, cmprsdDataSize, uncmprsdDataSize, cmprsFlag, typeCmprsData, name): self.position = position self.cmprsdDataSize = cmprsdDataSize self.uncmprsdDataSize = uncmprsdDataSize self.cmprsFlag = cmprsFlag self.typeCmprsData = typeCmprsData self.name = name class PyInstArchive: PYINST20_COOKIE_SIZE = 24 # For pyinstaller 2.0 PYINST21_COOKIE_SIZE = 24 + 64 # For pyinstaller 2.1+ MAGIC = b'MEI\014\013\012\013\016' # Magic number which identifies pyinstaller def __init__(self, path): self.filePath = path def open(self): try: self.fPtr = open(self.filePath, 'rb') self.fileSize = os.stat(self.filePath).st_size except: print('[*] Error: Could not open {0}'.format(self.filePath)) return False return True def close(self): try: self.fPtr.close() except: pass def checkFile(self): print('[*] Processing {0}'.format(self.filePath)) # Check if it is a 2.0 archive self.fPtr.seek(self.fileSize - self.PYINST20_COOKIE_SIZE, os.SEEK_SET) magicFromFile = self.fPtr.read(len(self.MAGIC)) if magicFromFile == self.MAGIC: self.pyinstVer = 20 # pyinstaller 2.0 print('[*] Pyinstaller version: 2.0') return True # Check for pyinstaller 2.1+ before bailing out self.fPtr.seek(self.fileSize - self.PYINST21_COOKIE_SIZE, os.SEEK_SET) magicFromFile = self.fPtr.read(len(self.MAGIC)) if magicFromFile == self.MAGIC: print('[*] Pyinstaller version: 2.1+') self.pyinstVer = 21 # pyinstaller 2.1+ return True print('[*] Error : Unsupported pyinstaller version or not a pyinstaller archive') return False def getCArchiveInfo(self): try: if self.pyinstVer == 20: self.fPtr.seek(self.fileSize - self.PYINST20_COOKIE_SIZE, os.SEEK_SET) # Read CArchive cookie (magic, lengthofPackage, toc, tocLen, self.pyver) = \ struct.unpack('!8siiii', self.fPtr.read(self.PYINST20_COOKIE_SIZE)) elif self.pyinstVer == 21: self.fPtr.seek(self.fileSize - self.PYINST21_COOKIE_SIZE, os.SEEK_SET) # Read CArchive cookie (magic, lengthofPackage, toc, tocLen, self.pyver, pylibname) = \ struct.unpack('!8siiii64s', self.fPtr.read(self.PYINST21_COOKIE_SIZE)) except: print('[*] Error : The file is not a pyinstaller archive') return False print('[*] Python version: {0}'.format(self.pyver)) # Overlay is the data appended at the end of the PE self.overlaySize = lengthofPackage self.overlayPos = self.fileSize - self.overlaySize self.tableOfContentsPos = self.overlayPos + toc self.tableOfContentsSize = tocLen print('[*] Length of package: {0} bytes'.format(self.overlaySize)) return True def parseTOC(self): # Go to the table of contents self.fPtr.seek(self.tableOfContentsPos, os.SEEK_SET) self.tocList = [] parsedLen = 0 # Parse table of contents while parsedLen < self.tableOfContentsSize: (entrySize, ) = struct.unpack('!i', self.fPtr.read(4)) nameLen = struct.calcsize('!iiiiBc') (entryPos, cmprsdDataSize, uncmprsdDataSize, cmprsFlag, typeCmprsData, name) = \ struct.unpack( \ '!iiiBc{0}s'.format(entrySize - nameLen), \ self.fPtr.read(entrySize - 4)) name = name.decode('utf-8').rstrip('\0') if len(name) == 0: name = str(uniquename()) print('[!] Warning: Found an unamed file in CArchive. Using random name {0}'.format(name)) self.tocList.append( \ CTOCEntry( \ self.overlayPos + entryPos, \ cmprsdDataSize, \ uncmprsdDataSize, \ cmprsFlag, \ typeCmprsData, \ name \ )) parsedLen += entrySize print('[*] Found {0} files in CArchive'.format(len(self.tocList))) def extractFiles(self): print('[*] Beginning extraction...please standby') extractionDir = os.path.join(os.getcwd(), os.path.basename(self.filePath) + '_extracted') if not os.path.exists(extractionDir): os.mkdir(extractionDir) os.chdir(extractionDir) for entry in self.tocList: basePath = os.path.dirname(entry.name) if basePath != '': # Check if path exists, create if not if not os.path.exists(basePath): os.makedirs(basePath) self.fPtr.seek(entry.position, os.SEEK_SET) data = self.fPtr.read(entry.cmprsdDataSize) if entry.cmprsFlag == 1: data = zlib.decompress(data) # Malware may tamper with the uncompressed size # Comment out the assertion in such a case assert len(data) == entry.uncmprsdDataSize # Sanity Check with open(entry.name, 'wb') as f: f.write(data) if entry.typeCmprsData == b's': print('[+] Possible entry point: {0}'.format(entry.name)) elif entry.typeCmprsData == b'z' or entry.typeCmprsData == b'Z': self._extractPyz(entry.name) def _extractPyz(self, name): dirName = name + '_extracted' # Create a directory for the contents of the pyz if not os.path.exists(dirName): os.mkdir(dirName) with open(name, 'rb') as f: pyzMagic = f.read(4) assert pyzMagic == b'PYZ\0' # Sanity Check pycHeader = f.read(4) # Python magic value if imp.get_magic() != pycHeader: print('[!] Warning: The script is running in a different python version than the one used to build the executable') print(' Run this script in Python{0} to prevent extraction errors(if any) during unmarshalling'.format(self.pyver)) (tocPosition, ) = struct.unpack('!i', f.read(4)) f.seek(tocPosition, os.SEEK_SET) try: toc = marshal.load(f) except: print('[!] Unmarshalling FAILED. Cannot extract {0}. Extracting remaining files.'.format(name)) return print('[*] Found {0} files in PYZ archive'.format(len(toc))) # From pyinstaller 3.1+ toc is a list of tuples if type(toc) == list: toc = dict(toc) for key in toc.keys(): (ispkg, pos, length) = toc[key] f.seek(pos, os.SEEK_SET) fileName = key try: # for Python > 3.3 some keys are bytes object some are str object fileName = key.decode('utf-8') except: pass # Make sure destination directory exists, ensuring we keep inside dirName destName = os.path.join(dirName, fileName.replace("..", "__")) destDirName = os.path.dirname(destName) if not os.path.exists(destDirName): os.makedirs(destDirName) try: data = f.read(length) data = zlib.decompress(data) except: print('[!] Error: Failed to decompress {0}, probably encrypted. Extracting as is.'.format(fileName)) open(destName + '.pyc.encrypted', 'wb').write(data) continue with open(destName + '.pyc', 'wb') as pycFile: pycFile.write(pycHeader) # Write pyc magic pycFile.write(b'\0' * 4) # Write timestamp if self.pyver >= 33: pycFile.write(b'\0' * 4) # Size parameter added in Python 3.3 pycFile.write(data) def main(): if len(sys.argv) < 2: print('[*] Usage: pyinstxtractor.py <filename>') else: arch = PyInstArchive(sys.argv[1]) if arch.open(): if arch.checkFile(): if arch.getCArchiveInfo(): arch.parseTOC() arch.extractFiles() arch.close() print('[*] Successfully extracted pyinstaller archive: {0}'.format(sys.argv[1])) print('') print('You can now use a python decompiler on the pyc files within the extracted directory') return arch.close() if __name__ == '__main__': main()
2.winhex用于編輯16進制的軟件
壓縮包已上傳至博主資源,下載地址:https://blog.csdn.net/qq_50216270?type=download
三.反編譯
1.放置腳本
將腳本和待編譯的exe文件放在同一路徑下后,在路徑框中輸入cmd打開終端
2.運行腳本
在終端中輸入python后輸入腳本名和待反編譯exe文件名
編譯成功后會在原路徑生成如下文件夾
3.找到軟件名文件和struct文件
4.托入winhex進行對比
5.將struct多出的那一行復制到puzzle前面
6.更改其后綴為.pyc
7.安裝第三方庫uncompyle
8.python版本為3.8以下可以調(diào)用uncompyle
對應路徑終端輸入uncompyle6 puzzle.pyc > puzzle.py
9.python版本為3.8以上可以選擇在線工具(.pyc>.py)
10.最后可以得到puzzle.py文件
代碼如下
#!/usr/bin/env python # visit http://tool.lu/pyc/ for more information import random from tkinter import Frame, Label, CENTER import logic import constants as c class GameGrid(Frame): def __init__(self): Frame.__init__(self) self.grid() self.master.title('C1CTF2019') self.master.bind('<Key>', self.key_down) self.commands = { c.KEY_J: logic.down, c.KEY_K: logic.up, c.KEY_L: logic.right, c.KEY_H: logic.left, c.KEY_RIGHT_ALT: logic.right, c.KEY_LEFT_ALT: logic.left, c.KEY_DOWN_ALT: logic.down, c.KEY_UP_ALT: logic.up, c.KEY_RIGHT: logic.right, c.KEY_LEFT: logic.left, c.KEY_DOWN: logic.down, c.KEY_UP: logic.up } self.grid_cells = [] self.init_grid() self.init_matrix() self.update_grid_cells() self.mainloop() def init_grid(self): background = Frame(self, c.BACKGROUND_COLOR_GAME, c.SIZE, c.SIZE, **('bg', 'width', 'height')) background.grid() for i in range(c.GRID_LEN): grid_row = [] for j in range(c.GRID_LEN): cell = Frame(background, c.BACKGROUND_COLOR_CELL_EMPTY, c.SIZE / c.GRID_LEN, c.SIZE / c.GRID_LEN, **('bg', 'width', 'height')) cell.grid(i, j, c.GRID_PADDING, c.GRID_PADDING, **('row', 'column', 'padx', 'pady')) t = Label(cell, '', c.BACKGROUND_COLOR_CELL_EMPTY, CENTER, c.FONT, 5, 2, **('master', 'text', 'bg', 'justify', 'font', 'width', 'height')) t.grid() grid_row.append(t) self.grid_cells.append(grid_row) def gen(self): return random.randint(0, c.GRID_LEN - 1) def init_matrix(self): self.matrix = logic.new_game(4) self.history_matrixs = list() self.matrix = logic.add_two(self.matrix) self.matrix = logic.add_two(self.matrix) def update_grid_cells(self): for i in range(c.GRID_LEN): for j in range(c.GRID_LEN): new_number = self.matrix[i][j] if new_number == 0: self.grid_cells[i][j].configure('', c.BACKGROUND_COLOR_CELL_EMPTY, **('text', 'bg')) continue self.grid_cells[i][j].configure(str(new_number), c.BACKGROUND_COLOR_DICT[new_number], c.CELL_COLOR_DICT[new_number], **('text', 'bg', 'fg')) self.update_idletasks() def key_down(self, event): key = repr(event.char) if key == c.KEY_BACK and len(self.history_matrixs) > 1: self.matrix = self.history_matrixs.pop() self.update_grid_cells() print('back on step total step:', len(self.history_matrixs)) elif key in self.commands: (self.matrix, done) = self.commands[repr(event.char)](self.matrix) if done: self.matrix = logic.add_two(self.matrix) self.history_matrixs.append(self.matrix) self.update_grid_cells() done = False if logic.game_state(self.matrix) == 'win': self.grid_cells[1][0].configure('C1CTF', c.BACKGROUND_COLOR_CELL_EMPTY, **('text', 'bg')) self.grid_cells[1][1].configure('{2048', c.BACKGROUND_COLOR_CELL_EMPTY, **('text', 'bg')) self.grid_cells[1][2].configure('_1s_', c.BACKGROUND_COLOR_CELL_EMPTY, **('text', 'bg')) self.grid_cells[1][3].configure('fun}', c.BACKGROUND_COLOR_CELL_EMPTY, **('text', 'bg')) if logic.game_state(self.matrix) == 'lose': self.grid_cells[1][1].configure('You', c.BACKGROUND_COLOR_CELL_EMPTY, **('text', 'bg')) self.grid_cells[1][2].configure('Lost!', c.BACKGROUND_COLOR_CELL_EMPTY, **('text', 'bg')) def generate_next(self): index = (self.gen(), self.gen()) while self.matrix[index[0]][index[1]] != 0: index = (self.gen(), self.gen()) self.matrix[index[0]][index[1]] = 2 gamegrid = GameGrid()
11.找到flag大公告成
總結
到此這篇關于python反編譯教程之2048小游戲?qū)嵗奈恼戮徒榻B到這了,更多相關python反編譯2048小游戲內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Python基于釘釘監(jiān)控發(fā)送消息提醒的實現(xiàn)
本文主要介紹了Python基于釘釘監(jiān)控發(fā)送消息提醒的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-06-06python 3調(diào)用百度OCR API實現(xiàn)剪貼板文字識別
這篇文章主要為大家詳細介紹了python 3調(diào)用百度OCR API實現(xiàn)剪貼板文字識別,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-09-09