如何讓 Emacs 俄羅斯方塊變得更難
你知道嗎,Emacs 捆綁了一個俄羅斯方塊的實現?只需要輸入 M-x tetris
就行了。
在對文字編輯器的討論中,Emacs 鼓吹者經常提到這一點。“沒錯,但是你那個編輯器能執行俄羅斯方塊嗎?”我很好奇,這會讓大家相信 Emacs 更優秀嗎?比如,為什麼有人會關心他們是否可以在文字編輯器中玩遊戲呢?“沒錯,但是你那臺吸塵器能播放 mp3 嗎?”
有人說,俄羅斯方塊總是很有趣的。像 Emacs 中的所有東西一樣,它的原始碼是開放的,易於檢查和修改,因此 我們可以使它變得更加有趣。所謂更加有趣,我的意思是更難。
讓遊戲變得更難的一個最簡單的方法就是“隱藏下一個塊預覽”。你無法在知道下一個塊會填滿空間的情況下有意地將 S/Z 塊放在一個危險的位置——你必須碰碰運氣,希望出現最好的情況。下面是沒有預覽的情況(如你所見,沒有預覽,我做出的某些選擇帶來了“可怕的後果”):
預覽框由一個名為 tetris-draw-next-shape
1 的函式設定:
(defun tetris-draw-next-shape ()
(dotimes (x 4)
(dotimes (y 4)
(gamegrid-set-cell (+ tetris-next-x x)
(+ tetris-next-y y)
tetris-blank)))
(dotimes (i 4)
(let ((tetris-shape tetris-next-shape)
(tetris-rot 0))
(gamegrid-set-cell (+ tetris-next-x
(aref (tetris-get-shape-cell i) 0))
(+ tetris-next-y
(aref (tetris-get-shape-cell i) 1))
tetris-shape))))
首先,我們引入一個標誌,決定是否允許顯示下一個預覽塊 2:
(defvar tetris-preview-next-shape nil
"When non-nil, show the next block the preview box.")
現在的問題是,我們如何才能讓 tetris-draw-next-shape
遵從這個標誌?最明顯的方法是重新定義它:
(defun tetris-draw-next-shape ()
(when tetris-preview-next-shape
;; existing tetris-draw-next-shape logic
))
但這不是理想的解決方案。同一個函式有兩個定義,這很容易引起混淆,如果上游版本發生變化,我們必須維護修改後的定義。
一個更好的方法是使用 advice。Emacs 的 advice 類似於 Python 裝飾器,但是更加靈活,因為 advice 可以從任何地方新增到函式中。這意味著我們可以修改函式而不影響原始的原始檔。
有很多不同的方法使用 Emacs advice(檢視手冊),但是這裡我們只使用 advice-add
函式和 :around
標誌。advice 函式將原始函式作為引數,原始函式可能執行也可能不執行。我們這裡,我們讓原始函式只有在預覽標誌是非空的情況下才能執行:
(defun tetris-maybe-draw-next-shape (tetris-draw-next-shape)
(when tetris-preview-next-shape
(funcall tetris-draw-next-shape)))
(advice-add 'tetris-draw-next-shape :around #'tetris-maybe-draw-next-shape)
這段程式碼將修改 tetris-draw-next-shape
的行為,而且它可以儲存在配置檔案中,與實際的俄羅斯方塊程式碼分離。
去掉預覽框是一個簡單的改變。一個更激烈的變化是,讓塊隨機停止在空中:
本圖中,紅色的 I 和綠色的 T 部分沒有掉下來,它們被固定下來了。這會讓遊戲變得 極其困難,但卻很容易實現。
和前面一樣,我們首先定義一個標誌:
(defvar tetris-stop-midair t
"If non-nil, pieces will sometimes stop in the air.")
目前,Emacs 俄羅斯方塊的工作方式 類似這樣子:活動部件有 x 和 y 座標。在每個時鐘滴答聲中,y 座標遞增(塊向下移動一行),然後檢查是否有與現存的塊重疊。如果檢測到重疊,則將該塊回退(其 y 座標遞減)並設定該活動塊到位。為了讓一個塊在半空中停下來,我們所要做的就是破解檢測函式 tetris-test-shape
。
這個函式內部做什麼並不重要 —— 重要的是它是一個返回布林值的無引數函式。我們需要它在正常情況下返回布林值 true(否則我們將出現奇怪的重疊情況),但在其他時候也需要它返回 true。我相信有很多方法可以做到這一點,以下是我的方法的:
(defun tetris-test-shape-random (tetris-test-shape)
(or (and
tetris-stop-midair
;; Don't stop on the first shape.
(< 1 tetris-n-shapes )
;; Stop every INTERVAL pieces.
(let ((interval 7))
(zerop (mod tetris-n-shapes interval)))
;; Don't stop too early (it makes the game unplayable).
(let ((upper-limit 8))
(< upper-limit tetris-pos-y))
;; Don't stop at the same place every time.
(zerop (mod (random 7) 10)))
(funcall tetris-test-shape)))
(advice-add 'tetris-test-shape :around #'tetris-test-shape-random)
這裡的硬編碼引數使遊戲變得更困難,但仍然可玩。當時我在飛機上喝醉了,所以它們可能需要進一步調整。
順便說一下,根據我的 tetris-scores
檔案,我的 最高分 是:
01389 Wed Dec 5 15:32:19 2018
該檔案中列出的分數預設最多為五位數,因此這個分數看起來不是很好。
給讀者的練習
- 使用 advice 修改 Emacs 俄羅斯方塊,使得每當方塊下移動時就閃爍顯示訊息 “OH SHIT”。訊息的大小與塊堆的高度成比例(當沒有塊時,訊息應該很小的或不存在的,當最高塊接近天花板時,訊息應該很大)。
- 在這裡給出的
tetris-test-shape-random
版本中,每隔七格就有一個半空中停止。一個玩家有可能能計算出時間間隔,並利用它來獲得優勢。修改它,使間隔隨機在一些合理的範圍內(例如,每 5 到 10 格)。 - 另一個對使用 Tetris 使用 advise 的場景,你可以試試 autotetris-mode。
- 想出一個有趣的方法來打亂塊的旋轉機制,然後使用 advice 來實現它。
-
Emacs 只有一個巨大的全域性名稱空間,因此函式和變數名一般以包名做字首以避免衝突。 ↩
-
很多人會說你不應該使用已有的名稱空間字首而且應該將自己定義的所有東西都放在一個預留的名稱空間中,比如像這樣
my/tetris-preview-next-shape
,然而這樣很難看而且沒什麼意義,因此我不會這麼幹。 ↩
via: https://nickdrozd.github.io/2019/01/14/tetris.html
作者:nickdrozd 選題:lujun9972 譯者:lujun9972 校對:wxy
本文由 LCTT 原創編譯,Linux中國 榮譽推出
相關文章
- 如何讓AI教機器自己玩俄羅斯方塊?AI
- 俄羅斯方塊練習
- Tetris 俄羅斯方塊遊戲遊戲
- canvas實現俄羅斯方塊Canvas
- 俄羅斯方塊(JS+CSS)JSCSS
- 【Java遊戲】java俄羅斯方塊!Java遊戲
- Flutter Web 實戰 - 俄羅斯方塊FlutterWeb
- 俄羅斯方塊歷史發展與變革創新
- 恰逢35歲生日 俄羅斯方塊的一切都變得井井有條
- 使用JavaScript實現一個俄羅斯方塊JavaScript
- 基於MonoGame重製《俄羅斯方塊》遊戲MonoGAM遊戲
- wxpython入門第十一步(俄羅斯方塊)Python
- 最新《 java實戰開發俄羅斯方塊教程》Java
- Python 實戰開發俄羅斯方塊遊戲Python遊戲
- 基於Flutter的俄羅斯方塊小遊戲Flutter遊戲
- c#實現簡單的俄羅斯方塊C#
- 俄羅斯方塊聯機小遊戲的實現遊戲
- 《俄羅斯方塊》系列 35 週年 一窺遊戲歷年玩法演變遊戲
- 使用C#和MonoGame開發俄羅斯方塊遊戲C#MonoGAM遊戲
- 用React、Redux、Immutable做俄羅斯方塊 | 掘金技術徵文ReactRedux
- 從俄羅斯方塊,邁向強化學習大門強化學習
- 初學者——Java之實現簡易俄羅斯方塊Java
- python開發俄羅斯方塊小遊戲程式碼例項Python遊戲
- “漢字俄羅斯方塊”《一字不落》今日上架Steam
- 為了上班摸魚我用Python製作了俄羅斯方塊?Python
- [分享]純python3手寫Tetris(俄羅斯方塊)遊戲Python遊戲
- Python:遊戲:300行程式碼實現俄羅斯方塊Python遊戲行程
- 函數語言程式設計嘗試之俄羅斯方塊函數程式設計
- 用 SQL 寫的俄羅斯方塊遊戲「GitHub 熱點速覽」SQL遊戲Github
- pyqt5製作俄羅斯方塊小遊戲-----原始碼解析QT遊戲原始碼
- 300行Python程式碼實現俄羅斯方塊,致敬逝去的童年Python
- 俄羅斯玩偶
- 俄羅斯:‘區塊鏈屬於我們’區塊鏈
- 回顧「俄羅斯方塊」曾經的一段蒸汽波時代
- 超越《俄羅斯方塊》後,《我的世界》想打造一個更具野心的世界
- Python3+pygame實現的俄羅斯方塊 程式碼完整 有演示效果PythonGAM
- 讓王老菊也翻車的“俄羅斯方塊”+硬核策略遊戲,手機版終於發售!遊戲
- Poka-Yoke讓失敗變得比成功更難 - reflectoring