龔漢伯
(寧波財經學院數字技術與工程學院 浙江省寧波市 315175)
傳統的課堂數電教學大都枯燥無味,因此有些地區開始嘗試將游戲與教學結合來提升教學質量,Minecraft 因其開放性強,知名度高,受眾面廣被成功選中[1-2]。游戲中的紅石設定與現實中的數字電路特性相似,可通過紅石元件和紅石特性產生強弱不同的紅石信號,實現延時、比較、放大等功能,因此現實電路移植進游戲成為可能[3-4]。
游戲中的物品特性與現實不同,移植需要適當轉化,但游戲物品繁多,初學者很難快速掌握。本文試提煉了部分紅石與指令在數電設計中的用法和技巧,用于啟發初學者快速入門紅石數電設計。
游戲中的環境與現實相近,有晝夜交替、天氣變換、山川河流等。晝夜交替會引起光線強度變化,這導致用到陽光探測器的電路輸出的紅石信號不穩定。白天的強光讓紅石線、螢石燈、紅石火把等器件的光效不明顯,這讓紅石線和用螢石燈組成的點陣顯示器或數碼管的故障很難被發現。天氣變化會降低能見度。山川河流限制了電路搭建的場地,且草綠色也會降低光效觀感。
電路搭建選用中國版Minecraft 版本號為1.13.2 或更高的Java版。創建地圖時選擇創造模式、超平坦地形和作弊可解決地形問題并為指令提供方便。按T 鍵或/鍵打開對話框,鍵入/gamerule doDaylightCycle false 后按回車鍵可關閉晝夜交替。同理/time set midnight 將時間設為午夜可增強光效觀感。/weather clear 999999將天氣改為晴天可消除雨天的視線阻礙。/fill~~10~~50~10~100 minecraft:sandstone 將在天空創建一塊長50 寬100 的沙石塊電路基板,地形不再是限制且顏色更美觀。注意指令參數間用空格分離。
為了獲取更多游戲中的信息方便后續設計,可按F3 鍵打開調試信息。若信息中無坐標數據,可按下ESC 鍵進入選項中的聊天設置,關閉簡化調試信息。
在數電中,邏輯門電路是最基礎的電路之一,它是大型集成電路的最小單位,作用是判斷輸入信號是否滿足條件,滿足就通過,不滿足則截止。游戲中可利用物品特性搭建邏輯門電路和其它基礎電路。

圖1:第一種非門

圖2:第二種非門

圖3:二輸入與門

圖4:三輸入與門

圖5:二輸入或門
第一種,當紅石火把所插方塊被充能時火把熄滅,利用此性質使輸入輸出相反,如圖1所示。第二種,需要陽光探測器、紅石比較器和紅石中繼器。由于在午夜,陽光探測器需要右鍵切換至反向模式,此時探測器的輸出強度只有11,如圖2所示。紅石比較器有比較和減法模式,這里使用比較模式。比較器三角指向的前端為輸出端,后方和兩側為輸入端,當兩側輸入小于等于后方輸入時將無衰減輸出后方信號,當兩側輸入大于后方輸入時將不輸出。紅石中繼器可用于放大信號,外部輸入信號經中繼器放大后可保證側方信號強度為15,大于陽光傳感器的11,輸出變為零實現非門功能。
現實中與門可由二極管和電阻搭建,而紅石中繼器的單向特性與二極管相似,自然想到用中繼器代換二極管,但實驗后發現并不可行。通過分析可知實際電路只要與地相連的均為0,紅石中只要與能量源相連的均為1,因此可將紅石信號通過非門取反后形成與非門,再通過非門輸出形成與門。二輸入與門如圖3所示,三輸入與門如圖4所示。
或門只需紅石粉,若輸入信號弱,可在兩個輸入或輸出上加中繼器。如圖5所示。

圖6:判斷電路

圖7:雙向紅石中繼器

圖8:原始3/8 線譯碼器

