'太好玩了,我用Python寫了個火影忍者版的連連看'

"

暑假馬上就要結束了,在暑假即將走向尾聲的時候,小編特地為大家準備了一款小遊戲——連連看。希望通過這一款小遊戲為大家放鬆身心,迎接新學年的到來。

連連看想必大家都玩過,相同的圖片,可以連在一起消掉,但前提是圖片連接的路徑要是直線,或者是“L”形(連接線有一個拐彎)或者是類似於“U”形(連接線有兩個拐彎)。那麼程序是如何實現的呢,先看一下整個的設計思路:

"

暑假馬上就要結束了,在暑假即將走向尾聲的時候,小編特地為大家準備了一款小遊戲——連連看。希望通過這一款小遊戲為大家放鬆身心,迎接新學年的到來。

連連看想必大家都玩過,相同的圖片,可以連在一起消掉,但前提是圖片連接的路徑要是直線,或者是“L”形(連接線有一個拐彎)或者是類似於“U”形(連接線有兩個拐彎)。那麼程序是如何實現的呢,先看一下整個的設計思路:

太好玩了,我用Python寫了個火影忍者版的連連看

01.

遊戲的界面設計

1).首先是對於整體界面的設計,如下圖所示:

"

暑假馬上就要結束了,在暑假即將走向尾聲的時候,小編特地為大家準備了一款小遊戲——連連看。希望通過這一款小遊戲為大家放鬆身心,迎接新學年的到來。

連連看想必大家都玩過,相同的圖片,可以連在一起消掉,但前提是圖片連接的路徑要是直線,或者是“L”形(連接線有一個拐彎)或者是類似於“U”形(連接線有兩個拐彎)。那麼程序是如何實現的呢,先看一下整個的設計思路:

太好玩了,我用Python寫了個火影忍者版的連連看

01.

遊戲的界面設計

1).首先是對於整體界面的設計,如下圖所示:

太好玩了,我用Python寫了個火影忍者版的連連看

大家運行程序後,會首先彈出選擇框,是否從第一關開始,選擇第一關後,點擊遊戲便可以開始遊戲。我們設計了一個菜單,點擊遊戲/開始遊戲即可!

02.

把火影忍者的人物放畫布

接下來就是將遊戲人物放到畫布上去,這裡我們選擇了我最喜歡的火影忍者的頭像,哈哈!

1).首先程序規定了每一個種類圖片

圖片所能出現的次數為4次,然後如果我們想實現一個8x8大小的圖片地圖,那麼就一共有8x8/4=16種類型的圖片可以出現。我們將每一種類型圖片編碼為一個數字,例如上圖中鳴人的編號為0,小櫻的編號為1。然後在對應到圖片上去,所以就會得到16(種類)x4(每個種類的圖片數量)=64個圖片,如下圖所示:

"

暑假馬上就要結束了,在暑假即將走向尾聲的時候,小編特地為大家準備了一款小遊戲——連連看。希望通過這一款小遊戲為大家放鬆身心,迎接新學年的到來。

連連看想必大家都玩過,相同的圖片,可以連在一起消掉,但前提是圖片連接的路徑要是直線,或者是“L”形(連接線有一個拐彎)或者是類似於“U”形(連接線有兩個拐彎)。那麼程序是如何實現的呢,先看一下整個的設計思路:

太好玩了,我用Python寫了個火影忍者版的連連看

01.

遊戲的界面設計

1).首先是對於整體界面的設計,如下圖所示:

太好玩了,我用Python寫了個火影忍者版的連連看

大家運行程序後,會首先彈出選擇框,是否從第一關開始,選擇第一關後,點擊遊戲便可以開始遊戲。我們設計了一個菜單,點擊遊戲/開始遊戲即可!

02.

把火影忍者的人物放畫布

接下來就是將遊戲人物放到畫布上去,這裡我們選擇了我最喜歡的火影忍者的頭像,哈哈!

1).首先程序規定了每一個種類圖片

圖片所能出現的次數為4次,然後如果我們想實現一個8x8大小的圖片地圖,那麼就一共有8x8/4=16種類型的圖片可以出現。我們將每一種類型圖片編碼為一個數字,例如上圖中鳴人的編號為0,小櫻的編號為1。然後在對應到圖片上去,所以就會得到16(種類)x4(每個種類的圖片數量)=64個圖片,如下圖所示:

