我的第二個Python趣味項目,來了!
點擊上方藍色字體,關注程序員zhenguo

今天是Python項目系列第二期,與大家一起動手制作2048游戲。
這個游戲當年風靡全球,游戲規(guī)則極其簡單,玩起來也是相當簡單,但是要想最后拼出2048,也絕非是一件容易的事。并且玩起來,也很有意思,總想一把一把的挑戰(zhàn)。
與2048游戲風格相似的是,它的代碼實現(xiàn)起來也是非常簡潔,代碼只有區(qū)區(qū)不到200行,并且是純Python,不用任何第三方包的情況下。
1 Python實現(xiàn)的2048游戲界面
我們先來一覽最終實現(xiàn)的游戲界面,順帶幫助不了解2048游戲的讀者,熟悉下它。
游戲主界面:

游戲基本規(guī)則:
鍵盤中上、下、左、右四個箭頭,對應4個漂流方向 合并。數(shù)值相等的兩個方格可以合并為1個方格,且值乘以2,如下圖左下角,兩個2方格可合并為一個4方格

合并后,最左下角就是4方格:

但是為什么它的上方又多了2方格呢?注意,這是第三個規(guī)則:
隨機2方格。發(fā)生合并操作時,會從灰色的單元格中隨機選擇一個,并創(chuàng)建出2方格 漂流。再有1個好玩的操作,我稱它為漂流,緊鄰上圖,我如果按下右箭頭,兩個左下角的4方格根據(jù)規(guī)則2首先合并為8方格。同時,所有方格整體向右漂流(沿著箭頭方向)。因為發(fā)生了合并操作,根據(jù)規(guī)則3,再生成一個2方格。因此得到了如下界面:

這就是游戲的規(guī)則,大家下載我的完整代碼后,玩耍一下后,理解規(guī)應該會更深,玩起來真的賊爽。
2 項目環(huán)境
本項目不使用任何第三方包,全都是Python自帶的模塊,且只用到2個模塊,可見2048游戲的魅力,實現(xiàn)的代碼都毫不費力。
一個模塊是Tkinter,用來做界面,還用到的隨機模塊random。
3 項目代碼講解
不到200行代碼,是個小框架。主要包括2個類:
Board Game
下面逐一介紹。
3.1 Board類
主要提供三個能力,分別對應上面的三個規(guī)則:
合并規(guī)則,對應
Board類的方法merge_grid隨機創(chuàng)建2方格,對應
Board類的方法random_cell漂流,對應
Board類的方法drifting_left
3.2 Game類
主要提供Tkinter的鍵盤消息和事件處理能力,對應方法event_handlers,比較簡單,所以主要講解Board類
merge_grid方法
編寫merge_grid方法的邏輯,假定是在按下左箭頭時,為什么這樣假定,后面我會重點分析,這是理解這套代碼的核心。基于此,合并鄰近的兩個非零相等單元格,實現(xiàn)邏輯很簡單:
????def?merge_grid(self):
????????"""
????????向左移動,合并鄰近的兩個非零相等單元格
????????:return:
????????"""
????????self.merge?=?False
????????for?i?in?range(4):
????????????for?j?in?range(3):
????????????????if?self.grid_cell[i][j]?==?self.grid_cell[i][j?+?1]?and?self.grid_cell[i][j]?!=?0:
????????????????????self.grid_cell[i][j]?*=?2
????????????????????self.grid_cell[i][j?+?1]?=?0
????????????????????self.score?+=?self.grid_cell[i][j]
????????????????????self.merge?=?True
random_cell方法
實現(xiàn)random_cell方法就更簡單了,隨機從灰色(沒有數(shù)字的方格)方格中,挑選一個,并賦值為2就行:
????def?random_cell(self):
????????"""
????????從零單元格中隨機產(chǎn)生一個2號單元格
????????:return:
????????"""
????????i,?j?=?random.choice([(i,?j)?for?i?in?range(4)?for?j?in?range(4)?if?self.grid_cell[i][j]?==?0])
????????self.grid_cell[i][j]?=?2
drifting_left方法
實現(xiàn)漂流drifting_left方法,使用的是最基本的快慢指針,cnt是慢指針,j是快指針。
????def?drifting_left(self):
????????"""
????????向左偏流,消除0方格
????????:return:
????????"""
????????self.compress?=?False
????????temp?=?[[0]?*?4?for?_?in?range(4)]
????????for?i?in?range(4):
????????????# cnt:慢指針,j:?快指針
????????????cnt?=?0
????????????for?j?in?range(4):
????????????????if?self.grid_cell[i][j]?!=?0:
????????????????????temp[i][cnt]?=?self.grid_cell[i][j]
????????????????????if?cnt?!=?j:
????????????????????????self.compress?=?True
????????????????????cnt?+=?1
????????self.grid_cell?=?temp
3.3 代碼核心
2048游戲會有4個漂流方向,分別為上、下、左、右。
而上面代碼,假定漂流是向左,并基于此編寫了向左漂流的邏輯。
這正是此套代碼實現(xiàn)的高明之處,其他上、下、右三方向的漂流,經(jīng)過reverse(反轉)或transpose(轉秩)后,都可以轉成向左漂流的邏輯。這兩個中間操作也都在Board類里提供了。
比如,實現(xiàn)向右漂流時,先執(zhí)行一次reverse,然后執(zhí)行drifting_left,再執(zhí)行一次reverse,就實現(xiàn)了右漂。
實現(xiàn)上漂時,先轉秩,再左漂,再轉秩。
這個變化思路,大家紙上畫一畫,一看便知。
還是有疑問的,留言區(qū)交流。
4 項目代碼講解
上面完整py代碼文件,在我的公眾號后臺回復:c,即可下載
同時過往或后面的Python項目代碼,我也會同步到這個文件夾中。
不用打賞,點個贊或在看
就心滿意足了
對應關鍵詞下載