python应用学习(六)——tkinter制作连连看小游戏
python 制作连连看小游戏
- 前言
- 一、准备
- 二、游戏简单介绍
- 1、游戏规则
- 2、游戏设计所需的图片库:
- 三、游戏设计
- I、创建Point点类
- II、定义函数
- III、游戏的主函数逻辑
- IV、完整代码
- 最后
前言
最近想做一个练练的小游戏给家里的小朋友玩儿,但是苦于选取素材,然后在一个巨佬的博客里找了灵感,就借用一下粉丝的头像试试爬取网页里的图片吧!(感谢各位啦!)
完成总目标:
爬取粉丝头像作为素材,完成一个连连看的小游戏
故本文分为两部分内容:
1、爬取素材部分(见python应用学习(五)——requests爬取网页图片);
2、利用素材完成连连看小游戏部分
(二)游戏制作部分
实现目标:
利用上次爬取的粉丝头像集作为素材完成连连看游戏的制作,游戏界面展示:
一、准备
1、python环境
2、涉及到的python库需要 pip install 包名
安装
二、游戏简单介绍
1、游戏规则
(1)两个选中的方块是相同的。
(2)两个选中的方块之间连接线的折点不超过两个(连接线由X轴和Y轴的平行线组成。
本游戏增加了智能查找功能,当玩家自己无法找到可以消去的两个方块时右击画面系统则会提示可以消去的两个方块。
2、游戏设计所需的图片库:
需要十张图片作为游戏素材,素材选取我在第一部分内容中通过爬虫爬取了粉丝的图片作为我的设计素材。
三、游戏设计
I、创建Point点类
class Point: def __init__(self,x,y): #构造函数,用于类实例化为对象时的初始化,具体解释见self.x = xself.y = y
II、定义函数
1、产生map地图矩阵create_map()
def create_map():global maptmpMap = []m=(Width)*(Height)//10print('m=',m)#给map矩阵的每一个位置放上打乱顺序之后的图片索引号(每个索引号对应着固定的图片)for x in range(0,m):for i in range(0,10):# 每种方块有10个tmpMap.append(x) #在tmpMap中放入0-9十种数字,每种数字十个,数字的大小对应的是imgs列表中图像对象的索引号random.shuffle(tmpMap) #将上面顺序放入的数字打乱顺序for x in range(0,Width):#0--14 for y in range(0,Height):#0--14map[x][y]=tmpMap[x*Width+y] #将tmpmap中的数据按顺序放入map形成一个10*10的矩阵print('-----------------map[][]----------------\n',map)
2、按照地图矩阵显示图片print_map()
def print_map( ):global image_map#将map矩阵中的索引号显示为对应的图片for x in range(0,Width): for y in range(0,Height):if(map[x][y]!=' '):img1= imgs[int(map[x][y])]id=cv.create_image((x*(windowwidth/10)+(windowwidth/20),y*(windowheight/10)+(windowheight/20)),image=img1)#图像中心在窗口中摆放的水平初始偏移量为40,竖直初始偏移量为40,每个图片相对偏移为80(初始偏移量的二倍)image_map[x][y]=id #把创建的图片的id放入image——map列表中与当前索引号相同的位置上,以便后续删除该id对应的图片cv.pack()# 按照图片显示位置将图片对应的imgs中的索引号显示成相应矩阵形式for y in range(0,Height):for x in range(0,Width):print (map[x][y],end=' ')#end = ‘ ’有了end就不是自动换行了,而是自动加空格print('')#自动换行
3、判断连通条件IsLink()
def IsLink (p1,p2):if lineLink(p1,p2):return Trueelif oneCornerLink(p1,p2):return Trueelif twoCornerLink(p1,p2):return Trueelse:return False
(1)直接连通lineLink()
def lineLink(p1,p2):absDistance = 0 #绝对距离(中间隔着的格子数)spaceCount = 0 #中间空着的格子数#p1和p2同行或者同列if (p1.x == p2.x or p1.y == p2.y):print('同行或者同列情况!')#同列情况if (p1.x == p2.x and p1.y != p2.y):print('同列')absDistance = abs(p1.y -p2.y) - 1 if p1.y > p2.y:zf = -1elif p1.y < p2.y:zf = 1for i in range(1,absDistance + 1):if (map[p1.x][p1.y + i * zf] == ' '):spaceCount = spaceCount + 1else:break#同行情况elif (p1.y == p2.y and p1.x != p2.x):print('同行')absDistance = abs(p1.x -p2.x) - 1 if p1.x > p2.x:zf = -1elif p1.x < p2.x:zf = 1for i in range(1,absDistance + 1):if (map[p1.x + i * zf][p1.y] == ' '):spaceCount = spaceCount + 1else:breakif (spaceCount == absDistance):print("行或者列直接连通!")return Trueelse:print('行/列不能消除!')return Falseelse:return False #不是同行同列直接返回False
(2)一个折点连通oneCornerLink()
def oneCornerLink(p1,p2):checkP1 = Point(p1.x,p2.y) #第一个直角点checkP2 = Point(p2.x,p1.y) #第二个直角点#第一个直角点检测if (map[checkP1.x][checkP1.y] == ' '):if (lineLink(checkP1,p1) and lineLink(checkP1,p2)):print("直角消除OK",checkP1.x,checkP1.y)LinePointStack.append(checkP1)return True#第二个直角点检测if (map[checkP2.x][checkP2.y] == ' '):if (lineLink(checkP2,p1) and lineLink(checkP2,p2)):print("直角消除OK",checkP2.x,checkP2.y)LinePointStack.append(checkP2)return Trueelse:print("不能直角消除")return False
(3)两个折点连通twoCornerLink()
def twoCornerLink(p1,p2):#从四个方向探测for i in range(0,4):checkP = Point(p1.x,p1.y)#向下if(i == 0):checkP.y+=1while ((checkP.y < Height) and (map[checkP.x][checkP.y] == " ")):if (oneCornerLink(checkP,p2)):print('下探测成功!')LinePointStack.append(checkP)return TruecheckP.y+=1#向上elif(i == 1):checkP.y-=1while ((checkP.y > 0) and (map[checkP.x][checkP.y] == " ")):if (oneCornerLink(checkP,p2)):print('上探测成功!')LinePointStack.append(checkP)return TruecheckP.y-=1#向左elif(i == 2):checkP.x-=1while ((checkP.x > 0) and (map[checkP.x][checkP.y] == " ")):if (oneCornerLink(checkP,p2)):print('左探测成功!')LinePointStack.append(checkP)return TruecheckP.x-=1#向右elif(i == 3):checkP.x+=1while ((checkP.x < Height) and (map[checkP.x][checkP.y] == " ")):if (oneCornerLink(checkP,p2)):print('右探测成功!')LinePointStack.append(checkP)return TruecheckP.x+=1print("不能通过两个折点连接")return False
4、判断两个图片是非为同一图像IsSame()
def IsSame(p1,p2):if (map[p1.x][p1.y] == map[p2.x][p2.y]):print("两个图片相同")return Trueelse:return False
5、在窗口中画网格drawgrid()
def drawgrid():for i in range(0,11):cv.create_line(0,(windowwidth/10)*i,windowwidth,(windowwidth/10)*i,width = 2)for i in range(0,11):cv.create_line((windowwidth/10)*i,0,(windowwidth/10)*i,windowwidth,width = 2)cv.pack()
6、画两图片的连接线drawLinkLine()
def drawLinkLine(p1,p2):print(LinePointStack,len(LinePointStack))if (len(LinePointStack)==0):print("直接连通")Line_id.append(drawLine(p1,p2)) #连接p1,p2并将连好的线的id存储在Line_id列表中elif (len(LinePointStack)==1):z=LinePointStack.pop()print("一折连通点z",z.x,z.y)Line_id.append(drawLine(p1,z))Line_id.append(drawLine(p2,z))elif (len(LinePointStack)==2):z1=LinePointStack.pop()print("2折连通点z1",z1.x,z1.y)Line_id.append(drawLine(p1,z1))z2=LinePointStack.pop()print("2折连通点z2",z2.x,z2.y)Line_id.append(drawLine(z1,z2)) Line_id.append(drawLine(p2,z2))
7、清除连接线和方块clearTwoBlock()
def clearTwoBlock():global firstSelectRectId,SecondSelectRectIdprint('clearTwoBlock__firstSelectRectId',firstSelectRectId)print('clearTwoBlock__SecondSelectRectId',SecondSelectRectId)#清除第一个选定框线 cv.delete(firstSelectRectId)#清除第2个选定框线 print('here---------------------')cv.delete(SecondSelectRectId) #清空记录方块的值map[p1.x][p1.y] = " "cv.delete(image_map[p1.x][p1.y])map[p2.x][p2.y] = " "cv.delete(image_map[p2.x][p2.y])Select_first = FalsedelConnectLine()#清除选中方块之间连接线
8、定义鼠标左键事件代码leftbuttonevent(event)
def leftbuttonevent(event):timer_interval = 0.1 # 这个间隔时间太长,那么在点击太快的话会出现误消除现象global Select_first,p1,p2global firstSelectRectId,SecondSelectRectIdprint ("clicked at", event.x, event.y)x=(event.x)//(windowwidth//10) #换算棋盘坐标y=(event.y)//(windowwidth//10)print ("clicked at", x, y)if map[x][y]==" ":showinfo(title="提示",message="此处无方块")else:if Select_first == False:p1=Point(x,y)#画选定(x1,y1)处的框线firstSelectRectId=cv.create_rectangle(x*(windowwidth/10),y*(windowwidth/10),x*(windowwidth/10)+(windowwidth/10),y*(windowwidth/10)+(windowwidth/10),width=2,outline="yellow")Select_first = Trueprint('选定第一个点',x,y)else:p2=Point(x,y)#判断第二次点击的方块是否已被第一次点击选取,如果是则返回。if (p1.x == p2.x) and (p1.y == p2.y):return#画选定(x2,y2)处的框线print('选定第二个点',x,y)SecondSelectRectId=cv.create_rectangle(x*(windowwidth/10),y*(windowwidth/10),x*(windowwidth/10)+(windowwidth/10),y*(windowwidth/10)+(windowwidth/10),width=2,outline="yellow")print('第二次点击的方块',SecondSelectRectId)cv.pack()#判断是否连通if IsSame(p1,p2) and IsLink(p1,p2):print('连通',x,y)Select_first = False#画选中方块之间连接线 drawLinkLine(p1,p2)# time.sleep(2) #这种方法不行,直接sleep()这段时间计算机什么也不干,是不行的# clearTwoBlock()t=Timer(timer_interval,clearTwoBlock)#定时函数,等待timer_interval之后执行clearTwoBlock函数,这段时间内主程序继续进行t.start() else: #重新选定第一个方块 #清除第一个选定框线 cv.delete(firstSelectRectId)cv.delete(SecondSelectRectId)#print('清除第一个选定框线')#firstSelectRectId=SecondSelectRectId#p1=Point(x,y) #设置重新选定第一个方块的坐标Select_first = False
9、定义鼠标右键事件代码 AutoFindLink(event)
def AutoFindLink(event):#自动查找global firstSelectRectId,SecondSelectRectIdglobal p1,p2timer_interval = 0.2m_nRoW=Heightm_nCol=WidthbFound = False#第一个方块从地图的0位置开始for i in range(0, m_nRoW* m_nCol):#找到则跳出循环if (bFound):break#算出对应的虚拟行列位置x1 = i % m_nCol y1 = i // m_nColp1=Point(x1,y1)#无图案的方块跳过if (map[x1][y1] == ' '):continue#第二个方块从前一个方块的后面开始for j in range( i +1 , m_nRoW* m_nCol):#算出对应的虚拟行列位置x2 = j % m_nCol y2 = j // m_nCol p2=Point(x2,y2)# 第二个方块不为空 且与第一个方块的动物相同if (map[x2][y2] != ' ' and IsSame(p1,p2)):#判断是否可以连通if (IsLink(p1, p2)):bFound = Truebreak#找到后自动消除if (bFound): #p1(x1,y1)与p2(x2,y2)连通print('找到后',p1.x,p1.y,p2.x,p2.y)#drawLinkLine(p1,p2)#画选定(x1,y1)处的框线firstSelectRectId =cv.create_rectangle(x1*(windowwidth/10),y1*(windowwidth/10),x1*(windowwidth/10)+(windowwidth/10),y1*(windowwidth/10)+(windowwidth/10),width=2,outline="yellow")#time.sleep(2)SecondSelectRectId=cv.create_rectangle(x2*(windowwidth/10),y2*(windowwidth/10),x2*(windowwidth/10)+(windowwidth/10),y2*(windowwidth/10)+(windowwidth/10),width=2,outline="yellow")print('右击——firstSelectRectId',firstSelectRectId)print('右击——SecondSelectRectId',SecondSelectRectId)t=Timer(timer_interval,clearTwoBlock) #定时函数,注意clearTwoBlock后面不要加括号,Timer的参数是要一个函数名而不是函数t.start() return bFound
III、游戏的主函数逻辑
LinePointStack = [] #将找出来的连接折点找出来放入列表中,以备连线时用
Line_id = [] #将连接好的线的id存储在Line_id列表中以备删除连接线
Select_first=False #是否已经选中第一块
firstSelectRectId=-1 #被选中第一块地图对象
SecondSelectRectId=-1 #被选中第二块地图对象
Height = 10 #纵向格子数
Width = 10 #横向格子数
windowwidth = 600 #窗口大小
windowheight = 600
map = [[" " for y in range(Height)]for x in range(Width)] #初始化一个空二维矩阵
image_map = [[" " for y in range(Height)]for x in range(Width)] #初始化一个空的二维矩阵root = Tk()
root.title('pyhton 连连看')
cv = Canvas(root, bg = 'white', width = windowwidth, height = windowheight)#修改图片大小
icon = []
for i in range(1,11): #从1-10共十张照片image = Image.open("D:\\ryc\python_learning\\10_linkup\\fan_avatar\\fans_avatar%s.png"%(i))image = image.resize(((windowwidth//10)-2, (windowheight//10)-2), Image.ANTIALIAS) # // ———— 整除 ; antialias是平滑处理icon.append(image)#PhotoImage()返回图像文件对象,并将十张图片放到一个列表中
imgs = []
for i in range(0,10):#image = Image.open("D:\\ryc\python_learning\\10_linkup\\fan_avatar\\fans_avatar%s.png"%(i))image = icon[i]photo = ImageTk.PhotoImage(image) imgs.append(photo)drawgrid() #画网格cv.bind("<Button-1>", leftbuttonevent) #鼠标左键事件
cv.bind("<Button-3>", AutoFindLink) #鼠标右键事件 <Button-2>是鼠标滚轮键
cv.pack()create_map()
print_map()
root.mainloop() #窗口显示
IV、完整代码
from tkinter import *
from PIL import Image, ImageTk
import random
import time
from threading import Timer
#from tkinter.messagebox import *#============================================创建Point点类================================================
class Point: def __init__(self,x,y): #构造函数,用于类实例化为对象时的初始化,具体解释见self.x = xself.y = y
#=========================================================================================================#=========================================在窗口中按照map矩阵中的索引号完成图片显示==============================================
def print_map( ):global image_map#将map矩阵中的索引号显示为对应的图片for x in range(0,Width): for y in range(0,Height):if(map[x][y]!=' '):img1= imgs[int(map[x][y])]id=cv.create_image((x*(windowwidth/10)+(windowwidth/20),y*(windowheight/10)+(windowheight/20)),image=img1)#图像中心在窗口中摆放的水平初始偏移量为40,竖直初始偏移量为40,每个图片相对偏移为80(初始偏移量的二倍)image_map[x][y]=id #把创建的图片的id放入image——map列表中与当前索引号相同的位置上,以便后续删除该id对应的图片cv.pack()# 按照图片显示位置将图片对应的imgs中的索引号显示成相应矩阵形式for y in range(0,Height):for x in range(0,Width):print (map[x][y],end=' ')#end = ‘ ’有了end就不是自动换行了,而是自动加空格print('')#自动换行
#=============================================================================================================================#================================产生map地图矩阵(矩阵的每个位置都存放着图片的索引号)=============================================
def create_map():global maptmpMap = []m=(Width)*(Height)//10print('m=',m)#给map矩阵的每一个位置放上打乱顺序之后的图片索引号(每个索引号对应着固定的图片)for x in range(0,m):for i in range(0,10):# 每种方块有10个tmpMap.append(x) #在tmpMap中放入0-9十种数字,每种数字十个,数字的大小对应的是imgs列表中图像对象的索引号random.shuffle(tmpMap) #将上面顺序放入的数字打乱顺序for x in range(0,Width):#0--14 for y in range(0,Height):#0--14map[x][y]=tmpMap[x*Width+y] #将tmpmap中的数据按顺序放入map形成一个10*10的矩阵print('-----------------map[][]----------------\n',map)
#=============================================================================================================================#=============================================连通条件判断=====================================================================
#========================判断两个方块是否可以连通============================
def IsLink (p1,p2):if lineLink(p1,p2):return Trueelif oneCornerLink(p1,p2):return Trueelif twoCornerLink(p1,p2):return Trueelse:return False
#=================================直接连通==================================
def lineLink(p1,p2):absDistance = 0 #绝对距离(中间隔着的格子数)spaceCount = 0 #中间空着的格子数#p1和p2同行或者同列if (p1.x == p2.x or p1.y == p2.y):print('同行或者同列情况!')#同列情况if (p1.x == p2.x and p1.y != p2.y):print('同列')absDistance = abs(p1.y -p2.y) - 1 if p1.y > p2.y:zf = -1elif p1.y < p2.y:zf = 1for i in range(1,absDistance + 1):if (map[p1.x][p1.y + i * zf] == ' '):spaceCount = spaceCount + 1else:break#同行情况elif (p1.y == p2.y and p1.x != p2.x):print('同行')absDistance = abs(p1.x -p2.x) - 1 if p1.x > p2.x:zf = -1elif p1.x < p2.x:zf = 1for i in range(1,absDistance + 1):if (map[p1.x + i * zf][p1.y] == ' '):spaceCount = spaceCount + 1else:breakif (spaceCount == absDistance):print("行或者列直接连通!")return Trueelse:print('行/列不能消除!')return Falseelse:return False #不是同行同列直接返回False
#==============================一个折点连通=================================
def oneCornerLink(p1,p2):checkP1 = Point(p1.x,p2.y) #第一个直角点checkP2 = Point(p2.x,p1.y) #第二个直角点#第一个直角点检测if (map[checkP1.x][checkP1.y] == ' '):if (lineLink(checkP1,p1) and lineLink(checkP1,p2)):print("直角消除OK",checkP1.x,checkP1.y)LinePointStack.append(checkP1)return True#第二个直角点检测if (map[checkP2.x][checkP2.y] == ' '):if (lineLink(checkP2,p1) and lineLink(checkP2,p2)):print("直角消除OK",checkP2.x,checkP2.y)LinePointStack.append(checkP2)return Trueelse:print("不能直角消除")return False
#==============================两个折点连通=================================
def twoCornerLink(p1,p2):#从四个方向探测for i in range(0,4):checkP = Point(p1.x,p1.y)#向下if(i == 0):checkP.y+=1while ((checkP.y < Height) and (map[checkP.x][checkP.y] == " ")):if (oneCornerLink(checkP,p2)):print('下探测成功!')LinePointStack.append(checkP)return TruecheckP.y+=1#向上elif(i == 1):checkP.y-=1while ((checkP.y > 0) and (map[checkP.x][checkP.y] == " ")):if (oneCornerLink(checkP,p2)):print('上探测成功!')LinePointStack.append(checkP)return TruecheckP.y-=1#向左elif(i == 2):checkP.x-=1while ((checkP.x > 0) and (map[checkP.x][checkP.y] == " ")):if (oneCornerLink(checkP,p2)):print('左探测成功!')LinePointStack.append(checkP)return TruecheckP.x-=1#向右elif(i == 3):checkP.x+=1while ((checkP.x < Height) and (map[checkP.x][checkP.y] == " ")):if (oneCornerLink(checkP,p2)):print('右探测成功!')LinePointStack.append(checkP)return TruecheckP.x+=1print("不能通过两个折点连接")return False
#=============================================================================================================================#================================================判断是非为同一图像============================================================
def IsSame(p1,p2):if (map[p1.x][p1.y] == map[p2.x][p2.y]):print("两个图片相同")return Trueelse:return False
#=============================================================================================================================#=======================================================画网格================================================================
def drawgrid():for i in range(0,11):cv.create_line(0,(windowwidth/10)*i,windowwidth,(windowwidth/10)*i,width = 2)for i in range(0,11):cv.create_line((windowwidth/10)*i,0,(windowwidth/10)*i,windowwidth,width = 2)cv.pack()
#======================================================画连接线================================================================
#连接线的绘制
def drawLine(p1,p2):print("drawLine p1,p2",p1.x,p1.y,p2.x,p2.y) id=cv.create_line(p1.x*(windowwidth/10)+(windowwidth/20),p1.y*(windowwidth/10)+(windowwidth/20),p2.x*(windowwidth/10)+(windowwidth/20),p2.y*(windowwidth/10)+(windowwidth/20),width=5,fill='red')#cv.pack()return id #存储在Line_id列表中以备删除连接线#绘制连接线,并将连好的线的id保存在line_id列表中
def drawLinkLine(p1,p2):print(LinePointStack,len(LinePointStack))if (len(LinePointStack)==0):print("直接连通")Line_id.append(drawLine(p1,p2)) #连接p1,p2并将连好的线的id存储在Line_id列表中elif (len(LinePointStack)==1):z=LinePointStack.pop()print("一折连通点z",z.x,z.y)Line_id.append(drawLine(p1,z))Line_id.append(drawLine(p2,z))elif (len(LinePointStack)==2):z1=LinePointStack.pop()print("2折连通点z1",z1.x,z1.y)Line_id.append(drawLine(p1,z1))z2=LinePointStack.pop()print("2折连通点z2",z2.x,z2.y)Line_id.append(drawLine(z1,z2)) Line_id.append(drawLine(p2,z2))
#=============================================================================================================================#====================================================删除连接线================================================================
def delConnectLine(): while len(Line_id)>0:idpop=Line_id.pop() #pop()函数返回值为列表中被删除的部分cv.delete(idpop)
#=============================================================================================================================#=================================================清除连接线和方块==============================================================
def clearTwoBlock():global firstSelectRectId,SecondSelectRectIdprint('clearTwoBlock__firstSelectRectId',firstSelectRectId)print('clearTwoBlock__SecondSelectRectId',SecondSelectRectId)#清除第一个选定框线 cv.delete(firstSelectRectId)#清除第2个选定框线 print('here---------------------')cv.delete(SecondSelectRectId) #清空记录方块的值map[p1.x][p1.y] = " "cv.delete(image_map[p1.x][p1.y])map[p2.x][p2.y] = " "cv.delete(image_map[p2.x][p2.y])Select_first = FalsedelConnectLine()#清除选中方块之间连接线
#=============================================================================================================================#===============================================鼠标左键事件代码===============================================================
def leftbuttonevent(event):timer_interval = 0.1 # 这个间隔时间太长,那么在点击太快的话会出现误消除现象global Select_first,p1,p2global firstSelectRectId,SecondSelectRectIdprint ("clicked at", event.x, event.y)x=(event.x)//(windowwidth//10) #换算棋盘坐标y=(event.y)//(windowwidth//10)print ("clicked at", x, y)if map[x][y]==" ":showinfo(title="提示",message="此处无方块")else:if Select_first == False:p1=Point(x,y)#画选定(x1,y1)处的框线firstSelectRectId=cv.create_rectangle(x*(windowwidth/10),y*(windowwidth/10),x*(windowwidth/10)+(windowwidth/10),y*(windowwidth/10)+(windowwidth/10),width=2,outline="yellow")Select_first = Trueprint('选定第一个点',x,y)else:p2=Point(x,y)#判断第二次点击的方块是否已被第一次点击选取,如果是则返回。if (p1.x == p2.x) and (p1.y == p2.y):return#画选定(x2,y2)处的框线print('选定第二个点',x,y)SecondSelectRectId=cv.create_rectangle(x*(windowwidth/10),y*(windowwidth/10),x*(windowwidth/10)+(windowwidth/10),y*(windowwidth/10)+(windowwidth/10),width=2,outline="yellow")print('第二次点击的方块',SecondSelectRectId)cv.pack()#判断是否连通if IsSame(p1,p2) and IsLink(p1,p2):print('连通',x,y)Select_first = False#画选中方块之间连接线 drawLinkLine(p1,p2)# time.sleep(2) #这种方法不行,直接sleep()这段时间计算机什么也不干,是不行的# clearTwoBlock()t=Timer(timer_interval,clearTwoBlock)#定时函数,等待timer_interval之后执行clearTwoBlock函数,这段时间内主程序继续进行t.start() else: #重新选定第一个方块 #清除第一个选定框线 cv.delete(firstSelectRectId)cv.delete(SecondSelectRectId)#print('清除第一个选定框线')#firstSelectRectId=SecondSelectRectId#p1=Point(x,y) #设置重新选定第一个方块的坐标Select_first = False
#=============================================================================================================================#===============================================鼠标右键事件代码===============================================================
def AutoFindLink(event):#自动查找global firstSelectRectId,SecondSelectRectIdglobal p1,p2timer_interval = 0.2m_nRoW=Heightm_nCol=WidthbFound = False#第一个方块从地图的0位置开始for i in range(0, m_nRoW* m_nCol):#找到则跳出循环if (bFound):break#算出对应的虚拟行列位置x1 = i % m_nCol y1 = i // m_nColp1=Point(x1,y1)#无图案的方块跳过if (map[x1][y1] == ' '):continue#第二个方块从前一个方块的后面开始for j in range( i +1 , m_nRoW* m_nCol):#算出对应的虚拟行列位置x2 = j % m_nCol y2 = j // m_nCol p2=Point(x2,y2)# 第二个方块不为空 且与第一个方块的动物相同if (map[x2][y2] != ' ' and IsSame(p1,p2)):#判断是否可以连通if (IsLink(p1, p2)):bFound = Truebreak#找到后自动消除if (bFound): #p1(x1,y1)与p2(x2,y2)连通print('找到后',p1.x,p1.y,p2.x,p2.y)#drawLinkLine(p1,p2)#画选定(x1,y1)处的框线firstSelectRectId =cv.create_rectangle(x1*(windowwidth/10),y1*(windowwidth/10),x1*(windowwidth/10)+(windowwidth/10),y1*(windowwidth/10)+(windowwidth/10),width=2,outline="yellow")#time.sleep(2)SecondSelectRectId=cv.create_rectangle(x2*(windowwidth/10),y2*(windowwidth/10),x2*(windowwidth/10)+(windowwidth/10),y2*(windowwidth/10)+(windowwidth/10),width=2,outline="yellow")print('右击——firstSelectRectId',firstSelectRectId)print('右击——SecondSelectRectId',SecondSelectRectId)t=Timer(timer_interval,clearTwoBlock) #定时函数,注意clearTwoBlock后面不要加括号,Timer的参数是要一个函数名而不是函数t.start() return bFound
#=============================================================================================================================#============================================================主函数部分=======================================================
LinePointStack = [] #将找出来的连接折点找出来放入列表中,以备连线时用
Line_id = [] #将连接好的线的id存储在Line_id列表中以备删除连接线
Select_first=False #是否已经选中第一块
firstSelectRectId=-1 #被选中第一块地图对象
SecondSelectRectId=-1 #被选中第二块地图对象
Height = 10 #纵向格子数
Width = 10 #横向格子数
windowwidth = 600 #窗口大小
windowheight = 600
map = [[" " for y in range(Height)]for x in range(Width)] #初始化一个空二维矩阵
image_map = [[" " for y in range(Height)]for x in range(Width)] #初始化一个空的二维矩阵root = Tk()
root.title('pyhton 连连看')
cv = Canvas(root, bg = 'white', width = windowwidth, height = windowheight)#修改图片大小
icon = []
for i in range(1,11): #从1-10共十张照片image = Image.open("D:\\ryc\python_learning\\10_linkup\\fan_avatar\\fans_avatar%s.png"%(i))image = image.resize(((windowwidth//10)-2, (windowheight//10)-2), Image.ANTIALIAS) # // ———— 整除 ; antialias是平滑处理icon.append(image)#PhotoImage()返回图像文件对象,并将十张图片放到一个列表中
imgs = []
for i in range(0,10):#image = Image.open("D:\\ryc\python_learning\\10_linkup\\fan_avatar\\fans_avatar%s.png"%(i))image = icon[i]photo = ImageTk.PhotoImage(image) imgs.append(photo)drawgrid() #画网格cv.bind("<Button-1>", leftbuttonevent) #鼠标左键事件
cv.bind("<Button-3>", AutoFindLink) #鼠标右键事件 <Button-2>是鼠标滚轮键
cv.pack()create_map()
print_map()
root.mainloop() #窗口显示
#=============================================================================================================================
最后
历经三天终于把这个东西搞定了,各种改错,其中不乏因为敲错大小写导致排错一个小时的情况,但是每个错误哪怕是再小也是需要认真分析的,这何尝不是一种乐趣呢?
都到这儿了,创作不易,各位看官留下你们宝贵的赞吧!笔者在此拜谢!!
其他python应用实例见:https://blog.csdn.net/weixin_45386875/article/details/113766276
python应用学习(六)——tkinter制作连连看小游戏相关推荐
- python 单机程序_Python tkinter制作单机五子棋游戏
本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 以下文章来源于Python家庭,作者Python家庭 实战项目:使用Python ...
- Python入门学习作业之猜年龄小游戏制作
最近在小破站学习Python入门教程 while循环和if的学习 文章目录 作业提示 一.思路与思考 二.敲代码步骤 1.引入库 2.读入数据 总结 作业提示 通过使用while和if函数制作猜年龄游 ...
- Unity 使用UGUI制作连连看小游戏
@[TOC]Unity UGUI 制作连连看那点儿事 前言 从事unity行业,仿真方向也3年有余了,从来没有尝试过自己写点什么,面对生活的各种压力人的情绪可能会产生各种波动,随着年龄的增长,人的想法 ...
- python连连看小游戏_利用Python制作一个连连看小游戏,边学边玩!
导语 今天我们将制作一个连连看小游戏,让我们愉快地开始吧~ 开发工具 Python版本:3.6.4 相关模块: pygame模块: 以及一些Python自带的模块 环境搭建 安装Python并添加到环 ...
- python拼图_利用python制作拼图小游戏的全过程
开发工具 Python版本:3.6.4 相关模块: pygame模块: 以及一些Python自带的模块 关注公众号:Python学习指南,回复"拼图"即可获取源码 环境搭建 安装P ...
- python剪刀石头布小游戏源码下载_Python Tkinter实现剪刀石头布小游戏
Python Tkinter实现剪刀石头布小游戏 发布时间:2020-10-26 14:56:52 来源:亿速云 阅读:67 作者:Leah 本篇文章给大家分享的是有关Python Tkinter实现 ...
- python实现剪刀石头布_用Python Tkinter实现剪刀石头布小游戏的方法
用Python Tkinter实现剪刀石头布小游戏的方法 发布时间:2020-12-07 10:38:11 来源:亿速云 阅读:90 作者:小新 这篇文章将为大家详细讲解有关用Python Tkint ...
- python五子棋游戏from tkinter import_Python tkinter制作单机五子棋游戏
本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 以下文章来源于Python家庭,作者Python家庭 实战项目:使用Python ...
- matlab制作打地鼠游戏,Python制作打地鼠小游戏
原标题:Python制作打地鼠小游戏 导语 大家好,欢迎来到 Crossin的编程教室 ! 打地鼠游戏相信大家都知道,这里就不多介绍了,反正就是不停地拿锤子打洞里钻出来的地鼠呗~ 今天就给大家分享一个 ...
最新文章
- 2014计算机三级网络技术,2014计算机三级网络技术综合题解题思路
- 机器学习理论《统计学习方法》学习笔记:第十章 隐马尔可夫模型(HMM)
- nhibernate3 linq的的select 操作
- 团队作业-Beta冲刺(周三)
- Java程序员都要懂得知识点:原始数据类型
- 四面八方的意思是什么,怎么用四面八方造句?
- 浅析VB For Each.Next语句
- java学习电子书_Java学习指南(第4版)(上册) 中文完整pdf扫描版[179MB]
- IP子网划分概念:IP地址,子网和网关配置——Vecloud
- 童年修复系列-SNES芯片组介绍及FPGA实现
- 第十一篇,看门狗定时器编程
- 机器学习:蒙特卡罗方法
- OllyDbg 常用命令 【Pray收集整理】
- 2021年中国互联网企业100强(附名单)
- 苹果xR为什么显示不了服务器,苹果手机iPhone XR无法连接到APP Store的解决方法
- Android 解决程序启动时的黑屏问题
- 群晖java安装失败_群晖NAS安装Jenkins
- 怎么改变计算机的黑屏,电脑调整分辨率最大会黑屏的解决方法
- Unity中国象棋(一)——初始化棋子
- Android端 WebP图片压缩与传输的一点探索