我的第二個(gè)Python趣味項(xiàng)目,來了!
點(diǎn)擊上方藍(lán)色字體,關(guān)注程序員zhenguo

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

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

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

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

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