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 = x
self.y = y
II、定義函式
1、產生map地圖矩陣create_map()
def create_map():
global map
tmpMap = []
m=(Width)*(Height)//10
print('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--14
map[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 True
elif oneCornerLink(p1,p2):
return True
elif twoCornerLink(p1,p2):
return True
else:
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 = -1
elif p1.y < p2.y:
zf = 1
for i in range(1,absDistance + 1):
if (map[p1.x][p1.y + i * zf] == ' '):
spaceCount = spaceCount + 1
else:
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 = -1
elif p1.x < p2.x:
zf = 1
for i in range(1,absDistance + 1):
if (map[p1.x + i * zf][p1.y] == ' '):
spaceCount = spaceCount + 1
else:
break
if (spaceCount == absDistance):
print("行或者列直接連通!")
return True
else:
print('行/列不能消除!')
return False
else:
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 True
else:
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+=1
while ((checkP.y < Height) and (map[checkP.x][checkP.y] == " ")):
if (oneCornerLink(checkP,p2)):
print('下探測成功!')
LinePointStack.append(checkP)
return True
checkP.y+=1
#向上
elif(i == 1):
checkP.y-=1
while ((checkP.y > 0) and (map[checkP.x][checkP.y] == " ")):
if (oneCornerLink(checkP,p2)):
print('上探測成功!')
LinePointStack.append(checkP)
return True
checkP.y-=1
#向左
elif(i == 2):
checkP.x-=1
while ((checkP.x > 0) and (map[checkP.x][checkP.y] == " ")):
if (oneCornerLink(checkP,p2)):
print('左探測成功!')
LinePointStack.append(checkP)
return True
checkP.x-=1
#向右
elif(i == 3):
checkP.x+=1
while ((checkP.x < Height) and (map[checkP.x][checkP.y] == " ")):
if (oneCornerLink(checkP,p2)):
print('右探測成功!')
LinePointStack.append(checkP)
return True
checkP.x+=1
print("不能通過兩個折點連接")
return False
4、判斷兩個圖片是非為同一影像IsSame()
def IsSame(p1,p2):
if (map[p1.x][p1.y] == map[p2.x][p2.y]):
print("兩個圖片相同")
return True
else:
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,SecondSelectRectId
print('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 = False
delConnectLine()#清除選中方塊之間連接線
8、定義滑鼠左鍵事件代碼leftbuttonevent(event)
def leftbuttonevent(event):
timer_interval = 0.1 # 這個間隔時間太長,那么在點擊太快的話會出現誤消除現象
global Select_first,p1,p2
global firstSelectRectId,SecondSelectRectId
print ("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 = True
print('選定第一個點',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,SecondSelectRectId
global p1,p2
timer_interval = 0.2
m_nRoW=Height
m_nCol=Width
bFound = False
#第一個方塊從地圖的0位置開始
for i in range(0, m_nRoW* m_nCol):
#找到則跳出回圈
if (bFound):
break
#算出對應的虛擬行列位置
x1 = i % m_nCol
y1 = i // m_nCol
p1=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 = True
break
#找到后自動消除
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 = x
self.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 map
tmpMap = []
m=(Width)*(Height)//10
print('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--14
map[x][y]=tmpMap[x*Width+y] #將tmpmap中的資料按順序放入map形成一個10*10的矩陣
print('-----------------map[][]----------------\n',map)
#=============================================================================================================================
#=============================================連通條件判斷=====================================================================
#========================判斷兩個方塊是否可以連通============================
def IsLink (p1,p2):
if lineLink(p1,p2):
return True
elif oneCornerLink(p1,p2):
return True
elif twoCornerLink(p1,p2):
return True
else:
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 = -1
elif p1.y < p2.y:
zf = 1
for i in range(1,absDistance + 1):
if (map[p1.x][p1.y + i * zf] == ' '):
spaceCount = spaceCount + 1
else:
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 = -1
elif p1.x < p2.x:
zf = 1
for i in range(1,absDistance + 1):
if (map[p1.x + i * zf][p1.y] == ' '):
spaceCount = spaceCount + 1
else:
break
if (spaceCount == absDistance):
print("行或者列直接連通!")
return True
else:
print('行/列不能消除!')
return False
else:
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 True
else:
print("不能直角消除")
return False
#==============================兩個折點連通=================================
def twoCornerLink(p1,p2):
#從四個方向探測
for i in range(0,4):
checkP = Point(p1.x,p1.y)
#向下
if(i == 0):
checkP.y+=1
while ((checkP.y < Height) and (map[checkP.x][checkP.y] == " ")):
if (oneCornerLink(checkP,p2)):
print('下探測成功!')
LinePointStack.append(checkP)
return True
checkP.y+=1
#向上
elif(i == 1):
checkP.y-=1
while ((checkP.y > 0) and (map[checkP.x][checkP.y] == " ")):
if (oneCornerLink(checkP,p2)):
print('上探測成功!')
LinePointStack.append(checkP)
return True
checkP.y-=1
#向左
elif(i == 2):
checkP.x-=1
while ((checkP.x > 0) and (map[checkP.x][checkP.y] == " ")):
if (oneCornerLink(checkP,p2)):
print('左探測成功!')
LinePointStack.append(checkP)
return True
checkP.x-=1
#向右
elif(i == 3):
checkP.x+=1
while ((checkP.x < Height) and (map[checkP.x][checkP.y] == " ")):
if (oneCornerLink(checkP,p2)):
print('右探測成功!')
LinePointStack.append(checkP)
return True
checkP.x+=1
print("不能通過兩個折點連接")
return False
#=============================================================================================================================
#================================================判斷是非為同一影像============================================================
def IsSame(p1,p2):
if (map[p1.x][p1.y] == map[p2.x][p2.y]):
print("兩個圖片相同")
return True
else:
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,SecondSelectRectId
print('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 = False
delConnectLine()#清除選中方塊之間連接線
#=============================================================================================================================
#===============================================滑鼠左鍵事件代碼===============================================================
def leftbuttonevent(event):
timer_interval = 0.1 # 這個間隔時間太長,那么在點擊太快的話會出現誤消除現象
global Select_first,p1,p2
global firstSelectRectId,SecondSelectRectId
print ("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 = True
print('選定第一個點',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,SecondSelectRectId
global p1,p2
timer_interval = 0.2
m_nRoW=Height
m_nCol=Width
bFound = False
#第一個方塊從地圖的0位置開始
for i in range(0, m_nRoW* m_nCol):
#找到則跳出回圈
if (bFound):
break
#算出對應的虛擬行列位置
x1 = i % m_nCol
y1 = i // m_nCol
p1=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 = True
break
#找到后自動消除
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
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/260587.html
標籤:python
上一篇:JavaWeb之Servlet
下一篇:566. 重塑矩陣