太好玩了,我用Python寫了個火影忍者版的連連看

2).然後,我們將上述的圖片打亂

按照畫布上的位置分別放置圖片,就得到了連連看的圖片界面。

"

暑假馬上就要結束了,在暑假即將走向尾聲的時候,小編特地為大家準備了一款小遊戲——連連看。希望通過這一款小遊戲為大家放鬆身心,迎接新學年的到來。

連連看想必大家都玩過,相同的圖片,可以連在一起消掉,但前提是圖片連接的路徑要是直線,或者是“L”形(連接線有一個拐彎)或者是類似於“U”形(連接線有兩個拐彎)。那麼程序是如何實現的呢,先看一下整個的設計思路:

太好玩了,我用Python寫了個火影忍者版的連連看

01.

遊戲的界面設計

1).首先是對於整體界面的設計,如下圖所示:

太好玩了,我用Python寫了個火影忍者版的連連看

大家運行程序後,會首先彈出選擇框,是否從第一關開始,選擇第一關後,點擊遊戲便可以開始遊戲。我們設計了一個菜單,點擊遊戲/開始遊戲即可!

02.

把火影忍者的人物放畫布

接下來就是將遊戲人物放到畫布上去,這裡我們選擇了我最喜歡的火影忍者的頭像,哈哈!

1).首先程序規定了每一個種類圖片

圖片所能出現的次數為4次,然後如果我們想實現一個8x8大小的圖片地圖,那麼就一共有8x8/4=16種類型的圖片可以出現。我們將每一種類型圖片編碼為一個數字,例如上圖中鳴人的編號為0,小櫻的編號為1。然後在對應到圖片上去,所以就會得到16(種類)x4(每個種類的圖片數量)=64個圖片,如下圖所示:

太好玩了,我用Python寫了個火影忍者版的連連看

2).然後,我們將上述的圖片打亂

按照畫布上的位置分別放置圖片,就得到了連連看的圖片界面。

太好玩了,我用Python寫了個火影忍者版的連連看

3).部分代碼如下圖所示

"

暑假馬上就要結束了,在暑假即將走向尾聲的時候,小編特地為大家準備了一款小遊戲——連連看。希望通過這一款小遊戲為大家放鬆身心,迎接新學年的到來。

連連看想必大家都玩過,相同的圖片,可以連在一起消掉,但前提是圖片連接的路徑要是直線,或者是“L”形(連接線有一個拐彎)或者是類似於“U”形(連接線有兩個拐彎)。那麼程序是如何實現的呢,先看一下整個的設計思路:

太好玩了,我用Python寫了個火影忍者版的連連看

01.

遊戲的界面設計

1).首先是對於整體界面的設計,如下圖所示:

太好玩了,我用Python寫了個火影忍者版的連連看

大家運行程序後,會首先彈出選擇框,是否從第一關開始,選擇第一關後,點擊遊戲便可以開始遊戲。我們設計了一個菜單,點擊遊戲/開始遊戲即可!

02.

把火影忍者的人物放畫布

接下來就是將遊戲人物放到畫布上去,這裡我們選擇了我最喜歡的火影忍者的頭像,哈哈!

1).首先程序規定了每一個種類圖片

圖片所能出現的次數為4次,然後如果我們想實現一個8x8大小的圖片地圖,那麼就一共有8x8/4=16種類型的圖片可以出現。我們將每一種類型圖片編碼為一個數字,例如上圖中鳴人的編號為0,小櫻的編號為1。然後在對應到圖片上去,所以就會得到16(種類)x4(每個種類的圖片數量)=64個圖片,如下圖所示:

太好玩了,我用Python寫了個火影忍者版的連連看

2).然後,我們將上述的圖片打亂

按照畫布上的位置分別放置圖片,就得到了連連看的圖片界面。

太好玩了,我用Python寫了個火影忍者版的連連看

3).部分代碼如下圖所示

太好玩了,我用Python寫了個火影忍者版的連連看

