【拼图游戏】自选图片拼图–基于pygame实现

游戏截图

0927-1

0927-2

0927-3

配置类

'''配置类'''
class CFG:
    def __init__(self):
        self.SCREENSIZE = (640, 640)
        self.PICTURE_ROOT_DIR = os.path.join(os.getcwd(), '你的图片文件夹')
        self.FONTPATH = os.path.join(os.getcwd(), '你的字体文件') # 例如simsun.ttc
        self.BACKGROUNDCOLOR = (255, 255, 255)
        self.FPS = 30
        self.NUMRANDOM = 50    # 随机打乱拼图次数

cfg=CFG()

打乱拼图

def newGameBoard(num_rows, num_cols, num_cells):
    board = [i for i in range(num_cells)]
    # 去掉右下角的一块作为空白
    blank_cell_idx = num_cells - 1
    board[blank_cell_idx] = -1
    for i in range(cfg.NUMRANDOM*num_rows): # n*n的拼图,打乱次数为50*n
        direction = random.randint(0, 3)
        if direction == 0:
            blank_cell_idx = moveLeft(board, blank_cell_idx, num_cols)
        elif direction == 1:
            blank_cell_idx = moveRight(board, blank_cell_idx, num_cols)
        elif direction == 2:
            blank_cell_idx = moveUp(board, blank_cell_idx, num_rows, num_cols)
        elif direction == 3:
            blank_cell_idx = moveDown(board, blank_cell_idx, num_cols)
    return board, blank_cell_idx

开始界面

