Python实现人物拼图游戏

本文介绍了如何使用Python的PIL库进行图片的裁剪功能,并结合Tkinter库实现了一个简单的3x3拼图游戏。代码示例展示了如何读取图片、切割成指定大小的块并创建一个基本的图形用户界面来玩拼图游戏。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.裁剪图片

import os
from PIL import Image

def splitimage(src, rownum, colnum, dstpath):
    img = Image.open(src)
    w, h = img.size
    if rownum <= h and colnum <= w:
        print('Original image info: %sx%s, %s, %s' % (w, h, img.format, img.mode))
        print('开始处理图片切割, 请稍候...')

        s = os.path.split(src)
        if dstpath == '':
            dstpath = s[0]
        fn = s[1].split('.')
        basename = fn[0]
        ext = fn[-1]

        num = 0
        rowheight = h // rownum
        colwidth = w // colnum
        for r in range(rownum):
            for c in range(colnum):
                box = (c * colwidth, r * rowheight, (c + 1) * colwidth, (r + 1) * rowheight)
                img.crop(box).save(os.path.join(dstpath, basename + '_' + str(num) + '.' + ext))
                num = num + 1

        print('图片切割完毕,共生成 %s 张小图片。' % num)
    else:
        print('不合法的行列切割参数!')

#src = input('请输入图片文件路径:')
src  =""#建议图片路径与python文件在同一文件目录下
if os.path.isfile(src):
    dstpath = input('请输入图片输出目录(不输入路径则表示使用源图片所在目录):')
    
    if (dstpath == '') or os.path.exists(dstpath):
        row = int(input('请输入切割行数:'))
        col = int(input('请输入切割列数:'))#本题是实现3*3的人物拼图游戏
        if row > 0 and col > 0:
            splitimage(src, row, col, dstpath)
        else:
            print('无效的行列切割参数!')
    else:
        print('图片输出目录 %s 不存在!' % dstpath)
else:
    print('图片文件 %s 不存在!' % src)

二.实现游戏

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


root = Tk('拼图2023')
root.title(" 拼图--2023")
# 载入外部图像
Pics = []
for i in range(9):
    filename = "kjx2_" + str(i) + ".png"#裁剪后照片文件路径
    Pics.append(PhotoImage(file=filename))
# 定义常量
# 画布的尺寸
WIDTH = 300
HEIGHT = 400
# 图像块的边长
IMAGE_WIDTH = WIDTH // 3
IMAGE_HEIGHT = HEIGHT // 3

# 棋盘行列数
ROWS = 3
COLS = 3
# 移动步数
steps = 0
#  保存所有图像块的列表
board = [[0, 1, 2],
         [3, 4, 5],
         [6, 7, 8]]


# 图像块类
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 init_board():
    # 打乱图像块坐标
    L = list(range(8))
    L.append(None)
    random.shuffle(L)
    # 填充拼图板
    for i in range(ROWS):
        for j in range(COLS):
            idx = i * ROWS + j
            orderID = L[idx]
            if orderID is None:
                board[i][j] = None
            else:
                board[i][j] = Square(orderID)
            # 重置游戏


def play_game():
    global steps
    steps = 0
    init_board()


# 绘制游戏界面各元素
def drawBoard(canvas):
    # 画黑框
    canvas.create_polygon((0, 0, WIDTH, 0, WIDTH, HEIGHT, 0, HEIGHT), width=1, outline='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")
    # 画图像块
    for i in range(ROWS):
        for j in range(COLS):
            if board[i][j] is not None:
                board[i][j].draw(canvas, (IMAGE_WIDTH * (j + 0.5), IMAGE_HEIGHT * (i + 0.5)))


def mouseclick(pos):
    global steps
    # 将点击位置换算成拼图板上的坐标
    r = int(pos.y // IMAGE_HEIGHT)
    c = int(pos.x // IMAGE_WIDTH)
    print(r, c)
    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
            # print(board)
            label1["text"] = str(steps)
            cv.delete('all')  # 清除canvas画布上的内容
            drawBoard(cv)
    if win():
        showinfo(title="恭喜", message="你成功了!")

def runanswers():
    

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


def callBack2():
    print("重新开始")
    play_game()
    cv.delete('all')  # 清除canvas画布上的内容
    drawBoard(cv)



# 设置窗口
cv = Canvas(root, bg='green', width=WIDTH, height=HEIGHT)
b1 = Button(root, text="重新开始",command=callBack2, width=20)
label1 = Label(root, text="0", fg="red", width=20)
label1.pack()
cv.bind("<Button-1>", mouseclick)
cv.find
cv.pack()
b1.pack()
play_game()
drawBoard(cv)
root.mainloop()










 注意:使用的照片大小不能太大,不然可能会出现覆盖的情况(如果你的显示屏很大当我没说),另外画布大小最好与原照片实际大小一样。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值