拼图游戏

程序说明

我们已经为你准备了程序模板,模板中导入了必要的模块和一些全局变量,你需要编写一些函数,实现这个游戏。
通过该项目你可以巩固对列表的理解,同时初尝面向对象编程的概念。
本项目用列表的列表表示拼图板,如下面的board变量所示。
board = [[None, None, None],
[None, None, None],
[None, None, None]]
这样的列表又叫二维列表,取得某个元素的方法与一维列表类似,例如board第一行第二列上的元素表示为board[0][1]。我将board组织成3行3列的形式,是希望你将其理解为一个3×3的矩阵,然后将其对应位置上的元素理解为拼图板上的图像块。

一开始board的所有元素都是None,通过init_board()函数,Square对象被填充到该列表中,拼图板上的空缺用None表示。

图像块在该程序里用Square对象表示,它们都只有一个属性:center,其含义是该图像块的中心在完整图像上的坐标。8个图像块的中心都在all_coordinates列表中(已经在程序中定义过了),你需要根据simpleguitk显示图像的方式理解这些坐标。Square对象还有一个draw方法,它根据图像块所在图板上的位置,在画布上显示自己。

因为通过frame.set_mouseclick_handler(mouseclick) 注册了鼠标点击事件,所以当鼠标点在画布上时,就触发了mouseclick函数,该函数的参数pos是鼠标点击在画布上的坐标,可以利用取整操作将该坐标换算成board列表上的坐标,例如pos[1] // IMAGE_SIZE 可以得到board“矩阵”的横坐标。

有了board列表上元素的坐标,就可以取得该元素然后根据该元素是空缺还是图像块,如果是图像块再判断其能否移动,如果能移动就要和附近的空缺交换在board列表中的位置。

编码步骤

(1)完成Square类的draw方法。
(2)在draw函数中迭代board列表,调用每个图像块对象的draw方法,在画布上显示图像块。
(3)编写mouseclick函数,实现游戏逻辑。

实现后参考图

python拼图程序设计步骤 拼图 python_python

项目模板

# -*- coding: utf-8 -*-

import simpleguitk as simplegui
import random

# 载入外部图像
baymax = simplegui.load_image("http://mooc.xjau.edu.cn:80/asset-v1:XJAU_CS+CS001+2019_T1+type@asset+block@baymax.jpg")

# 定义常量
# 画布的尺寸
WIDTH = 600
HEIGHT = WIDTH + 100

# 图像块的边长
IMAGE_SIZE = WIDTH / 3


# 图像块坐标列表
all_coordinates = [[IMAGE_SIZE*0.5, IMAGE_SIZE*0.5], [IMAGE_SIZE*1.5, IMAGE_SIZE*0.5],
                   [IMAGE_SIZE*2.5, IMAGE_SIZE*0.5], [IMAGE_SIZE*0.5, IMAGE_SIZE*1.5],
                   [IMAGE_SIZE*1.5, IMAGE_SIZE*1.5], [IMAGE_SIZE*2.5, IMAGE_SIZE*1.5],
                   [IMAGE_SIZE*0.5, IMAGE_SIZE*2.5], [IMAGE_SIZE*1.5, IMAGE_SIZE*2.5], None]

# 棋盘行列数
ROWS = 3
COLS = 3

# 移动步数
steps = 0

# 保存所有图像块的列表
board = [[None, None, None],
         [None, None, None],
         [None, None, None]]        


# 图像块类
class Square:
    def __init__(self, coordinate):
        self.center = coordinate

    def draw(self, canvas, board_pos):
        # 步骤1 代码写在这里
        pass


# 初始化拼图板
def init_board():
    # 打乱图像块坐标
    random.shuffle(all_coordinates)
    # 填充拼图板
    for i in range(ROWS):
        for j in range(COLS):
            idx = i * ROWS + j
            square_center = all_coordinates[idx]
            if square_center is None:
                board[i][j] = None
            else:
                board[i][j] = Square(square_center)


# 重置游戏    
def play_game():
    global steps
    steps = 0
    init_board()


# 绘制游戏界面各元素
def draw(canvas):
    # 画黑框
    canvas.draw_polygon([[0, 0], [WIDTH, 0], [WIDTH, WIDTH], [0, WIDTH]], 1, 'Black')

    # 画目标图像
    canvas.draw_image(baymax, [WIDTH/2, WIDTH/2], [WIDTH, WIDTH], [50, WIDTH+50], [98, 98])

    # 画步数
    canvas.draw_text("步数:"+str(steps), [400, 680], 22, "White")

    # 画图像块
    # 步骤2 代码写在这里
    pass
    
    
def mouseclick(pos):
    global steps
    # 将点击位置换算成拼图板上的坐标
    r = int(pos[1] // IMAGE_SIZE)
    c = int(pos[0] // IMAGE_SIZE)

    if r < 3 and c < 3:             # 点击位置在拼图板内才移动图片
        if board[r][c] is None:     # 点到空位置上什么也不移动
            return
        else:
            # 依次检查当前图像块的上,下,左,右是否有空位置,如果有就移动当前图像块
            # 步骤3 代码写在这里
            pass


# 创建框架
frame = simplegui.create_frame("拼图", WIDTH, HEIGHT)
frame.set_canvas_background("Black")
frame.set_draw_handler(draw)
frame.add_button("重新开始", play_game, 60)

# 注册鼠标事件
frame.set_mouseclick_handler(mouseclick)

# 初始化游戏
play_game()

# 启动框架
frame.start()