Python遊戲開發:數字華容道

Python遊戲開發:數字華容道

今年年初,新一季的《最強大腦》開播了,第一集選拔的時候大家做了一個數字遊戲,名叫《數字華容道》,當時何猷君以二十幾秒的成績奪得該項目的冠軍,看了這個遊戲之後我決定要寫一個《數字華容道》的程序,過去了半年,我終於記起了這件事,今天就來實現。

數字推盤遊戲(n-puzzle)是一種智力遊戲,常見的類型有十五數字推盤遊戲和八數字推盤遊戲等。十五數字推盤遊戲的板上會有十五個方塊和一個大小相當於一個方塊的空位(供方塊移動之用),當15個數字依次排序並且最後一個格子為空位即代表挑戰成功。

本文使用 PyQt5 進行設計與實現,PyQt5 是該程序的一個呈現方式,最重要的是算法,學會了算法,完全可以使用 PyGame 或者 Tkinter 實現。

PyQt5安裝:pip install PyQt5

本文使用環境:

  • 系統:Windows 10 64位
  • Python版本:3.6

1、佈局設計

做一個簡版的數字華容道,佈局設計如圖所示:

Python遊戲開發:數字華容道

簡版數字華容道佈局

  • 圖中灰色的部分使用 QWidget 作為整個遊戲的載體;
  • 黃色部分使用 QGridLayout 作為數字方塊的佈局;
  • 紅色部分使用 QLabel 作為數字方塊。

2、算法設計

如上圖所示,本遊戲共需要15個方塊,每個方塊代表一個數字。我們可以使用 一個二維 list來存儲方塊上的數字。其實我們要創建一個 4x4 的 list 存儲 0~15 各個數字,0 代表空的位置。

2.1 創建並初始化數組

創建數組的方法:

  • 創建一個長度為16的數組,並且在對應位置上保存著 0~15 ;
  • 打亂順序
Python遊戲開發:數字華容道

2.2 移動算法

假如移動之前個數字位置如左圖所示,那麼當按下左箭頭時,會變成如右圖所示:

Python遊戲開發:數字華容道

左移

可以看到 (1, 2)(1, 3) 兩個位置上的數字互換了,即 0 和 8 互換;如果右圖所示再次按下左箭頭,那麼所有數字都不會改變,因為 數字 0 右邊沒有數了。

總結一下:如果 數字 0 所在位置為 (row, column),並且 column≠3 那麼按下左箭頭之後,(row, column) 和 (row, column+1) 位置上的數組互換,同理可得:

  • 如果 數字 0 所在位置為 (row, column),並且 column≠0 那麼按下右箭頭之後,(row, column) 和 (row, column-1) 位置上的數組互換;
  • 如果 數字 0 所在位置為 (row, column),並且 row≠3 那麼按下上箭頭之後,(row, column) 和 (row+1, column) 位置上的數組互換;
  • 如果 數字 0 所在位置為 (row, column),並且 row≠0 那麼按下下箭頭
    之後,(row, column) 和 (row-1, column) 位置上的數組互換;

將移動算法封裝成一個函數如下:

Python遊戲開發:數字華容道

2.3 是否勝利檢測算法

檢測是否勝利其實很簡單:前15個位置分別對應,最後一個為0即為勝利 ,不過為了避免不必要的計算,我們先檢測最後一個是否為 0 ,如果不為0 前面的就不用比較了。具體代碼實現如下:

Python遊戲開發:數字華容道

3、實現

下面講解所有功能模塊的實現。

3.1 框架搭建

創建 QWidget 作為整個遊戲的載體:

Python遊戲開發:數字華容道

運行結果如下圖所示:

Python遊戲開發:數字華容道

框架運行結果

Python遊戲開發:數字華容道

框架運行結果

3.2 數字方塊實現

前面已經提到,用一個二維數組來存放 0~16 個數字,最終我們要轉換成一個數字方塊,單獨創建一個類:

Python遊戲開發:數字華容道

該類繼承自 QLablel ,初始化需要傳入一個參數 number ,number就是數字方塊上顯示的數字。

3.3 將數字轉換成方塊添加到佈局

佈局採用 QGridLayout 創建一個 4X4 的 self.gltMain,將16個 Block 添加到 self.gltMain:

Python遊戲開發:數字華容道

3.4 初始化佈局

初始化佈局包括隨機數據的產生與將數字轉換成方塊添加到佈局

Python遊戲開發:數字華容道

3.5 按鍵檢測

QWidget 有一個 keyPressEvent 事件句柄,我們只需要重新實現該方法即可:

Python遊戲開發:數字華容道

按鍵檢測到按鍵按下之後判斷該鍵值是否為 “↑↓←→”或“WSAD”,並作出相應的移動(move),移動之後刷新佈局(updatePannel),最後檢測是否完成挑戰(checkResult),如果完成挑戰,彈出提示框。如果點擊了 OK 按鈕,遊戲重新開始(onInit)。

3.6 試玩測試

至此,所有功能模塊介紹完畢,不要著急看完整代碼,我們先運行一下程序看是否還有 Bugs。

玩了幾局之後發現,並不是所有的局都能都還原,如下面這種情況:

Python遊戲開發:數字華容道

無法還原

如圖所示,1415 方塊位置反了,無論如何也還原不聊了,這種情況是隨機出現的。到底是怎麼回事呢?經過一番上網搜索,確實如果只有兩個數字的位置反了,無論如何也還原不了的。那這是由什麼造成的呢?還記得我們的二維數組是怎麼產生的吧,隨機的,也就是說可能會隨機到無法還原的情況。

如何避免這種情況呢?初始化數組時,所有的位置都是正確的數字,然後使用 move 進行移動打亂。

3.7 改進完善

由於前面已經將各個功能模塊單獨寫成了方法,因此我們只需修改 onInit 方法即可。

Python遊戲開發:數字華容道

先生成一個順序數組,裡面保存著[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0],然後轉為二維數組 blocks,再後隨即移動500次,最後添加到佈局。

4、完整代碼

Python遊戲開發:數字華容道

5、總結

在做的過程中遇到最大的坑就是

隨機數組導致無法還原。另外在做這個遊戲的時候我已經找到還原規律了,這樣在測試的時候可以做完完整測試,否則根本無法測試都挑戰成功那一步。

另外要對《最強大腦》做一下吐槽:這個項目根本就是有偏袒的,玩過的人會很快,沒有玩過的找規律的時間就很長。我在手機上玩4X4的最快還原用了 33 秒,對於該節目的冠軍(即便是玩過)很是敬仰。

  1. 代碼獲取:點擊左下角“瞭解更多”也可以獲取到源碼。
Python遊戲開發:數字華容道


分享到:


相關文章: