浣Y(jié)構(gòu)到網(wǎng)格建模)
把填字游戲做在莫比烏斯帶上第一眼會(huì)覺得這就是一個(gè)紙藝噱頭。真正動(dòng)手之后才會(huì)發(fā)現(xiàn)它改變的不是“帶子能不能扭轉(zhuǎn)”而是填字游戲最基本的空間規(guī)則一個(gè)格子有哪些鄰居、詞條可以沿哪個(gè)方向延伸、跨過粘合線之后又會(huì)落到哪一行。這篇文章就以“莫比烏斯帶填字游戲”為主題把看似玩具化的概念拆成三個(gè)可以落地的部分紙帶模型、網(wǎng)格數(shù)據(jù)結(jié)構(gòu)和題目設(shè)計(jì)流程。適合對數(shù)學(xué)謎題、紙藝、算法建模和創(chuàng)意開發(fā)感興趣的讀者。最值得關(guān)注的不是表面怎么畫格子而是“邊界配對”把紙帶左端和右端翻轉(zhuǎn)后粘起來離散網(wǎng)格里會(huì)多出一整套平時(shí)根本不會(huì)出現(xiàn)的相鄰關(guān)系而這恰恰是莫比烏斯帶填字游戲真正有趣的地方。1. 莫比烏斯帶填字游戲和普通填字的本質(zhì)區(qū)別1.1 普通網(wǎng)格是平鋪莫比烏斯網(wǎng)格是配對普通的填字游戲建立在矩形網(wǎng)格上。網(wǎng)格的上下左右都有邊界邊界之外的格子不存在。所以一個(gè)詞條老老實(shí)實(shí)地待在某個(gè)網(wǎng)格行或者列里不會(huì)突然跳到另一行。莫比烏斯帶不一樣。一條標(biāo)準(zhǔn)莫比烏斯帶是先把紙帶扭轉(zhuǎn) 180 度再把兩端粘起來。從連續(xù)幾何上看它只有一個(gè)曲面也只有一條連續(xù)邊界。但從填字游戲的角度來看我們不可能在真正的三維帶子上直接排版編輯最后還是要把它“展開”成一張二維矩形紙。區(qū)別在于這張矩形紙的左右兩側(cè)并不是普通畫紙的空白邊而是粘合邊。如果帶子的網(wǎng)格是 L×W也就是橫向 8 格、縱向 3 格我們把左邊緣和右邊緣配對起來。注意配對不是簡單的第 0 行接第 0 行因?yàn)橹谱鬟@條帶子時(shí)扭轉(zhuǎn)了 180 度。所以配對要按照翻轉(zhuǎn)規(guī)則來右邊緣第 y 行跨過粘合線之后會(huì)接回左邊緣的第 W-1-y 行。這看起來不復(fù)雜但它已經(jīng)改變了填字游戲里有關(guān)鄰居的判斷標(biāo)準(zhǔn)。1.2 扭轉(zhuǎn) 180 度帶來的鄰居規(guī)則對于一個(gè)矩形網(wǎng)格一個(gè)格子通常有四個(gè)鄰居上、下、左、右。在莫比烏斯帶填字游戲里上、下的判斷沒有變化仍然沿著帶子的寬度方向移動(dòng)只要走到頂行或底行再往外就是紙帶的真實(shí)邊緣不存在別的格子。左、右則需要特殊處理。具體規(guī)則可以這樣定義移動(dòng)方向從 (x, y) 出發(fā)走到普通網(wǎng)格內(nèi)跨過粘合線后向右x L-1到達(dá) (x1, y)如果 x L-1則到達(dá) (0, W-1-y)向左x 0到達(dá) (x-1, y)如果 x 0則到達(dá) (L-1, W-1-y)向上y 0到達(dá) (x, y-1)如果 y 0則無鄰居向下y W-1到達(dá) (x, y1)如果 y W-1則無鄰居這里的 L 是帶長方向的格子數(shù)量W 是帶寬方向的格子數(shù)量。橫向代表沿著帶子繞圈的方向“跨過粘合線”就是要從一側(cè)跑到另一側(cè)。還有一個(gè)容易被忽略的特性在普通圓柱面上橫向走一圈會(huì)回到同一個(gè)地方在莫比烏斯帶上橫向走完一圈并不會(huì)回到原來的行而要先經(jīng)歷一次行號(hào)翻轉(zhuǎn)再走完一圈才會(huì)回到起點(diǎn)。這意味著如果把一條橫向詞的長度設(shè)計(jì)成超過帶長 L詞條跨過邊界后就會(huì)改變所在行。這個(gè)現(xiàn)象才是莫比烏斯帶填字游戲和普通二維填字游戲最大的不同。注意不要一開始就把問題想成“在圓環(huán)內(nèi)表面寫字”。莫比烏斯帶沒有內(nèi)表面和外表面的區(qū)分它只有一個(gè)連續(xù)表面。網(wǎng)格處理時(shí)只要把左右邊緣按翻轉(zhuǎn)關(guān)系配對就可以在普通二維平面上完成所有設(shè)計(jì)。2. 用紙帶做一個(gè)最小模型驗(yàn)證跨面詞到底怎么走2.1 先做一個(gè) 8×3 的紙帶網(wǎng)格我建議不要直接寫代碼先用剪刀、膠帶和一張紙條做一次最小實(shí)驗(yàn)。材料很簡單一張長紙條、一把尺子、一支筆、一段透明膠帶。把紙條分成 8 列、3 行每個(gè)格子盡量均勻。在展開狀態(tài)下你可以看到一個(gè) 8×3 的矩形區(qū)域。第 0 行、第 1 行、第 2 行從上到下排布。在展開圖的左端和右端分別做標(biāo)記。關(guān)鍵是記錄每個(gè)格子的坐標(biāo)例如第 0 行第 0 列寫成 (0,0)第 0 行第 7 列寫成 (7,0)。不要急著寫字先用編號(hào)代替字母。接下來做一個(gè)最小驗(yàn)證從 (0,0) 出發(fā)沿橫向向右走。走到 (7,0) 后如果把紙帶兩端扭轉(zhuǎn) 180 度再粘起來那么下一步會(huì)落到哪里按照邊界配對規(guī)則落點(diǎn)應(yīng)該是 (0, W-1-0)也就是 (0,2)。這個(gè)結(jié)果很關(guān)鍵。也就是說當(dāng)你沿著帶子的橫向方向一直走第一個(gè)遇到的格子還在原行但越過粘合線后下一個(gè)格子已經(jīng)跑到帶子的另一條“視覺邊緣”上了。2.2 寫一個(gè)跨邊詞試試現(xiàn)在把編號(hào)換成字母。假設(shè)橫向詞是 ABCDEFGHI長度是 9。L 8所以前 8 個(gè)字母剛好填滿第 0 行的 8 個(gè)格子第 0 行ABCDEFGH第 0 列到第 7 列01234567第 9 個(gè)字母 I 不能繼續(xù)放在第 8 列因?yàn)榈?8 列不存在。按照莫比烏斯帶的規(guī)則它落到第 0 列的第 2 行也就是 (0,2)。于是展開圖里會(huì)看到第 0 行ABCDEFGH第 1 行第 2 行I在普通填字游戲里ABCDEFGHI 不是一行詞因?yàn)?I 出現(xiàn)在另一行。但在莫比烏斯帶填字游戲里它們是同一個(gè)連續(xù)橫向詞。物理上當(dāng)你把紙帶扭轉(zhuǎn)粘合后A 到 I 確實(shí)位于同一條連續(xù)路徑上。這會(huì)給答題者帶來很強(qiáng)的空間錯(cuò)位感。它不再是一個(gè)“把所有詞分別放進(jìn)行和列”的傳統(tǒng)謎題而是一個(gè)“路徑可以跨過邊界并改變行號(hào)”的拓?fù)渲i題。2.3 把紙帶粘起來之后怎么驗(yàn)證手工驗(yàn)證時(shí)我常用的方法是先不寫字先在每條路徑的格子上用鉛筆輕輕編號(hào)。比如從某個(gè)起點(diǎn)出發(fā)沿橫向向右走每經(jīng)過一個(gè)格子就寫“1、2、3……”。走到右邊界后用手把紙條扭轉(zhuǎn)再把左端對齊觀察編號(hào)下一個(gè)應(yīng)該落在哪一行。具體做法先把格子畫好不剪斷紙條。從 (0,0) 開始在第一行依次寫上 1 到 8。把紙條扭轉(zhuǎn) 180 度使左端和右端相對。在左端第 2 行邊上繼續(xù)寫第 9 個(gè)編號(hào)。用透明膠帶固定再沿著帶子繼續(xù)走一遍看編號(hào)是否連續(xù)。如果編號(hào)沒有跨到第 2 行而是回到了第 0 行說明你沒有扭轉(zhuǎn) 180 度而是做成了普通圓環(huán)。這種錯(cuò)誤在自建模型時(shí)非常容易發(fā)生視覺上看起來都是“紙條圈起來了”但拓?fù)湫再|(zhì)完全不同。這個(gè)手工模型做一次基本就能確定后續(xù)代碼里的方向邏輯了。3. 把紙帶翻譯成數(shù)據(jù)結(jié)構(gòu)坐標(biāo)、移動(dòng)和回環(huán)3.1 用扭轉(zhuǎn)矩形表示莫比烏斯帶紙帶模型的缺點(diǎn)是不方便批量生成題目也不方便自動(dòng)驗(yàn)證答案。所以下一步要把它抽象成數(shù)據(jù)結(jié)構(gòu)。最簡單的方式是直接使用“扭轉(zhuǎn)矩形”。仍然用 L×W 的二維數(shù)組保存格子但數(shù)組的左右兩邊按照翻轉(zhuǎn)規(guī)則相連。數(shù)組內(nèi)部可以存放字母、空格、編號(hào)或者答案。每個(gè)格子在數(shù)組里的坐標(biāo)仍然是 (x, y)只是訪問相鄰格子時(shí)不能只用普通數(shù)組加減法。這種展開方式和物理紙帶是等價(jià)的紙帶的左邊緣和右邊緣在數(shù)組里看起來隔得很遠(yuǎn)但在邏輯上相鄰。只要在代碼里把左右邊緣的配對規(guī)則寫對所有路徑計(jì)算都可以在二維數(shù)組上完成。3.2 Python 里的邊界鄰居模型下面給出一段示例代碼用來描述莫比烏斯帶填字游戲的基礎(chǔ)網(wǎng)格。它不依賴任何第三方庫只使用列表和元組。class MobiusGrid: def __init__(self, length, width): self.L length self.W width self.cells [[ for _ in range(length)] for _ in range(width)] # cells[y][x] 表示第 y 行、第 x 列的格子 def right(self, x, y): 從 (x, y) 向右移動(dòng)一格返回新的坐標(biāo)。 if 0 x self.L - 1: return (x 1, y) if x self.L - 1: # 跨過右邊緣。扭轉(zhuǎn)后回到左邊緣行號(hào)翻轉(zhuǎn)。 return (0, self.W - 1 - y) raise ValueError(x out of range) def left(self, x, y): 從 (x, y) 向左移動(dòng)一格返回新的坐標(biāo)。 if 0 x self.L - 1: return (x - 1, y) if x 0: # 跨過左邊緣回到右邊緣行號(hào)翻轉(zhuǎn)。 return (self.L - 1, self.W - 1 - y) raise ValueError(x out of range) def down(self, x, y): 向下移動(dòng)一格。這里不跨越莫比烏斯邊緣。 if y self.W - 1: return (x, y 1) return None def up(self, x, y): 向上移動(dòng)一格。這里不跨越莫比烏斯邊緣。 if y 0: return (x, y - 1) return None這段代碼的關(guān)鍵是right和left。當(dāng)x self.L - 1時(shí)向右移動(dòng)不再是越界而是進(jìn)入左側(cè)的翻轉(zhuǎn)行。當(dāng)x 0時(shí)向左移動(dòng)也一樣。W - 1 - y就是行號(hào)翻轉(zhuǎn)。3.3 從一個(gè)起點(diǎn)遍歷你會(huì)看到兩次經(jīng)過同一面有了基礎(chǔ)鄰居函數(shù)可以做一個(gè)簡單的路徑追蹤。例如從起點(diǎn) (0, 0) 開始橫向連續(xù)走 20 步打印路徑坐標(biāo)。def walk_right(grid, start, steps): path [] x, y start for _ in range(steps): path.append((x, y)) x, y grid.right(x, y) return path grid MobiusGrid(length8, width3) path walk_right(grid, (0, 0), 20) for i, p in enumerate(path): print(i, p)運(yùn)行后你會(huì)看到類似下面的結(jié)果0 (0, 0) 1 (1, 0) 2 (2, 0) 3 (3, 0) 4 (4, 0) 5 (5, 0) 6 (6, 0) 7 (7, 0) 8 (0, 2) 9 (1, 2) 10 (2, 2) 11 (3, 2) 12 (4, 2) 13 (5, 2) 14 (6, 2) 15 (7, 2) 16 (0, 0)從第 0 步到第 15 步走完了一個(gè)完整的橫向周期。可以看到位置先在第 0 行然后跳到第 2 行最后才回到第 0 行。這一輪一共經(jīng)過了 16 個(gè)格子正好等于 2L 16。這個(gè)現(xiàn)象告訴我們在莫比烏斯帶填字游戲里橫向詞的長度如果設(shè)計(jì)成超過 8就會(huì)進(jìn)入另一行設(shè)計(jì)成 15還不會(huì)回到起點(diǎn)只有長度等于 16 時(shí)才會(huì)構(gòu)成一個(gè)完整的閉合路徑。普通填字游戲的“一行詞”概念在這里徹底失效了。4. 設(shè)計(jì)題面的基本原則先定跨邊詞再補(bǔ)交叉詞4.1 跨邊詞的長度要和帶長、帶寬配合設(shè)計(jì)題面時(shí)第一步不是寫提示而是決定帶子的 L 和 W。L 決定了一條橫向詞在不跨越邊界時(shí)可以占多少個(gè)格子。如果想讓詞條跨過莫比烏斯帶的粘合線最好讓橫向詞長度大于 L甚至接近 2L。舉個(gè)例子如果帶長 L8帶寬 W3一條長度為 9 的詞開頭落在第 0 行結(jié)尾落在第 2 行。一條長度為 16 的詞則構(gòu)成一個(gè)完整的橫向回環(huán)首尾會(huì)碰到同一個(gè)位置。這里有一個(gè)實(shí)用技巧設(shè)計(jì)跨邊詞時(shí)先不要把它當(dāng)成“一整行”而要把它當(dāng)成一條二維平面上的連續(xù)路徑。路徑上經(jīng)過每一個(gè)格子時(shí)記錄坐標(biāo)即可。至于它是不是和普通網(wǎng)格行對齊并不重要。4.2 交叉詞要區(qū)分“跨邊”和“貼邊”莫比烏斯帶上的填字游戲不能只有橫向詞否則更像是在打印一條循環(huán)字符串。要成為真正的填字游戲還需要交叉詞。交叉詞通常沿縱向放置。縱向詞的位置計(jì)算很簡單從一個(gè)格子出發(fā)沿 up 或 down 方向走。如果走到頂行或底行再往外就是紙帶邊緣不能再繼續(xù)。縱向詞不會(huì)跨過左、右粘合線除非你刻意設(shè)計(jì)“先向下再橫向跨邊再向下”的 L 形路徑但那種情況更接近復(fù)雜迷宮不適合入門。因此設(shè)計(jì)題面時(shí)要注意區(qū)分兩類詞詞條類型是否可以跨過左右粘合線位置特征難度普通橫向詞不跨只占一行內(nèi)的連續(xù)格子低跨邊橫向詞跨超出帶長 L跳到翻轉(zhuǎn)后的行中縱向交叉詞不跨只占一列內(nèi)的連續(xù)格子低L 形組合詞跨需要走多個(gè)方向高新手階段我建議先設(shè)計(jì) 2 到 3 條跨邊橫向詞其余都使用普通橫向詞和縱向交叉詞。這樣既能讓玩家感受到莫比烏斯帶的特殊規(guī)則又不會(huì)因?yàn)槁窂竭^于復(fù)雜而無法手算。4.3 給玩家寫提示時(shí)要標(biāo)明跨邊提示在普通填字游戲里提示一般寫“橫 3某種動(dòng)物”玩家就知道去第 3 行找。在莫比烏斯帶填字游戲里跨邊詞不在單一視覺行內(nèi)所以提示必須更明確。差勁的提示“第 0 行的一種動(dòng)物。”問題在于跨邊詞的第 9 個(gè)字符可能落在第 2 行玩家會(huì)找不到。更穩(wěn)妥的提示“從第 0 行第 0 列開始向右越過紙帶邊界后繼續(xù)的一段橫向詞一種動(dòng)物。”“橫向跨帶詞以 M 開頭共 9 個(gè)字母跨越邊界后接在第 2 行。”“繞環(huán)詞從左上角開始沿橫向走丟 16 步回到起點(diǎn)的循環(huán)詞。”這樣玩家至少知道這個(gè)詞不是普通的一行詞而是需要把展開圖邊界連接起來理解。提醒跨邊詞的起點(diǎn)不同跨過邊界后的落點(diǎn)也不同。起點(diǎn)行 y 越靠近中間跨邊后的行 W-1-y 越靠近另一側(cè)中間。所以在寫提示時(shí)盡量給出明確的起點(diǎn)坐標(biāo)和總長度。5. 驗(yàn)證、查錯(cuò)和常見問題它看起來能解為什么總卡住5.1 先按坐標(biāo)鏈路檢查而不是直接看輸出實(shí)際調(diào)試莫比烏斯帶填字游戲時(shí)最容易出現(xiàn)的問題是代碼寫完后單詞能填進(jìn)單元格但答案在視覺上完全對不上。我建議按這個(gè)順序排查先檢查單個(gè)格子的鄰居關(guān)系。從一個(gè)格子向右走一步確認(rèn)坐標(biāo)變化是否符合預(yù)期。再檢查跨邊詞。把一條詞逐字拆成坐標(biāo)序列從起點(diǎn)開始一路走到詞尾查看最后一個(gè)字母落在哪里。然后檢查交叉點(diǎn)。找到兩條詞相交的格子確認(rèn)兩條詞確實(shí)在那個(gè)坐標(biāo)上共享同一個(gè)字母。最后打印完整展開圖。把整個(gè)帶子展開成 L×W 的二維表格再在表格上標(biāo)出所有詞路徑。這樣能快速定位問題到底出在邊界配對邏輯還是出在詞庫長度設(shè)置。5.2 常見錯(cuò)位和行號(hào)翻轉(zhuǎn)錯(cuò)誤最常見的問題是搞混y和W-1-y。很多人寫完right函數(shù)后跨邊回到左邊緣時(shí)直接寫了(0, y)這就做成了普通圓環(huán)而不是莫比烏斯帶。可以單獨(dú)寫一個(gè)小的坐標(biāo)測試grid MobiusGrid(length8, width3) # 從 (7, 0) 向右期望回到 (0, 2) assert grid.right(7, 0) (0, 2) # 從 (0, 0) 向左期望到 (7, 2) assert grid.left(0, 0) (7, 2) # 從 (7, 1) 向右期望回到 (0, 1) assert grid.right(7, 1) (0, 1) # 從 (7, 2) 向右期望回到 (0, 0) assert grid.right(7, 2) (0, 0)這些斷言如果全部通過邊界規(guī)則基本正確。5.3 重復(fù)詞和反轉(zhuǎn)詞跨邊路徑的第二層坑莫比烏斯帶填字游戲還有一個(gè)特殊的坑因?yàn)闄M向路徑經(jīng)過 2L 步后會(huì)回到起點(diǎn)所以一條詞如果設(shè)計(jì)成剛好繞完整圈那么它的起點(diǎn)和終點(diǎn)會(huì)重合。這時(shí)候要特別檢查詞是否存在“循環(huán)首尾相接”的問題。例如詞 ABABABAB長度為 8在普通網(wǎng)格里是一行簡單詞。但在莫比烏斯帶橫向周期里如果長度等于 2L玩家繞完一圈后會(huì)回到同一個(gè)字母。如果詞本身具有周期性就可能出現(xiàn)兩個(gè)不同位置的字母完全相同導(dǎo)致填字游戲出現(xiàn)歧義。另一個(gè)常見問題是反轉(zhuǎn)。在普通填字游戲里“橫著寫”和“橫著往回寫”通常被視為不同方向。在莫比烏斯帶里由于跨邊后行號(hào)翻轉(zhuǎn)一個(gè)詞從某個(gè)起點(diǎn)橫向走完一圈回來時(shí)路徑方向會(huì)在視覺上變成另一行但字母順序保持不變。如果詞庫中存在重復(fù)詞條或者某個(gè)詞反向讀也是另一個(gè)有效詞就需要在自動(dòng)生成器里做去重檢查。排查思路現(xiàn)象原因處理方式跨邊詞的最后一個(gè)字母落在平凡行而不是預(yù)期行行號(hào)翻轉(zhuǎn)寫錯(cuò)檢查W-1-y是否在左右兩邊都使用了詞條繞一圈后和另一條詞重復(fù)沒檢查閉合路徑對每條詞生成完整坐標(biāo)序列再做集合查重打印出來像普通二維填字莫比烏斯特色不明顯所有橫向詞長度都小于 L增加跨邊詞讓詞長超過帶長物理紙帶上看起來有空隙但展開圖里連不上粘合線方向不一致手工模型和代碼統(tǒng)一按“右邊緣接左邊緣且行號(hào)翻轉(zhuǎn)”執(zhí)行6. 從手工模型到在線謎題真正落地時(shí)要注意什么6.1 自動(dòng)出題生成器的輸入?yún)?shù)如果你不滿足于手工設(shè)計(jì)想做一個(gè)自動(dòng)生成莫比烏斯帶填字游戲的工具建議先定義輸入?yún)?shù)。常見參數(shù)包括帶長 L橫向格子數(shù)量。帶寬 W縱向格子數(shù)量。詞庫橫向詞、縱向詞、跨邊詞。跨邊詞數(shù)量建議占總橫向詞的 1/3 左右。交叉規(guī)則每條詞必須至少和另一條詞相交一次。生成思路和普通填字游戲類似先放置跨邊詞因?yàn)樗鼈兪菍ξ恢孟拗谱顕?yán)格的詞條。跨邊詞需要寫成完整坐標(biāo)序列例如從 (0,0) 開始經(jīng)過 (7,0)再到 (0,2)然后繼續(xù)橫向走。生成器需要支持這種連續(xù)路徑的點(diǎn)位沖突檢測。放置跨邊詞后再用普通橫向詞和縱向詞去填充空白格子。最后檢查所有詞是否滿足交叉要求路徑是否存在多個(gè)分離區(qū)域。6.2 渲染交互頁面的數(shù)據(jù)要點(diǎn)如果要把莫比烏斯帶填字游戲做成網(wǎng)頁交互數(shù)據(jù)結(jié)構(gòu)和渲染可以分離。底層仍然使用 L×W 數(shù)組但要增加一個(gè)“連接關(guān)系表”記錄每個(gè)格子的四個(gè)鄰居坐標(biāo)。在畫布上有兩種常見渲染方式渲染方式效果適合場景直接畫展開矩形簡單左右邊緣用箭頭或彩色線標(biāo)出配對關(guān)系教學(xué)演示、編輯器模擬三維紙帶動(dòng)畫更直觀但需要處理扭曲貼圖展示型項(xiàng)目不適合大量文字編輯直接畫展開矩形時(shí)建議在左右邊緣畫上配對提示。例如給第 0 行和第 2 行使用同一種顏色并標(biāo)注“這兩行在粘合后相連”。如果把左右邊緣和行號(hào)翻轉(zhuǎn)關(guān)系展示清楚玩家不需要真的看懂拓?fù)鋵W(xué)也能玩。6.3 適合用在哪里從數(shù)學(xué)科普到創(chuàng)意題目設(shè)計(jì)莫比烏斯帶填字游戲并不是一個(gè)非常成熟的商業(yè)謎題類型但它很適合做三件事。第一是數(shù)學(xué)科普。用填字游戲引入單面曲面、邊界配對、周期路徑這些概念比只放一張莫比烏斯帶圖片更能讓人記住。第二是算法訓(xùn)練。寫一個(gè)莫比烏斯帶填字游戲自動(dòng)生成器需要處理坐標(biāo)系、路徑連續(xù)性、邊界翻轉(zhuǎn)、單詞沖突檢測、答案驗(yàn)證這些都是很好的編程練習(xí)。第三是創(chuàng)意紙藝或游戲設(shè)計(jì)。把普通填字游戲的平面網(wǎng)格替換成可扭曲粘貼的帶面結(jié)構(gòu)會(huì)讓玩家產(chǎn)生新鮮的空間感特別適合放在數(shù)學(xué)主題展覽、獨(dú)立解謎活動(dòng)或者小型桌游作品里。我自己在落地時(shí)一般會(huì)先用 8×3 的小紙帶跑通路徑再改成 12×4 的更大網(wǎng)格最后才接詞庫和數(shù)據(jù)渲染。不要一開始就上長詞、高并發(fā)或者復(fù)雜動(dòng)畫因?yàn)檫@類問題最核心的難點(diǎn)根本不在性能而在“邊界配對”是否嚴(yán)謹(jǐn)。配對邏輯寫對了后面的自動(dòng)出題和交互設(shè)計(jì)都只是時(shí)間問題。配對邏輯一旦寫錯(cuò)后面所有提示、答案、校驗(yàn)都會(huì)跟著錯(cuò)。