圖9:指令改進型3/8 線譯碼器
判斷電路在指令簡化部分非常重要,其結構與第二種非門相似,只需在輸入引腳處直接引出輸出端即可,該電路實現了對0 和1 的判斷。輸入0 時只有比較器一端輸出1,該輸出端為復位端;輸入1 時只有直接引出端為1,該輸出端為置位端。如圖6所示。
單個紅石中繼器只能單向增強信號,想要雙向通信自然想到再并聯一個反向的中繼器,但如此連接的兩個中繼器會相互激活,成為不受控能量源。解決這個問題可以利用中繼器的中繼鎖特性。當紅石中繼器的側方有信號輸入時會進入保持狀態,無論輸入端是否有信號,輸出端信號不變,該狀態的特點是中繼器上出現一條橫杠。
雙向中繼器包含兩個中繼器和兩個比較器,比較器用于控制紅石線走向并作為中繼鎖開關。由于中繼器的延時特性,在用于放大的中繼器在產生信號前,另一個中繼器先進入鎖止狀態使輸出保持為零,這樣每次只有一個中繼器工作,避免了相互激發。如圖7所示。
大型電路由基礎電路組成,以3/8 線譯碼器為例,根據邏輯式畫出邏輯圖后直接用基礎電路搭建即可。搭建時注意紅石線間的間隔,相鄰的紅石線會自動相連,可用比較器或中繼器進行隔離。如圖8所示。
紅石信號衰減速度與電路體積相比還是太快,長距離鋪設需大量使用中繼器,代價是產生較大延遲和總線的時序混亂,這會導致多個集成電路通信時的數據錯誤,處理速度也難以提高。
龐大的體積導致搭建和改動非常耗時。搭建前需要計算好間隔,否則空間不足可能導致紅石信號相互干擾。總之設計者將花大量時間在搭建上而不是數電設計上,這與游戲學習的初衷相違背。
電路規模龐大和紅石線的某些特性無法直接控制有關:臨近的紅石線會自動相連,想要獨立走線必須增大間距或用特殊器件改變走向;紅石線要依附方塊才能鋪設且只能依附于方塊上方,因此電路無法雙面走線且飛線時要浪費大量空間鋪設方塊;紅石線無法直接在垂直方向鋪設,需要用實心方塊或半磚搭建樓梯后再在其上鋪紅石線。
紅石信號強度通過某些方法確實能提高,但紅石線的其他特性無法改變,不使用紅石線長距離傳輸是根本辦法,下文的無線紅石能基本解決這個問題,其中指令起了關鍵作用。
豐富的指令是Minecraft 開放的一個重要原因,指令能幫玩家實現正常游戲無法實現的功能,也為自動化提供了便利。指令分為兩個重要部分:指令本身和數據標簽,數電入門不必全部知曉,掌握關鍵幾個即可。了解個別指令后就能制作簡易無線紅石。
格式:/fill 起點坐標 終點坐標 方塊名稱[方塊狀態]可選參數。該指令可批量填充方塊,平面立體均可填充??蛇x參數可忽略,默認值為replace。
格式:/setblock 坐標 方塊名稱[方塊狀態]{數據標簽} 可選參數。該指令可更改指定位置的方塊。要刪除指定位置的方塊可用air 方塊填充。可選參數可忽略,默認值為replace。
格式:/clone 被復制區域的開始坐標 被復制區域的結束坐標 新位置坐標 可選參數一 可選參數二。該指令可復制指定空間內包括空氣在內的方塊至新的位置,兩坐標為被復制空間的對角坐標,兩個可選參數均可忽略,默認值分別為replace 和normal。注意命令方塊內的指令也將被復制。
格式:/summon 實體名稱 坐標 {數據標簽}。該指令可在指定位置召喚實體,實體包括但不限于具有速度、位置、角度、生命值等特征,占據一定空間并受重力影響的物體。其中下落的方塊falling_block 較為特殊,與數據標簽配合能轉變成其他方塊。
格式:/kill 目標[目標選擇器]。用于清除實體,例如/kill @e[type=command_block_minecart,distance=..2]的效果是清除所有命令方塊礦車,@e 表示所有實體,type 選擇具體的實體類型,distance控制選擇范圍,點點2為距指令發出者小于兩個方塊的實體。
數字信號的特點給無線紅石帶來了極大便利,無須知道紅石線的具體能量強度,只要紅石線上有能量則代表1,無能量則代表0。無線紅石傳遞的不是紅石強度信號而是直接遠程放置紅石源,放置則為1,不放則為0。
將上文的判斷電路稍加改裝:在兩個輸出端各放一個命令方塊,兩方塊內均使用setblock 指令且坐標相同,區別是置位端的方塊種類為redstone_block 的紅石塊或其他紅石源,而復位端為air 空氣。輸入為1 時將激活置位端的命令方塊,坐標處被放置紅石源,這樣高電平信號就能無線傳遞到指定位置。輸入0 時激活復位端的命令方塊,坐標處被填充空氣使紅石塊移除即傳遞低電平信號。如圖10所示。
圖9為使用指令簡化的3/8 線譯碼器,相比原始譯碼器,改進型體積更小且線路更簡潔。三位輸入端的右位使用連鎖型無線紅石,其余兩位使用OOC 無線紅石。
由于一個命令方塊只能存一條簡易指令,一個判斷電路只能控制一個坐標的數據傳輸,若一條紅石線有多個分支就要多個判斷電路,這種設計任然較為復雜。
判斷電路的作用是鑒別紅石線的電平高低,而相連的分支線路的電平應是相同的,所以不需要多個判斷電路,只需一個能同時執行多個setblock 指令,能在多個坐標同時放置紅石源的方法。
如圖11所示,多條指令可用連鎖命令方塊執行,使用時需將第二個以及后方的命令方塊的模式調至連鎖且保持開啟,方塊上的箭頭指向的是下一個將被觸發的連鎖方塊[5]。每個方塊中都有一條setblock 指令且坐標不同,由于指令簡單所以執行速度很快,效果接近同時執行。
這種方法可稱為連鎖型無線紅石。該種方法執行效率最高且穩定性最好但仍有缺陷,從圖9可看出與用OOC 無線紅石的其它兩個端輸入端相比,連鎖型的體積仍然較大。使用下文的OOC 可以再次簡化紅石電路。
NBT(Named Binary Tags)又稱數據標簽是游戲中一種儲存數據的格式,可在指令中設定方塊的各項參數。想要執行復雜指令甚至編寫程序比如OOC,就需要了解NBT。
格式:BlockState:{Name:方塊名稱,Properties:{方塊狀態1:值1,方塊狀態2:值2…}}。該標簽用于下落的方塊,Name 和Properties為BlockState 的子標簽,前者用于指定下落方塊將轉變成的類型且不可省略,后者用于設定方塊狀態可以省略,大多方塊的狀態僅朝向起作用,若召喚的是連鎖命令方塊就需要用該狀態控制朝向。