該函數是對畫布圖片進行一個初始化:

  • 首先,是將每一個類別的小圖片都添加self.num張,形成一個self.picsKind * self.num大小的一維數組;
  • 然後,將小圖片的索引順序進行打亂;
  • 最後,是將小圖片的索引轉化為一個二維數組,也就是呈現給大家的一個正方形的界面。
"

暑假馬上就要結束了,在暑假即將走向尾聲的時候,小編特地為大家準備了一款小遊戲——連連看。希望通過這一款小遊戲為大家放鬆身心,迎接新學年的到來。

連連看想必大家都玩過,相同的圖片,可以連在一起消掉,但前提是圖片連接的路徑要是直線,或者是“L”形(連接線有一個拐彎)或者是類似於“U”形(連接線有兩個拐彎)。那麼程序是如何實現的呢,先看一下整個的設計思路:

太好玩了,我用Python寫了個火影忍者版的連連看

01.

遊戲的界面設計

1).首先是對於整體界面的設計,如下圖所示:

太好玩了,我用Python寫了個火影忍者版的連連看

大家運行程序後,會首先彈出選擇框,是否從第一關開始,選擇第一關後,點擊遊戲便可以開始遊戲。我們設計了一個菜單,點擊遊戲/開始遊戲即可!

02.

把火影忍者的人物放畫布

接下來就是將遊戲人物放到畫布上去,這裡我們選擇了我最喜歡的火影忍者的頭像,哈哈!

1).首先程序規定了每一個種類圖片

圖片所能出現的次數為4次,然後如果我們想實現一個8x8大小的圖片地圖,那麼就一共有8x8/4=16種類型的圖片可以出現。我們將每一種類型圖片編碼為一個數字,例如上圖中鳴人的編號為0,小櫻的編號為1。然後在對應到圖片上去,所以就會得到16(種類)x4(每個種類的圖片數量)=64個圖片,如下圖所示:

太好玩了,我用Python寫了個火影忍者版的連連看

2).然後,我們將上述的圖片打亂

按照畫布上的位置分別放置圖片,就得到了連連看的圖片界面。

太好玩了,我用Python寫了個火影忍者版的連連看

3).部分代碼如下圖所示

太好玩了,我用Python寫了個火影忍者版的連連看

該函數是對畫布圖片進行一個初始化:

  • 首先,是將每一個類別的小圖片都添加self.num張,形成一個self.picsKind * self.num大小的一維數組;
  • 然後,將小圖片的索引順序進行打亂;
  • 最後,是將小圖片的索引轉化為一個二維數組,也就是呈現給大家的一個正方形的界面。
太好玩了,我用Python寫了個火影忍者版的連連看

這裡是將我們存放到self.pics裡面的圖片,通過函數self. get_left_top_point函數來獲得其對應的座標,並按照此座標將圖片放置到畫布的相應位置。

其中有一點應用的很是巧妙,就是利用索引來作為判斷是否是一類圖片的標誌(後面有代碼示例的),接下來就是進行圖片的消除,如下圖所示。

"

暑假馬上就要結束了,在暑假即將走向尾聲的時候,小編特地為大家準備了一款小遊戲——連連看。希望通過這一款小遊戲為大家放鬆身心,迎接新學年的到來。

連連看想必大家都玩過,相同的圖片,可以連在一起消掉,但前提是圖片連接的路徑要是直線,或者是“L”形(連接線有一個拐彎)或者是類似於“U”形(連接線有兩個拐彎)。那麼程序是如何實現的呢,先看一下整個的設計思路:

太好玩了,我用Python寫了個火影忍者版的連連看

01.

遊戲的界面設計

1).首先是對於整體界面的設計,如下圖所示:

太好玩了,我用Python寫了個火影忍者版的連連看

大家運行程序後,會首先彈出選擇框,是否從第一關開始,選擇第一關後,點擊遊戲便可以開始遊戲。我們設計了一個菜單,點擊遊戲/開始遊戲即可!

02.

把火影忍者的人物放畫布

接下來就是將遊戲人物放到畫布上去,這裡我們選擇了我最喜歡的火影忍者的頭像,哈哈!

1).首先程序規定了每一個種類圖片

