python实现图片切割及拼图游戏

    技术2023-07-17  124

    python实现图片切割及拼图游戏

    摘要引言背景意义实现功能图片分割拼图游戏 系统结构图片切割拼图游戏 实现代码图片分割拼图游戏 实验结果程序一程序二 实验总结

    摘要

    本程序分为两个部分,都是由python编写而成的。一是图片切割程序,即传入图片的地址,图片的输入目录,程序会按指定的行列进行切割(采用3行3列,分成9张图片用于第二部分游戏的实现)。二是拼图游戏程序,游戏界面的正上方是一个拼图步数统计,界面左边是两个组件,上方是重新开始按钮,下方是拼图的完整原图作为拼图参考,界面右边是拼图游戏的主体,一个正方形再分成3行3列9个小正方块,用于存放8张切割好的图片,一个空白块,空白快用于实现四周小图片的移动。游戏成功会有弹窗提示游戏结束。

    引言

    背景

    自从20世纪90年代初Python语言诞生至今, Python已经成为最受欢迎的程序设计语言之一。自从2004年以后,python的使用率呈线性增长。它被TIOBE编程语言排行榜评为2010年度语言。 拼图游戏是广受欢迎的一种智力游戏,它不仅可以帮助家长锻炼儿童的动手动脑能力,还可帮助扩展儿童的思维,加强还原能力,提高记忆力;同时也可促进家长与孩子之间的互动。

    意义

    本程序主要意义有扩展思维,加强还原能力,提高记忆力,也可以用来打发时间

    实现功能

    图片分割

    输入指定的图片地址,输入输出的保存目录,输入行列数,程序将指定图片按照指定行列数进行切割,并保存到指定目录。

    拼图游戏

    第一个程序切割好的3*3=9张小图像块会在运行程序时载入(如果不用第一个程序分割图片,则需要自己准备9张指定大小的小图片按照指定名字放置在指定位置下)。

    运行程序会有拼图游戏的界面。如 图1—拼图界面 所示。 右上角是拼图游戏的标题。

    步数用于统计用户拼图的步数,每次图像移动后步数+1,点击重新开始可重置步数。

    重新开始按钮可以重置游戏,包括重新打乱拼图和重置步数。

    鼠标点击的图像块四周存在空白块,则移动图像块,并且步数+1,所有块移动到指定的位置则游戏结束,弹出“你成功了”弹窗。

    图1-拼图界面:

    系统结构

    图片切割

    图片裁剪基本原理如 图2—图片切割原理 所示:

    图2—图片切割原理:

    图片切割流程图如 图3—图片切割流程图 所示:

    图3—图片切割流程图 :

    拼图游戏

    拼图显示原理如 图4—拼图显示流程图 所示:

    图4—拼图显示流程图: 鼠标点击移动拼图块原理如 图5—拼图块移动原理 所示:

    图5—拼图块移动原理: 拼图游戏实现流程图如 图6—游戏流程图 所示:

    图6—游戏流程图 :

    居中并且带尺寸的图片: 当然,我们为了让用户更加便捷,我们增加了图片拖拽功能。

    实现代码

    图片分割

    from PIL import Image def splitimage(sre,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]#使用源图片所在目录s[0] fn=s[1].split('.')#s[1]是源图片文件名 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="C:\woman.png" if os.path.isfile(src): dstpath=input('请输入图片输出目录(不输入路径则表示使用源图片所在目录):') if(dstpath=='')or os.path.exists(dstpath): row=int(input('请输入切割行数:')) col=int(input('请输入切割列数:')) if row>0 and col>0: splitimage(src,row,col,dstpath) else: print('无效的行列切割参数!') else: print('图片输出目录%s不存在!'%dstpath) else: print('图片文件%s不存在!'%src)

    拼图游戏

    导包及定义常量:

    from tkinter import* from tkinter.messagebox import* import random from PIL import Image,ImageTk #本程序images目录下已经有用1.图片分解切出的9张小图片 #可以用自己喜欢的图片进行替换(大小:450*450) #定义常量 #画布的尺寸 WIDTH=450 HEIGHT=450 #图像块的边长 IMAGE_WIDTH=WIDTH//3 IMAGE_HEIGHT=HEIGHT//3 #游戏的行/列数 ROWS=3 COLS=3 #移动步数 steps=0 #保存所有图像块的列表 board=[[0,1,2], [3,4,5], [6,7,8]] root=Tk('拼图1702-171110058') root.title("171110058-陈嘉锐-拼图")

    载入外部9个小图片:

    #载入外部事先生成的9个小图像块 Pics=[] for i in range(9): filename=r"images/1702-171110058"+str(i)+".png" Pics.append(PhotoImage(file=filename))

    Square类将图像块图片绘制到Canvas上:

    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)

    打乱图像块,按编号生成对应的图像块到board列表:

    def init_board():#打乱图像块 L=list(range(9))#L列表中[0,1,2,3,4,5,6,7,8] random.shuffle(L) #填充拼图板 for i in range(ROWS): for j in range(COLS): idx=i*ROWS+j orderID=L[idx] if orderID is 8: #8号拼块不显示,所以存为None board[i][j]=None else: board[i][j]=Square(orderID)

    绘制出图像块:

    def drawBoard(canvas): canvas.create_polygon((0,0,WIDTH,0,WIDTH,HEIGHT,0,HEIGHT), width=1,outline='White',fill='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) 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') #清除画布上的内容 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 play_game() : global steps steps=0 init_board() def callBack2(): print("重新开始") play_game() cv.delete('all') #清除画布上的内容 drawBoard(cv)

    主程序:

    path="/Users/xiaoyao/Desktop/python期末作业/images/1.png" image1=Image.open(path)#通过Image=photo设置要展示的图片 photo1=ImageTk.PhotoImage(image1)#创建tkinter兼容的图片 cv=Canvas(root,bg='green',width=WIDTH,height=HEIGHT) bl=Button(root,text="重新开始",command=callBack2,width=28) b2=Label(root,image=photo1,width=200) label1=Label(root,text="步数:"+str(steps),fg="red",width=40) label1.pack() cv.bind("<Button-1>",mouseclick) cv.pack(side='right') bl.pack() #b2.pack() b2.place(y = 150,width = 200,height = 200) play_game() drawBoard(cv) root.mainloop()

    实验结果

    程序一

    程序二

    实验总结

    Python语言功能强大,但是因为自己的能力不足,实现这么是一个小小的程序却也用了很多时间,英语水平太差,python掌握得不是很多,实现一个小小的功能最后可能要在各大网站找资料,最后虽然基本上能达到了预期的目标。但是因为时间又能,能力也一般,程序还存在许多不足之处,只能等以后继续完善。

    Processed: 0.020, SQL: 9