'''游戏开始界面'''
def gameStart(screen, width, height):
    screen.fill(cfg.BACKGROUNDCOLOR)

    tfont = pygame.font.Font(cfg.FONTPATH, width // 4)
    title = tfont.render('Jigsaw', True, (255, 0, 0))
    trect = title.get_rect()
    trect.midtop = (width / 2, height / 10)
    screen.blit(title, trect)

    cfont = pygame.font.Font(cfg.FONTPATH, width // 20)
    content1 = cfont.render('Press number key to start', True, (0, 0, 255))
    content2 = cfont.render('Alternatives:3*3 4*4 …… 9*9', True, (0, 0, 0))
    crect1 = content1.get_rect()
    crect1.midtop = (width / 2, height / 2.2)
    crect2 = content2.get_rect()
    crect2.midtop = (width / 2, height / 1.8)
    screen.blit(content1, crect1)
    screen.blit(content2, crect2)

    while True:
        for event in pygame.event.get():
            if (event.type == pygame.QUIT) or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
                pygame.quit()
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                for i in range(2,10):
                    if event.key == ord(str(i)):
                        return i
        pygame.display.update()

移动方块

def moveRight(board, blank_cell_idx, num_cols):
    if blank_cell_idx % num_cols == 0: return blank_cell_idx
    board[blank_cell_idx - 1], board[blank_cell_idx] = board[blank_cell_idx], board[blank_cell_idx - 1]
    return blank_cell_idx - 1
    
def moveLeft(board, blank_cell_idx, num_cols):
    if (blank_cell_idx + 1) % num_cols == 0: return blank_cell_idx
    board[blank_cell_idx + 1], board[blank_cell_idx] = board[blank_cell_idx], board[blank_cell_idx + 1]
    return blank_cell_idx + 1
    
def moveDown(board, blank_cell_idx, num_cols):
    if blank_cell_idx < num_cols: return blank_cell_idx
    board[blank_cell_idx - num_cols], board[blank_cell_idx] = board[blank_cell_idx], board[blank_cell_idx - num_cols]
    return blank_cell_idx - num_cols
    
def moveUp(board, blank_cell_idx, num_rows, num_cols):
    if blank_cell_idx >= (num_rows - 1) * num_cols: return blank_cell_idx
    board[blank_cell_idx + num_cols], board[blank_cell_idx] = board[blank_cell_idx], board[blank_cell_idx + num_cols]
    return blank_cell_idx + num_cols

判断游戏是否结束

def isGameOver(board, size):
    assert isinstance(size, int)
    num_cells = size * size
    for i in range(num_cells - 1):
        if board[i] != i: return False
    return True

结束界面

def gameOver(screen, width, height):
    screen.fill(cfg.BACKGROUNDCOLOR)

    tfont = pygame.font.Font(cfg.FONTPATH, width // 8)
    title = tfont.render('Success!', True, (255, 0, 0))
    trect = title.get_rect()
    trect.midtop = (width / 2, height / 3.5)
    screen.blit(title, trect)

    cfont = pygame.font.Font(cfg.FONTPATH, width // 25)
    content = cfont.render('press space to try again', False, (0,0,0))
    crect = content.get_rect()
    crect.midtop = (width / 2, height / 2)
    screen.blit(content, crect)

    pygame.display.update()
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    pygame.quit()
                    sys.exit()
                if event.key == pygame.K_SPACE: # 按空格重新开始游戏
                    main()
        pygame.display.update()

主函数

def main():
    pygame.init()
    clock = pygame.time.Clock()
    # 加载图片
    img = pygame.image.load(GetImage(cfg.PICTURE_ROOT_DIR))
    img = pygame.transform.scale(img, cfg.SCREENSIZE)
    img_rect = img.get_rect()
    # 设置窗口
    screen = pygame.display.set_mode(cfg.SCREENSIZE)
    pygame.display.set_caption('Jigsaw')
    # 游戏开始界面
    size = gameStart(screen, img_rect.width, img_rect.height)
    assert isinstance(size, int)
    num_rows, num_cols = size, size
    num_cells = size * size
    # 计算Cell大小
    cell_width = img_rect.width // num_cols
    cell_height = img_rect.height // num_rows
    # 避免初始化为原图
    while True:
        game_board, blank_cell_idx = newGameBoard(num_rows, num_cols, num_cells)
        if not isGameOver(game_board, size):
            break
    # 主循环
    is_running = True
    while is_running:
        for event in pygame.event.get():
            if (event.type == pygame.QUIT) or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
                pygame.quit()
                sys.exit()
            elif event.type == pygame.KEYDOWN:  # wsad操作
                if event.key == pygame.K_UP or event.key == ord('w'):
                    blank_cell_idx = moveUp(game_board, blank_cell_idx, num_rows, num_cols)
                elif event.key == pygame.K_DOWN or event.key == ord('s'):
                    blank_cell_idx = moveDown(game_board, blank_cell_idx, num_cols)
                elif event.key == pygame.K_LEFT or event.key == ord('a'):
                    blank_cell_idx = moveLeft(game_board, blank_cell_idx, num_cols)
                elif event.key == pygame.K_RIGHT or event.key == ord('d'):
                    blank_cell_idx = moveRight(game_board, blank_cell_idx, num_cols)
            elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                x, y = pygame.mouse.get_pos()  # 鼠标点击
                x_pos = x // cell_width
                y_pos = y // cell_height
                idx = x_pos + y_pos * num_cols
                if idx == blank_cell_idx - 1:
                    blank_cell_idx = moveRight(game_board, blank_cell_idx, num_cols)
                elif idx == blank_cell_idx + 1:
                    blank_cell_idx = moveLeft(game_board, blank_cell_idx, num_cols)
                elif idx == blank_cell_idx + num_cols:
                    blank_cell_idx = moveUp(game_board, blank_cell_idx, num_rows, num_cols)
                elif idx == blank_cell_idx - num_cols:
                    blank_cell_idx = moveDown(game_board, blank_cell_idx, num_cols)
        # 判断游戏是否结束
        if isGameOver(game_board, size):
            game_board[blank_cell_idx] = num_cells - 1
            is_running = False

        screen.fill(cfg.BACKGROUNDCOLOR)
        for i in range(num_cells):
            if game_board[i] == -1:
                continue
            x_pos = i // num_cols
            y_pos = i % num_cols
            rect = pygame.Rect(y_pos * cell_width, x_pos * cell_height, cell_width, cell_height)
            img_area = pygame.Rect((game_board[i] % num_cols) * cell_width, (game_board[i] // num_cols) * cell_height,
                                   cell_width, cell_height)
            screen.blit(img, rect, img_area)
        for i in range(num_cols + 1):
            pygame.draw.line(screen, (0,0,0), (i * cell_width, 0), (i * cell_width, img_rect.height))
        for i in range(num_rows + 1):
            pygame.draw.line(screen, (0,0,0), (0, i * cell_height), (img_rect.width, i * cell_height))
        pygame.display.update()
        clock.tick(cfg.FPS)
    # 游戏结束界面
    gameOver(screen, img_rect.width, img_rect.height)

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>