上一篇文章中,我們梳理了實現簡易版 2048 遊戲的基本知識,這篇文章将介紹如何實現各個模塊。換句話說,上一次我們确定了旅行的目的地,這一次就讓我們自由暢行在山間田野。
主程序,即 game 函數按部就班地向下執行,該判斷就判斷,然後執行相應函數。首先讀取用戶輸入,第一個判斷:是否移動數字,顯然要移動數字要滿足以下條件:
- 用戶輸入小寫的 w s a d 對應上下左右
- 該移動方向上允許移動
具體來說,移動方向最前面有空間或者有連續相同的數字。可以移動則執行 move 函數,并在棋盤上生成随機數字,否則原樣輸出。
其次判斷:棋盤是否被填滿。被填滿時執行 fail 函數。
最後判斷:是否勝利。如果獲勝,打印獲勝提示。
首先是移動模塊:
basic 函數用來執行移動與碰撞的操作。move_{up,down,right,left} 函數用來實現各個方向上的 basic 函數操作。move 函數用來響應用戶指令,實現各個方向上的移動。
棋盤由 4 * 4 矩陣組成,0 代表該位置上沒有數字。basic 函數就是基于矩陣的運算,且以右移為基礎移動。
4 * 4 矩陣:
向右滑動:
每一周期分為 4 輪,每一輪操作一行(共 4 行),從最左面的元素開始執行。設置 flag 用于提示這一輪是否發生了改變,如果發生了改變,這一輪就再進行一次循環,直到 flag 保持為 0 不變。對于循環的每一個元素,如果該元素不為 0 ,若下個元素為 0,就交換當前值與下個元素的值。若下個元素與當前元素相同,則當前元素置 0 ,且下一個元素增加一倍,分數還要增加 100 分。
舉個例子:對于第一行 [2 2 0 4]
第一輪:
- 4 與 0 不交換 [2 2 0 4]
- 0 與 2 交換 [2 0 2 4]
- 0 與 2 交換 [0 2 2 4]
- flag = 1 且 score = 0
第二輪:
- 4 與 2 不交換 [0 2 2 4]
- a13 雙倍 a12 置 0 [0 0 4 4]
- 0 不變 [0 0 4 4]
- flag = 1 且 score = 100
第三輪:
- a14 雙倍 a13 置 0 [0 0 0 8]
- 不變 [0 0 0 8]
- 不變 [0 0 0 8]
- flag = 1 且 score = 100
第四輪:
- 不變
- 不變
- 不變
- flag = 0 且 score = 0
即第一輪最後輸出結果 [0 0 0 8]。
以上就是向右移動的操作,而對于其他方向上的移動其實就是在此基礎上進行矩陣的轉置與逆置操作。
# A 為 4*4 的矩陣 # 轉置操作 A.T # 逆置操作 A[::-1,::-1]
下圖為原矩陣:
向下滑動:
将原矩陣轉置得到新矩陣,新矩陣向右滑動,相當于原矩陣向下滑動,再轉置變回原矩陣。
向左滑動:
将原矩陣逆置得到新矩陣,新矩陣向右滑動,相當于原矩陣向左滑動,再逆置變回原矩陣。
向上滑動:
将原矩陣轉置加逆置得到新矩陣,新矩陣向右滑動,相當于原矩陣向上滑動,再通過轉置加逆置變回原矩陣。
接下來,我們講 choice 模塊:首先獲取值為 0 的矩陣元素的位置,并儲存在字典裡,以序号( 最大值為 count ) 為索引。其次産生 [0,count) 範圍内的随機數(随機抽取值為 0 的元素),并且産生随機數 2 或 4 (概率為 75% 與 25%)。最後将随機抽取的元素更改為生成的随機數(2 或 4)。
然後是生成分數:
首先遊戲開始時加載一次分數(曆史最高分),遊戲結束時保存最高分。每次打印棋盤前,都比較當前分數與當前最高分,并更改當前最高分數。
其次是打印模塊:
隻打印非零值。
最後是一些零碎的知識點:
首先我們要初始化程序,初次運行遊戲會在當前目錄生成 ‘out.npy’ 文件,并且儲存 0 在文本中。其次初始化棋盤,最後就可以愉快地開始遊戲了。
以上便是 python 實現 2048 遊戲的完結版,如果想獲取源代碼,在微信後台回複 2048 。
,