圖片所能出現的次數為4次,然後如果我們想實現一個8x8大小的圖片地圖,那麼就一共有8x8/4=16種類型的圖片可以出現。我們將每一種類型圖片編碼為一個數字,例如上圖中鳴人的編號為0,小櫻的編號為1。然後在對應到圖片上去,所以就會得到16(種類)x4(每個種類的圖片數量)=64個圖片,如下圖所示:

太好玩了,我用Python寫了個火影忍者版的連連看

2).然後,我們將上述的圖片打亂

按照畫布上的位置分別放置圖片,就得到了連連看的圖片界面。

太好玩了,我用Python寫了個火影忍者版的連連看

3).部分代碼如下圖所示

太好玩了,我用Python寫了個火影忍者版的連連看

該函數是對畫布圖片進行一個初始化:

  • 首先,是將每一個類別的小圖片都添加self.num張,形成一個self.picsKind * self.num大小的一維數組;
  • 然後,將小圖片的索引順序進行打亂;
  • 最後,是將小圖片的索引轉化為一個二維數組,也就是呈現給大家的一個正方形的界面。
太好玩了,我用Python寫了個火影忍者版的連連看

這裡是將我們存放到self.pics裡面的圖片,通過函數self. get_left_top_point函數來獲得其對應的座標,並按照此座標將圖片放置到畫布的相應位置。

其中有一點應用的很是巧妙,就是利用索引來作為判斷是否是一類圖片的標誌(後面有代碼示例的),接下來就是進行圖片的消除,如下圖所示。

太好玩了,我用Python寫了個火影忍者版的連連看

03.

核心算法解釋

敲黑板劃重點來了,只有符合上述三種情況的圖片我們才能夠消除,那麼程序如何判斷二者是否符合被消除的條件呢?

  • 我們以直線連接為例。上圖中可以直線連接的兩個佐助橫縱座標分別為(2,3)和(3,3),那麼我們就判斷他們x座標(直線連接,橫縱座標肯定有一個相等,就不用判斷相等的座標了);
  • 如果他們中間沒有其他的圖片,那麼他們就可以被連接然後消掉,否則就不可以;

例如(4,4)和(4,6)的小櫻之間有一個其他人的存在,他們就不能被連接,其他的情況也是類似判斷,部分代碼如下圖所示:

"

暑假馬上就要結束了,在暑假即將走向尾聲的時候,小編特地為大家準備了一款小遊戲——連連看。希望通過這一款小遊戲為大家放鬆身心,迎接新學年的到來。

連連看想必大家都玩過,相同的圖片,可以連在一起消掉,但前提是圖片連接的路徑要是直線,或者是“L”形(連接線有一個拐彎)或者是類似於“U”形(連接線有兩個拐彎)。那麼程序是如何實現的呢,先看一下整個的設計思路:

太好玩了,我用Python寫了個火影忍者版的連連看

01.

遊戲的界面設計

1).首先是對於整體界面的設計,如下圖所示:

太好玩了,我用Python寫了個火影忍者版的連連看

大家運行程序後,會首先彈出選擇框,是否從第一關開始,選擇第一關後,點擊遊戲便可以開始遊戲。我們設計了一個菜單,點擊遊戲/開始遊戲即可!

02.

把火影忍者的人物放畫布

接下來就是將遊戲人物放到畫布上去,這裡我們選擇了我最喜歡的火影忍者的頭像,哈哈!

1).首先程序規定了每一個種類圖片

圖片所能出現的次數為4次,然後如果我們想實現一個8x8大小的圖片地圖,那麼就一共有8x8/4=16種類型的圖片可以出現。我們將每一種類型圖片編碼為一個數字,例如上圖中鳴人的編號為0,小櫻的編號為1。然後在對應到圖片上去,所以就會得到16(種類)x4(每個種類的圖片數量)=64個圖片,如下圖所示:

太好玩了,我用Python寫了個火影忍者版的連連看

2).然後,我們將上述的圖片打亂

按照畫布上的位置分別放置圖片,就得到了連連看的圖片界面。

太好玩了,我用Python寫了個火影忍者版的連連看

3).部分代碼如下圖所示

太好玩了,我用Python寫了個火影忍者版的連連看

該函數是對畫布圖片進行一個初始化:

  • 首先,是將每一個類別的小圖片都添加self.num張,形成一個self.picsKind * self.num大小的一維數組;
  • 然後,將小圖片的索引順序進行打亂;
  • 最後,是將小圖片的索引轉化為一個二維數組,也就是呈現給大家的一個正方形的界面。
太好玩了,我用Python寫了個火影忍者版的連連看

這裡是將我們存放到self.pics裡面的圖片,通過函數self. get_left_top_point函數來獲得其對應的座標,並按照此座標將圖片放置到畫布的相應位置。

其中有一點應用的很是巧妙,就是利用索引來作為判斷是否是一類圖片的標誌(後面有代碼示例的),接下來就是進行圖片的消除,如下圖所示。

太好玩了,我用Python寫了個火影忍者版的連連看

03.

核心算法解釋

敲黑板劃重點來了,只有符合上述三種情況的圖片我們才能夠消除,那麼程序如何判斷二者是否符合被消除的條件呢?

  • 我們以直線連接為例。上圖中可以直線連接的兩個佐助橫縱座標分別為(2,3)和(3,3),那麼我們就判斷他們x座標(直線連接,橫縱座標肯定有一個相等,就不用判斷相等的座標了);
  • 如果他們中間沒有其他的圖片,那麼他們就可以被連接然後消掉,否則就不可以;

例如(4,4)和(4,6)的小櫻之間有一個其他人的存在,他們就不能被連接,其他的情況也是類似判斷,部分代碼如下圖所示:

太好玩了,我用Python寫了個火影忍者版的連連看

上面的3中連接方法(直連,L型連接和U型連接)。當我們判斷二者可以連接後,利用tkinter的畫布中的delete函數,便可以將圖片刪掉。部分程序如下所示:

"

暑假馬上就要結束了,在暑假即將走向尾聲的時候,小編特地為大家準備了一款小遊戲——連連看。希望通過這一款小遊戲為大家放鬆身心,迎接新學年的到來。

連連看想必大家都玩過,相同的圖片,可以連在一起消掉,但前提是圖片連接的路徑要是直線,或者是“L”形(連接線有一個拐彎)或者是類似於“U”形(連接線有兩個拐彎)。那麼程序是如何實現的呢,先看一下整個的設計思路:

太好玩了,我用Python寫了個火影忍者版的連連看

01.

遊戲的界面設計

1).首先是對於整體界面的設計,如下圖所示:

太好玩了,我用Python寫了個火影忍者版的連連看

大家運行程序後,會首先彈出選擇框,是否從第一關開始,選擇第一關後,點擊遊戲便可以開始遊戲。我們設計了一個菜單,點擊遊戲/開始遊戲即可!

02.

把火影忍者的人物放畫布

接下來就是將遊戲人物放到畫布上去,這裡我們選擇了我最喜歡的火影忍者的頭像,哈哈!

1).首先程序規定了每一個種類圖片

圖片所能出現的次數為4次,然後如果我們想實現一個8x8大小的圖片地圖,那麼就一共有8x8/4=16種類型的圖片可以出現。我們將每一種類型圖片編碼為一個數字,例如上圖中鳴人的編號為0,小櫻的編號為1。然後在對應到圖片上去,所以就會得到16(種類)x4(每個種類的圖片數量)=64個圖片,如下圖所示:

太好玩了,我用Python寫了個火影忍者版的連連看

2).然後,我們將上述的圖片打亂

按照畫布上的位置分別放置圖片,就得到了連連看的圖片界面。

太好玩了,我用Python寫了個火影忍者版的連連看

3).部分代碼如下圖所示

太好玩了,我用Python寫了個火影忍者版的連連看

該函數是對畫布圖片進行一個初始化:

  • 首先,是將每一個類別的小圖片都添加self.num張,形成一個self.picsKind * self.num大小的一維數組;
  • 然後,將小圖片的索引順序進行打亂;
  • 最後,是將小圖片的索引轉化為一個二維數組,也就是呈現給大家的一個正方形的界面。
太好玩了,我用Python寫了個火影忍者版的連連看

這裡是將我們存放到self.pics裡面的圖片,通過函數self. get_left_top_point函數來獲得其對應的座標,並按照此座標將圖片放置到畫布的相應位置。

其中有一點應用的很是巧妙,就是利用索引來作為判斷是否是一類圖片的標誌(後面有代碼示例的),接下來就是進行圖片的消除,如下圖所示。

太好玩了,我用Python寫了個火影忍者版的連連看

03.

核心算法解釋

敲黑板劃重點來了,只有符合上述三種情況的圖片我們才能夠消除,那麼程序如何判斷二者是否符合被消除的條件呢?

  • 我們以直線連接為例。上圖中可以直線連接的兩個佐助橫縱座標分別為(2,3)和(3,3),那麼我們就判斷他們x座標(直線連接,橫縱座標肯定有一個相等,就不用判斷相等的座標了);
  • 如果他們中間沒有其他的圖片,那麼他們就可以被連接然後消掉,否則就不可以;

例如(4,4)和(4,6)的小櫻之間有一個其他人的存在,他們就不能被連接,其他的情況也是類似判斷,部分代碼如下圖所示:

太好玩了,我用Python寫了個火影忍者版的連連看

上面的3中連接方法(直連,L型連接和U型連接)。當我們判斷二者可以連接後,利用tkinter的畫布中的delete函數,便可以將圖片刪掉。部分程序如下所示:

太好玩了,我用Python寫了個火影忍者版的連連看

當我們將所有的圖片都消掉後,程序便會彈出提示框,祝賀我們闖關成功。下面,小編就為大家帶來視頻展示,看看小編的功力如何。

(連連看運行視頻)

怎麼樣看完視頻,是不是感覺還不錯,唯一美中不足的就是沒有加入聲音。大家如果有興趣的可以拿著完整的源碼改改,看看能否優化和加入聲音,這樣效果更佳!

連連看源碼:

import random, sys

import tkinter as tk

import tkinter.messagebox

from tkinter.messagebox import askyesno

from PIL import Image, ImageTk

class MainWindow():

def __init__(self):

self.title = "連連看遊戲"

self.windowWidth = 700

self.windowWidth = 700

self.windowHeigth = 500

self.root = tk.Tk()

self.root.title(self.title)

self.CWindow(self.windowWidth, self.windowHeigth)

self.root.minsize(460, 460)

self.pics = []

self.primary = askyesno(title='選擇第一關', message='第一關(yes) 第二關(no)')

self.Interface()

if self.primary == False:

self.picsize = 10 # 每行每列的圖片數量

self.num = 4

self.picWidth = 40 # 小圖片的寬

self.picHeight = 40 # 小圖片的寬

else:

self.picsize = 8 # 每行每列的圖片數量

self.num = 4

self.picWidth = 50 # 小圖片的寬

self.picHeight = 50 # 小圖片的寬

self.picsKind = self.picsize * self.picsize / self.num # 小圖片種類數量

self.picsmap = [] # 遊戲地圖

self.margin = 25

self.firstClick = True

self.start = False

self.lastPoint = None

self.none = -1

self.noLink = 0

self.lineLink = 1

self.L_Link = 2

self.U_link = 3

self.put_pic_in_pics()

self.root.mainloop()

def Interface(self):

self.menu = tk.Menu(self.root, bg="lightgrey", fg="black")

self.list_menu = tk.Menu(self.menu, tearoff=0, bg="lightgrey", fg="black")

self.list_menu.add_command(label="開始遊戲", command=self.game_start, accelerator="Ctrl+N")

self.list_menu.add_command(label="退出", command=self.game_stop, accelerator="Ctrl+M")

self.menu.add_cascade(label="遊戲", menu=self.list_menu)

self.root.configure(menu=self.menu)

self.canvas = tk.Canvas(self.root, bg='white', width=450, height=450)

self.canvas.pack(side=tk.TOP, pady=5)

self.canvas.bind('<Button-1>', self.clickCanvas)

def CWindow(self, w, h): # 設置屏幕的位置

swidth = self.root.winfo_screenwidth()

sheight = self.root.winfo_screenheight()

size = '%dx%d+%d+%d' % (w, h, (swidth - w) / 2, (sheight - h) / 2)

self.root.geometry(size)

def game_start(self):

self.ini_game()

self.put_pics_on_canvas()

self.start = True

def game_stop(self):

sys.exit()

def clickCanvas(self, event):

if self.start:

point = self.get_index_coord(Point(event.x, event.y)) # 返回鼠標點擊的位置到底是哪一幅圖片。例如[0,0]代表左上角第一幅