圖10:改裝后的判斷電路

圖11:連鎖型命令方塊
格式:Time:數值。用于下落的方塊,表示已存在的時刻數(一刻為0.05 秒),若沒有該標簽下落方塊將瞬間消失。和summon 指令配合時建議設置為1。
格式:TileEntityData:{其他標簽}。該標簽用于下落的方塊,當下落的方塊接觸到其它方塊變為實體時,標簽內的數據會被復制到實體中。
這兩標簽用于命令方塊且常與TileEntityData 配合使用。TileEntityData{ auto:1,Command:"完整指令"}},Command 為往命令方塊寫入的指令,auto 為命令方塊是否保持開啟,1 開啟0 關閉,開啟后方塊無需紅石信號也能立即運行。
格式:Passengers:[{id:方塊名稱,其它標簽},{id:方塊名稱},...]。騎乘標簽,該標簽召喚的實體將騎在前一個實體上,標簽中的id為并列關系即多個實體騎在同一個實體上,但執行每個id 的順序有先后。若要按順序騎乘即后一個騎在前一個之上,可在id 后方繼續嵌套騎乘標簽如Passengers:[{id:…,Passengers :[{…}]},{...}]。該標簽用于實體,對普通方塊不起作用。
一鍵命令方塊亦稱OOC(Only One Command),主體只有一個命令方塊,與之前的簡易指令不同,有了數據標簽的加入,方塊內可存入多條能連續執行的指令,只需將載體命令方塊激活,指令將自動運行。OOC 對于電路簡化以及代碼化傳播有非常大的幫助。
堆疊型程序比較繁瑣但思路清晰,適合新手鞏固命令和數據標簽的語法。原理是利用Passengers 標簽不斷嵌套指令召喚出命令方塊,同時用Command 標簽在每個命令方塊內存入指令并運行,最后填充空氣消除所有召喚出的方塊來結束程序。以下為模板。
/summon falling_block~1~1~{BlockState:{Name:command_blo ck},Time:1,TileEntityData:{auto:1,Command:"命令1"},
Passengers:[{id:falling_block,BlockState:{Name:command_block},Time:1,TileEntityData:{auto:1,Command:"命令2"},
Passengers:[{id:falling_block,BlockState:{Name:command_block},Time:1,TileEntityData:{auto:1,Command:"命令3"},
Passengers:[{id:falling_block,BlockState:{Name:command_block},Time:1,TileEntityData:{auto:1,Command:"命令..."},
Passengers:[{id:falling_block,BlockState:{Name:command_block},Time:1,TileEntityData:{auto:1,Command:"/fill~~~~~-4~air"},
}]}]}]}]}
命令方塊礦車于Java1.7 版加入游戲,礦車型程序利用了礦車的疊加特性,即多個礦車使用騎乘標簽疊加在一起卻不會掉落,以下為模板。
/summon falling_block~~1~{BlockState:{Name:redstone_block},Time:1,
Passengers:[{id:falling_block,BlockState:{Name:activator_rail},Time:1,
Passengers:[{id:command_block_minecart,Command:"命令1"},
{id:command_block_minecart,Command:"命令2"},
{id:command_block_minecart,Command:"命令3"},
{id:command_block_minecart,Command:"命令..."},
{id:command_block_minecart,Command:"/setblock~~2~command_block{auto:1,Command:"fill~~~~~-3~air"}"},
{id:command_block_minecart,Command:"/kill@e[type=command_block_minecart,distance=..2]"}]}]}
堆疊型的方塊種類單一,且能嚴格按照騎乘順序執行指令,因此程序執行不易出錯,可靠性高。礦車型程序的主體為命令方塊礦車,因其本身為實體,所以無須用falling_block 做中間轉換而省去了BlockState 的大量代碼,也無須嵌套大量Passenger 標簽就能連續運行,程序執行效率遠超堆疊型。
程序代碼冗長,實際執行的只有Command 后方的指令,其余代碼只為保持程序的自動運行,這導致程序運行速度不高。單個OOC 中若有多條指令,執行過程中方塊將疊加到很高的高度,這會影響多層電路的設計。
一是由于summon 指令與Passenger 標簽只能用于實體,普通方塊想要被召喚和騎乘必須經過falling_block 這一實體媒介轉換,而轉換的代碼較長因此耗費較多時間且代碼顯得冗長。二是為了程序的連續運行,每添加一條指令須嵌套一個騎乘標簽,這也降低了程序執行效率。三是被召喚的方塊的空間若被其它方塊占用,則召喚方塊將變成掉落物,其攜帶的指令也無法執行,所以堆疊型OOC 上方不能有障礙物。
程序最后kill 指令里的distance 標簽用于控制清除范圍。范圍太小容錯率低,礦車可能不會全部清除,范圍大又會誤刪附近的程序礦車。程序中獨立放置的命令方塊不會嚴格按照程序順序執行,當電路速度很快時,前一個未執行的方塊將影響下一個將要放置的方塊。
由于命令方塊礦車需要激活才能運行,所以下方要放置用紅石塊充能的激活鐵軌。礦車出現到被鐵軌激活有一定的時間,若附近有多條OOC 同時執行,未激活的礦車被附近范圍設定錯誤的kill指令清除,那么礦車搭載的指令將無法執行。
獨立放置命令方塊是為了解決方塊與實體無法用一條指令清除的問題。如果按順序運行kill 和fill 指令,無論哪個先執行都將破壞另一條的觸發環境,只有將其中一條轉移至外部獨立運行才能解決這個問題。
由于兩種OOC 主要依靠游戲特性實現,所以弊端無法避免,只能在設計電路時靈活運用。
將判斷電路輸出端的命令方塊中的簡易指令換成OOC 即可,所有Command 標簽后均為setblock 指令只是坐標不同,這樣只需一個命令方塊就能向多個坐標傳數據。
由于OOC 的弊端不可不免,設計時最好根據實際情況選擇合適的無線紅石,或者將連鎖型與OOC 結合使用來彌補各自短板,例如將堆疊型程序拆成兩部分別放在兩個連鎖方塊中,這樣能將堆疊高度降低一半。
為方便設計的傳播,可將設計好的電路寫成OOC 程序。集成電路多由基礎電路組合而成,編寫時可先放置基礎電路,之后大量使用clone 指令復制已放置好的部分能提高編寫效率。
編寫帶有程序的命令方塊時注意,一對雙引號間若還有引號則每個引號都須用反斜杠/轉義,如同礦車型放置fill 指令一樣。若嵌套層數過多,反斜杠自身也需要反斜杠轉義。為了避免過多的符號轉義,可將普通方塊和程序方塊分開編寫,用不同的OOC 放置。
紅石數電入門并不難,在了解部分紅石特性并學習少量基礎電路后,利用數電模塊化特點搭建大型電路不再困難,搭建時利用指令優化電路不僅效率高,還能降低電路搭建難度。將電路編寫成OOC,電路就能以代碼的形式儲存和傳播,極大方便了紅石數電的交流和學習。