通過(guò)加入自己定義的圖片,對(duì)這個(gè)圖片完成一定數(shù)量的拆分后再將拆分后的小圖片進(jìn)行隨機(jī)打亂,這也算是實(shí)現(xiàn)一個(gè)拼圖小游戲的基本思路吧。
為了將其做成一個(gè)桌面應(yīng)用,這里使用的是pygame這一個(gè)非標(biāo)準(zhǔn)庫(kù)。python環(huán)境中還沒(méi)有pygame的話可以選擇使用pip的方式安裝一下。
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/
下面將開(kāi)發(fā)中使用到的python庫(kù)都列舉一下,除了pygame處理游戲之外,還有sys、random分別用來(lái)做系統(tǒng)操作和隨機(jī)數(shù)的處理。
# Importing the pygame, sys, and random modules.
import pygame, sys, random
# Importing all the constants from the pygame.locals module.
from pygame.locals import *
創(chuàng)建一個(gè)python類GameMain,將所有的游戲處理相關(guān)的業(yè)務(wù)全部寫(xiě)到這個(gè)類中進(jìn)行處理,包括一些初始化操作等等,最后我們通過(guò)main函數(shù)調(diào)用啟動(dòng)整個(gè)拼圖游戲。
class GameMain():
def __init__(self, window_width, window_height, background_color,
fps, colums, max_round_time, game_image):
self.init_static_data(window_width=window_width, window_height=window_height,
background_color=background_color, fps=fps, colums=colums, max_round_time=max_round_time)
self.init_game_data(game_image='./wd.jpeg')
self.init_game_main()
通過(guò)GameMain類的初始化函數(shù)init來(lái)做類的初始化并且分別調(diào)用init_static_data、init_game_data、init_game_main三個(gè)主要的實(shí)現(xiàn)函數(shù)。
init_static_data函數(shù)主要用來(lái)將一些全局的靜態(tài)參數(shù)進(jìn)行初始化賦值,為了避免沒(méi)有值時(shí)候的報(bào)錯(cuò)默認(rèn)分別給這些參數(shù)都賦值,包括背景顏色、拼圖游戲分割成小圖片的列數(shù)等等。
def init_static_data(self, window_width=500, window_height=500,
background_color=(255, 255, 255), fps=40, colums=3, max_round_time=100):
"""
The function initializes the game data and the game main
:param window_width: The width of the game window
:param window_height: The height of the game window
:param background_color: The background color of the game window
:param fps: The number of frames per second that the game will run at
:param colums: The number of columns in the game
:param max_round_time: The maximum time for each round
:param game_image: The image that will be used for the game
"""
self.window_width = window_width
self.window_height = window_height
self.background_color = background_color
self.black_color = (0, 0, 0)
self.fps = fps
self.colums = colums
self.cell_nums = self.colums * self.colums
self.max_round_time = max_round_time
init_game_data函數(shù),主要將游戲執(zhí)行過(guò)程中的一些參數(shù)進(jìn)行計(jì)算或者計(jì)算之后的數(shù)據(jù)值進(jìn)行保存,因?yàn)樵诤竺娴挠螒蛑餮h(huán)中肯定是需要用到的,包括游戲載入的一整張圖片的路徑以及游戲窗口的標(biāo)題等等。
def init_game_data(self, game_image='./wd.jpeg'):
"""
> This function initializes the game data by reading the game image and extracting the game data from it
:param game_image: The image of the game you want to play, defaults to ./wd.jpeg (optional)
"""
pygame.init()
self.main_clock = pygame.time.Clock()
self.game_image = pygame.image.load(game_image)
self.game_rect = self.game_image.get_rect()
self.window_surface = pygame.display.set_mode((self.game_rect.width, self.game_rect.height))
pygame.display.set_caption('拼圖游戲')
self.cell_width = int(self.game_rect.width / self.colums)
self.cell_height = int(self.game_rect.height / self.colums)
self.finished = False
self.game_board, self.black_cell = self.generate_game_borad()
init_game_main函數(shù)中加入了死循環(huán)的方式讓游戲一直處于執(zhí)行中的狀態(tài),除非是已經(jīng)完成了游戲或是直接退出游戲了才會(huì)停止。主要實(shí)現(xiàn)的是游戲步驟以及鍵盤(pán)的監(jiān)聽(tīng)或鼠標(biāo)的點(diǎn)擊事件維持整個(gè)游戲狀態(tài)的運(yùn)行。
def init_game_main(self):
"""
> This function initializes the game data by reading the game image and extracting the game data from it
:param game_image: The image of the game you want to play, defaults to ./wd.jpeg (optional), defaults to ./wd.jpeg
(optional)
"""
while True:
for event in pygame.event.get():
if event.type == QUIT:
self.game_exit()
if self.finished:
continue
if event.type == KEYDOWN:
if event.key == K_LEFT or event.key == ord('a'):
self.black_cell = self.move_left(self.game_board, self.black_cell)
if event.key == K_RIGHT or event.key == ord('d'):
self.black_cell = self.move_right(self.game_board, self.black_cell)
if event.key == K_UP or event.key == ord('w'):
self.black_cell = self.move_up(self.game_board, self.black_cell)
if event.key == K_DOWN or event.key == ord('s'):
self.black_cell = self.move_down(self.game_board, self.black_cell)
if event.type == MOUSEBUTTONDOWN and event.button == 1:
x, y = pygame.mouse.get_pos()
col = int(x / self.cell_width)
row = int(y / self.cell_height)
index = col + row * self.colums
if (
index == self.black_cell - 1 or index == self.black_cell + 1 or index == self.black_cell - self.colums or index == self.black_cell + self.colums):
self.game_board[self.black_cell], self.game_board[index] = self.game_board[index], \
self.game_board[self.black_cell]
self.black_cell = index
if (self.is_finished(self.game_board)):
self.game_board[self.black_cell] = self.cell_nums - 1
self.finished = True
self.window_surface.fill(self.background_color)
for i in range(self.cell_nums):
row_dst = int(i / self.colums)
col_dst = int(i % self.colums)
rect_dst = pygame.Rect(col_dst * self.cell_width, row_dst * self.cell_height, self.cell_width,
self.cell_height)
if self.game_board[i] == -1:
continue
row_area = int(self.game_board[i] / self.colums)
col_area = int(self.game_board[i] % self.colums)
rect_area = pygame.Rect(col_area * self.cell_width, row_area * self.cell_height, self.cell_width,
self.cell_height)
self.window_surface.blit(self.game_image, rect_dst, rect_area)
for i in range(self.colums + 1):
pygame.draw.line(self.window_surface, self.black_color, (i * self.cell_height, 0),
(i * self.cell_width, self.game_rect.height))
for i in range(self.colums + 1):
pygame.draw.line(self.window_surface, self.black_color, (0, i * self.cell_height),
(self.game_rect.width, i * self.cell_height))
pygame.display.update()
self.main_clock.tick(self.fps)
game_exit函數(shù),執(zhí)行游戲退出操作。
def game_exit(self):
"""
It exits the game.
"""
pygame.quit()
sys.exit()
generate_game_borad函數(shù),生成游戲運(yùn)行的主布局。
def generate_game_borad(self):
"""
It generates the game board.
"""
board = []
for i in range(self.cell_nums):
board.append(i)
black_cell = self.cell_nums - 1
board[black_cell] = -1
for i in range(self.max_round_time):
direction = random.randint(0, 3)
if (direction == 0):
black_cell = self.move_left(board, black_cell)
elif (direction == 1):
black_cell = self.move_right(board, black_cell)
elif (direction == 2):
black_cell = self.move_up(board, black_cell)
elif (direction == 3):
black_cell = self.move_down(board, black_cell)
return board, black_cell
move_right函數(shù),執(zhí)行向右移動(dòng)的操作。
def move_right(self, board, black_cell):
"""
> The function `move_right` takes in a board and a black cell and returns the board after the black cell has moved
right
:param board: the board that the game is being played on
:param black_cell: the cell that is currently black
"""
if black_cell % self.colums == 0:
return black_cell
board[black_cell - 1], board[black_cell] = board[black_cell], board[black_cell - 1]
return black_cell - 1
move_left函數(shù),執(zhí)行向左移動(dòng)的操作。
def move_left(self, board, black_cell):
"""
It moves the black cell to the left.
:param board: the board that the game is being played on
:param black_cell: the cell that is currently black
"""
if black_cell % self.colums == self.colums - 1:
return black_cell
board[black_cell + 1], board[black_cell] = board[black_cell], board[black_cell + 1]
return black_cell + 1
move_down函數(shù),執(zhí)行向下移動(dòng)的操作。
def move_left(self, board, black_cell):
"""
It moves the black cell to the left.
:param board: the board that the game is being played on
:param black_cell: the cell that is currently black
"""
if black_cell % self.colums == self.colums - 1:
return black_cell
board[black_cell + 1], board[black_cell] = board[black_cell], board[black_cell + 1]
return black_cell + 1
def move_down(self, board, black_cell):
"""
It moves the black cell down.
:param board: the board that the game is being played on
:param black_cell: the cell that the player is currently on
"""
if black_cell < self.colums:
return black_cell
board[black_cell - self.colums], board[black_cell] = board[black_cell], board[black_cell - self.colums]
return black_cell - self.colums
move_up函數(shù),執(zhí)行向下移動(dòng)的操作。
def move_up(self, board, black_cell):
"""
It moves the black cell up one space.
:param board: the board that the game is being played on
:param black_cell: the cell that the player is currently on
"""
if black_cell >= self.cell_nums - self.colums:
return black_cell
board[black_cell + self.colums], board[black_cell] = board[black_cell], board[black_cell + self.colums]
return black_cell + self.colums
is_finished函數(shù),校驗(yàn)拼圖是否已經(jīng)完成的操作。
def is_finished(self, board):
"""
If the board is full, the game is over
:param board: a 2D array representing the current state of the board. The board is composed of 3 characters: 'X',
'O', and ' '. 'X' and 'O' represent the two players. ' ' represents an empty space
"""
for i in range(self.cell_nums - 1):
if board[i] != i:
return False
return True
最后,只需要通過(guò)main的主函數(shù)將這個(gè)游戲應(yīng)用調(diào)用就可以直接打開(kāi)拼圖游戲了,并且可以設(shè)置相關(guān)的圖片參數(shù)想對(duì)哪個(gè)圖片拼圖就設(shè)置哪個(gè),一般建議設(shè)置1024像素以內(nèi)的圖片效果會(huì)比較好。
# This is a special variable in Python that is set when the program is run. If the program is being run directly (as
# opposed to being imported), then `__name__` will be set to `'__main__'`.
if __name__ == '__main__':
"""
It moves the black cell up one space
:param board: the board that the game is being played on
:param black_cell: the cell that the player is currently on
:return: The new position of the black cell.
"""
GameMain(window_width=500, window_height=500,
background_color=(255, 255, 255), fps=40,
colums=3, max_round_time=100, game_image='./wd.jpeg')
「Python 集中營(yíng)」,只做知識(shí)分享 !
聯(lián)系客服