如何讓 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
相關文章
- 如何讓AI教機器自己玩俄羅斯方塊?AI
- Tetris 俄羅斯方塊遊戲遊戲
- 分析:Google讓我們變得更愚蠢嗎Go
- 【Java遊戲】java俄羅斯方塊!Java遊戲
- canvas實現俄羅斯方塊Canvas
- Win32俄羅斯方塊Win32
- 俄羅斯方塊(JS+CSS)JSCSS
- 我的俄羅斯方塊程式
- 詳解ResNet 網路,如何讓網路變得更“深”了
- 如何讓python變得更快?Python
- Smartour——讓網頁導覽變得更簡單網頁
- 讓動畫變得更簡單之FLIP技術動畫
- WPF自定義Panel:讓拖拽變得更簡單
- Flutter Web 實戰 - 俄羅斯方塊FlutterWeb
- java控制檯版本 俄羅斯方塊Java
- 鵬躍俄羅斯方塊遊戲 1.0遊戲
- JavaScript 寫遊戲 : 俄羅斯方塊 (轉)JavaScript遊戲
- CUPS讓Linux列印變得更輕鬆(轉)Linux
- 請大家談談‘俄羅斯方塊程式
- JS編寫的俄羅斯方塊 (轉)JS
- 智簡魔方DCIM系統如何讓資料中心管理變得更簡單
- 《俄羅斯方塊》系列 35 週年 一窺遊戲歷年玩法演變遊戲
- 如何讓開發變得敏捷起來?敏捷
- 潛力:如何讓Rust變得更高階?Rust
- 基於Flutter的俄羅斯方塊小遊戲Flutter遊戲
- 使用JavaScript實現一個俄羅斯方塊JavaScript
- 一個俄羅斯方塊的原始碼 (轉)原始碼
- 一個俄羅斯方塊遊戲源程式 (轉)遊戲
- 基於MonoGame重製《俄羅斯方塊》遊戲MonoGAM遊戲
- LEARUN快速開發平臺,讓開發變得更簡單
- 認知增強技術,讓人類變得更聰明
- 如何讓程式設計師變得沒朋友程式設計師
- 如何讓資料清洗工作變得簡單
- 最新《 java實戰開發俄羅斯方塊教程》Java
- 俄羅斯方塊聯機小遊戲的實現遊戲
- c#實現簡單的俄羅斯方塊C#
- Python 實戰開發俄羅斯方塊遊戲Python遊戲
- 一塊想讓你我變得更好的手錶Apple WatchAPP