# 有效點擊座標

if point.isUserful() and not self.check_none(point):

if self.firstClick: # 如果是第一次點擊圖片,那麼就畫一個紅框

self.draw_red_rectangle(point)

self.firstClick = False

self.lastPoint = point

else:

if self.lastPoint.isEqual(point): # 如果連續點擊同一小圖片兩次的話,就將話得紅框去掉

self.firstClick = True

self.canvas.delete("rectRedOne")

else:

linkType = self.get_link_type(self.lastPoint, point)

if linkType['type'] != self.noLink:

# TODO Animation

self.delete_linked_points(self.lastPoint, point)

self.canvas.delete("rectRedOne")

self.firstClick = True

if self.check_end():

tk.messagebox.showinfo("You Win!", "Tip")

self.start = False

else:

self.lastPoint = point

self.canvas.delete("rectRedOne")

self.draw_red_rectangle(point)

# 判斷遊戲是否結束

def check_end(self):

for y in range(0, self.picsize):

for x in range(0, self.picsize):

if self.picsmap[y][x] != self.none:

return False

return True

def put_pic_in_pics(self): # 將小頭像放到pics數組裡面

ori_image = Image.open(r'./pic/img.png')

if self.primary == True: # 如果是第一關的話,需要將原始圖片擴大之後再進行剪裁。

ori_image = ori_image.resize((1250, 50), Image.NEAREST)

for i in range(0, int(self.picsKind)):

pic = ori_image.crop((self.picWidth * i, 0,

self.picWidth * i + self.picWidth - 1, self.picHeight - 1))

self.pics.append(ImageTk.PhotoImage(pic))

def ini_game(self): # 初始化地圖

self.picsmap = [] # 重置地圖

index1 = []

indexs = []

for i in range(0, int(self.picsKind)):

for j in range(0, self.num):

index1.append(i) # 向tmpRecords裡添加小圖片索引,每一個種類的圖片都添加self.num個

total = self.picsize * self.picsize # 總共的圖片數量

print('tmpRecords', index1)

for x in range(0, total):

index = random.randint(0, total - x - 1) # 打亂順序

indexs.append(index1[index]) # 向records裡添加小圖片的索引

del index1[index]

print('records', indexs)

print(len(indexs))

# 一維數組轉為二維,y為高維度

for y in range(0, self.picsize): # 將小圖片轉化為二維矩陣形式

for x in range(0, self.picsize):

if x == 0:

self.picsmap.append([])

self.picsmap[y].append(indexs[x + y * self.picsize])

def put_pics_on_canvas(self): # 根據地圖繪製圖像

self.canvas.delete("all")

for y in range(0, self.picsize):

for x in range(0, self.picsize):

point = self.get_left_top_point(Point(x, y)) # 獲取小圖片應該放在什麼位置(左上角的座標)

self.canvas.create_image((point.x, point.y),

image=self.pics[self.picsmap[y][x]], anchor='nw', tags='im%d%d' % (x, y)) # 將小圖片放入指定位置

def get_left_top_point(self, point): # 獲取對應矩形的左上角頂點座標

return Point(self.getx(point.x), self.gety(point.y))

def getx(self, x): # 更新x的位置

return x * self.picWidth + self.margin

def gety(self, y): # 更新y的位置

return y * self.picHeight + self.margin

def get_index_coord(self, point): # 獲取內部座標

x = -1

y = -1

for i in range(0, self.picsize):

x1 = self.getx(i)

x2 = self.getx(i + 1)

if point.x >= x1 and point.x < x2:

x = i

for j in range(0, self.picsize):

j1 = self.gety(j)

j2 = self.gety(j + 1)

if point.y >= j1 and point.y < j2:

y = j

return Point(x, y)

def draw_red_rectangle(self, point): # 選擇的區域變紅,point為內部座標

pointLT = self.get_left_top_point(point) # 獲取小圖片的左上角座標

pointRB = self.get_left_top_point(Point(point.x + 1, point.y + 1)) # 在小圖片的左上角座標上(x,y)分別加一

self.canvas.create_rectangle(pointLT.x, pointLT.y,

pointRB.x - 1, pointRB.y - 1, outline='red', tags="rectRedOne") # 以(x+1,y+1)為左上角座標,畫圓

