用python将图片切割成9张,选取8张和一张空白图进行随机排序,生成一个简易的九宫格拼图游戏
请使用600X600分辨率的图片,并命名为"pic.png"
if __name__ == "__main__":
bCut = 1; # bCut = 1时 切割成3*3小图片。# 取图片区域(0, 0, 600, 600)
if bCut == 1:
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('不合法的行列切割参数!')
def cropimage(src):
img = Image.open(src)
region = (0, 0, 600, 600) # 取图片区域(0, 0, 600, 600)
# 裁切图片
cropImg = img.crop(region)
# 保存裁切后的图片
cropImg.save(src)
# src = input('请输入图片文件路径:')
src = "pic.png"
if os.path.isfile(src):
dstpath = input('请输入图片输出目录(直接回车则表示使用py文件所在目录):')
if (dstpath == '') or os.path.exists(dstpath):
cropimage(src);
row = 3
col = 3
if row > 0 and col > 0:
splitimage(src, row, col, dstpath)
else:
print('无效的行列切割参数!')
else:
print('图片输出目录 %s 不存在!' % dstpath)
else:
print('图片文件 %s 不存在!' % src)
#exit(0);
from tkinter import *
from tkinter.messagebox import *
import random
root = Tk('拼图')
root.title("拼图")
# 载入外部图像
Pics = []
for i in range(9):
filename = "pic_" + str(i) + ".png"
Pics.append(PhotoImage(file=filename))
# 定义常量
# 画布的尺寸
WIDTH = 600
HEIGHT = 600
# 图像块的边长
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 # 为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', fill='Pink')
# 画目标图像
# 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)
bCycle = 1; # 循环移位标志 added by zim
if bCycle == 0: # 原始版本,没有循环移位
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)
else: # 循环移位版本
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
################################# 循环移位,即类似贪食蛇可从最左边墙移动到最右边 by zim
elif r - 2 >= 0 and board[r - 2][c] is None: # 判断最上面是否为空
board[r][c] = None
board[r - 2][c] = current_square
steps += 1
elif r + 2 <= 2 and board[r + 2][c] is None: # 判断最下面是否为空
board[r][c] = None
board[r + 2][c] = current_square
steps += 1
elif c + 2 <= 2 and board[r][c + 2] is None: # 判断最右面是否为空
board[r][c] = None
board[r][c + 2] = current_square
steps += 1
elif c - 2 >= 0 and board[r][c - 2] is None: # 判断最左面是否为空
board[r][c] = None
board[r][c - 2] = current_square
steps += 1
# print(board)
label1["text"] = str(steps)
cv.delete('all') # 清除canvas画布上的内容
drawBoard(cv)
if win():
showinfo(title="恭喜", message="你成功了!")
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()
运行代码,切割