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