def delete_linked_points(self, p1, p2): # 消除連通的兩個塊

self.picsmap[p1.y][p1.x] = self.none

self.picsmap[p2.y][p2.x] = self.none

self.canvas.delete('im%d%d' % (p1.x, p1.y))

self.canvas.delete('im%d%d' % (p2.x, p2.y))

def check_none(self, point): # 判斷圖上該點是否為空

if self.picsmap[point.y][point.x] == self.none:

return True

else:

return False

def get_link_type(self, p1, p2): # 判斷兩個點連通類型

# 首先判斷兩個方塊中圖片是否相同

if self.picsmap[p1.y][p1.x] != self.picsmap[p2.y][p2.x]: # 這裡運用的很巧妙,利用數字索引來判斷是否為同一類型圖片。如果不是,肯定無法連接

return {'type': self.noLink}

if self.line_link_type(p1, p2):

return {

'type': self.lineLink

}

res = self.L_Link_type(p1, p2)

if res:

return {

'type': self.L_Link,

'p1': res

}

res = self.U_Link_type(p1, p2)

if res:

return {

'type': self.U_link,

'p1': res['p1'],

'p2': res['p2']

}

return {

'type': self.noLink

}

def line_link_type(self, p1, p2): # 直線相連,判斷兩幅圖的前進道路上是否有圖片阻攔。

# 水平

if p1.y == p2.y:

# 大小判斷

if p2.x < p1.x:

start = p2.x

end = p1.x

else:

start = p1.x

end = p2.x

for x in range(start + 1, end):

if self.picsmap[p1.y][x] != self.none:

return False

return True

elif p1.x == p2.x:

if p1.y > p2.y:

start = p2.y

end = p1.y

else:

start = p1.y

end = p2.y

for y in range(start + 1, end):

if self.picsmap[y][p1.x] != self.none:

return False

return True

return False

def L_Link_type(self, p1, p2): # 一個拐彎相連,類似於“L”型

corner = Point(p1.x, p2.y)

if self.line_link_type(p1, corner) and self.line_link_type(corner, p2) and self.check_none(corner):

return corner

corner = Point(p2.x, p1.y)

if self.line_link_type(p1, corner) and self.line_link_type(corner, p2) and self.check_none(corner):

return corner

def U_Link_type(self, p1, p2): # # 兩個個拐彎相連,類似於“U”型

for y in range(-1, self.picsize + 1):

corner1 = Point(p1.x, y)

corner2 = Point(p2.x, y)

if y == p1.y or y == p2.y:

continue

if y == -1 or y == self.picsize:

if self.line_link_type(p1, corner1) and self.line_link_type(corner2, p2):

return {'p1': corner1, 'p2': corner2}

else:

if self.line_link_type(p1, corner1) and self.line_link_type(corner1,

corner2) and self.line_link_type(

corner2, p2) and self.check_none(corner1) and self.check_none(corner2):

return {'p1': corner1, 'p2': corner2}

# 橫向判斷

for x in range(-1, self.picsize + 1):

corner1 = Point(x, p1.y)

corner2 = Point(x, p2.y)

if x == p1.x or x == p2.x:

continue

if x == -1 or x == self.picsize:

if self.line_link_type(p1, corner1) and self.line_link_type(corner2, p2):

return {'p1': corner1, 'p2': corner2}

else:

if self.line_link_type(p1, corner1) and self.line_link_type(corner1,

corner2) and self.line_link_type(

corner2, p2) and self.check_none(corner1) and self.check_none(corner2):

return {'p1': corner1, 'p2': corner2}

class Point():

def __init__(self, x, y):

self.x = x

self.y = y

def isUserful(self): # 座標x和y都大於0

if self.x >= 0 and self.y >= 0:

return True

else:

return False

def isEqual(self, point): # 判斷兩個點是否相同

if self.x == point.x and self.y == point.y:

return True

else:

return False

def clone(self): # 克隆一份對象

return Point(self.x, self.y)

def changeTo(self, point): # 改為另一個對象

self.x = point.x

self.y = point.y

if __name__ == '__main__':

MainWindow()

"

相關推薦

推薦中...