首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >迎中秋,我用Python开发了一款月饼拼图游戏,快来看看你要几步完成挑战吧

迎中秋,我用Python开发了一款月饼拼图游戏,快来看看你要几步完成挑战吧

作者头像
可以叫我才哥
发布2021-09-24 15:56:23
5880
发布2021-09-24 15:56:23
举报
文章被收录于专栏:可以叫我才哥可以叫我才哥

大家好,我是才哥。

马上中秋了,不得不说,已经感受到了浓浓的中秋气氛,大家吃月饼都快吃“”了,毕竟公司之间月饼送来送去的。。

那么,今天才哥带大家玩点不一样的,咱们用Python写个益智拼图游戏,咱自己拼个月饼出来,顺便比拼一下IQ,看看最少几步搞定(欢迎留言区 留言)!

先看效果:(点击播放)

接下来,我们介绍一下开发过程。

目录:

  • 1. 图片资源准备
  • 2. 拼图逻辑梳理
  • 3. 功能开发

1. 图片资源准备

案例中我们采用的是3×3的拼图结构,需要准备一张月饼图,建议是正方形的尺寸(当然大家学会后可以任意尺寸其实),然后将图片裁剪成3×3=9张。

这里采用的是PIL库的操作方法,关于该库的更多操作技巧大家可以参考此前推文《Python基础模块:图像处理模块@PIL(批量分类处理图片及添加水印)》。

from PIL import Image

img = Image.open(r'月饼.png') 
# 设置裁剪的 分割
n = 3
# 重置 尺寸
img = img.resize((520, 520))
w, h = img.size

for i in range(n):
    for j in range(n):
        # 设置裁剪的 区域(左上及右下坐标)
        box = (h/n * i, h/n * j, w/n * (i+1), w/n * (j+1))
        # 裁剪
        region = img.crop(box) 
        # 保存裁剪后的图片
        region.save(f'{i+3*j}.png')

裁剪后

2. 拼图逻辑梳理

这里我们将采取TK库进行游戏制作,基于此我们梳理拼图逻辑。

  • 先构建一个画布区域
  • 然后将画布区域分为9份(本案例中),从左到右从上到下依次编号为0-8
  • 初始情况下,随机在每个区域填充一份月饼区域图(第1步中裁剪的,除了第8张),其中有一个区域为空
  • 点击月饼区域图,如果和空区域相邻则互换,每次互换则步数加1
  • 当画布区域和月饼区域一一对应,则成功

接下来,我们实现以上功能。

3. 功能开发

先构建画布区域和月饼区域图列表

import random
from tkinter.messagebox import *
from tkinter import *

# 画布区域(这里就是图片尺寸)
w = w
h = h
# 月饼区域图的边长
img_w = w // 3
img_h = h // 3
# 游戏的行列数
ROWS = 3
COLS = 3
# 移动步数
steps = 0
# 保存所有月饼区域图的列表
board = [[0, 1, 2],
         [3, 4, 5],
         [6, 7, 8]]
root = Tk('月饼拼图')
root.title("月饼拼图@可以叫我才哥")
# 载入月饼区域图9张(编号0-8)
Pics = []
for i in range(9):
    filename = f"{i}.png"
    Pics.append(PhotoImage(file=filename))

再定义一个月饼区域图的类

这个类包含编号和填充图的方法,create_image是在指定位置创建一张图

class Square:
    def __init__(self, orderID):
        self.orderID = orderID

    def draw(self, canvas, board_pos):
        img = Pics[self.orderID]
        canvas.create_image(board_pos, image=img)

初始化

就是随机打乱编号

def initBoard():
    # 创建 0-8 的数字列表
    L = list(range(9))  
    # 打乱列表顺序
    random.shuffle(L)
    # 为每个月饼区域块分配编号(随机)
    for i in range(ROWS):
        for j in range(COLS):
            idx = i * ROWS+j
            orderID = L[idx]
            # 8号就是左下角,这里需要空出来
            if orderID == 8:
                board[i][j] = None
            else:
                board[i][j] = Square(orderID)

填充画布区域块

用月饼区域图填充对应位置

def drawBoard(canvas):
    canvas.create_polygon((0, 0, w, 0, w, h, 0, h), width=1, outline='white')
    for i in range(ROWS):
        for j in range(COLS):
            if board[i][j] != None:
                board[i][j].draw(canvas, (img_w*(j+0.5), img_h*(i+0.5)))

操作逻辑

鼠标点击判断,根据点击的区域块与空白块相邻关系决定互换逻辑(上下左右)

def mouseClick(pos):
    global steps
    r = int(pos.y // img_h)
    c = int(pos.x // img_w)
    if r < 3 and c < 3:
        if board[r][c] is None:
            return
        else:
            current_square = board[r][c]
            if r-1 >= 0 and board[r-1][c] is None:
                board[r][c] = None
                board[r-1][c] = current_square
                steps += 1
            elif c+1 <= 2 and board[r][c+1] is None:
                board[r][c] = None
                board[r][c+1] = current_square
                steps += 1
            elif r+1 <= 2 and board[r+1][c] is None:
                board[r][c] = None
                board[r+1][c] = current_square
                steps += 1
            elif c-1 >= 0 and board[r][c-1] is None:
                board[r][c] = None
                board[r][c-1] = current_square
                steps += 1
            lb["text"] = f"累计使用步数:{steps}"
            cv.delete('all') 
            drawBoard(cv)
    if win():
        showinfo(title="提示", message="挑战成功!")

成功判断

当区域块和月饼区域块一一对应,则拼图挑战成功

def win(): 
    for i in range(ROWS): 
        for j in range(COLS): 
            if board[i][j] != None  and  board[i][j].orderID !=i * ROWS + j: 
                return False 
    return True

开始游戏与重置

def playGame(): 
    global steps  
    steps = 0 
    initBoard()

def rePlay(): 
    print("重新开始") 
    playGame() 
    # 清除canvas画布上的内容
    cv.delete('all')  
    # 累计步数清零
    lb["text"] = "累计使用步数:0"
    drawBoard(cv)

执行语句

显示当前累计步数预计重置游戏按钮

if __name__ == "__main__":
    cv = Canvas(root, bg = 'white', width = w, height = h) 
    b1=Button(root,bg = 'yellow', text="重新开始",font = 20, command=rePlay,width=20,height=2) 
    lb=Label(root, text=f"累计使用步数:{steps}" ,fg="red", width=30, height=2, font=12) 
    lb.pack() 
    cv.bind("<Button-1>", mouseClick) 
    cv.find 
    cv.pack() 
    b1.pack() 
    playGame() 
    drawBoard(cv) 
    root.mainloop()

基于以上几步,我们就完成了本次的拼图游戏。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-09-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 可以叫我才哥 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档