2025年6月29日

從公地悲劇到永續共榮:引導學生體驗資源管理的互動模擬程式「大家的村莊」

雖然課本上,我們不直接教「公地悲劇 (Tragedy of the Commons)」這個概念,不過實際上在教生物多樣性危機、人與環境時,我們就是在傳達這個概念-個人利益與群體福祉之間的拉扯與權衡

這個概念,過去我用過很多的實體活動來模擬,像是

當時玩過這些活動的學生,現在都已經幾歲了啊。今年我把這個遊戲改寫成線上遊戲了,是一個回合制的集體線上遊戲,就叫「大家的村莊」



「大家的村莊」是什麼

這是一個動態、即時的網頁互動模擬工具,環境就是一個線上村莊,每位學生登入後就成為村民,共同依賴一座漁獲有限的池塘維生。他們的每一個決定,都將即時影響自己、他人以及整個村莊的未來。


核心玩法:不只是捕魚

遊戲規則直觀而簡單:

  1. 共享資源:全班學生共享一個初始擁有固定魚量的池塘。
  2. 個人決策:在每一「年」(回合)中,學生需決定要捕撈多少條魚。
  3. 經濟誘因:捕獲的魚在滿足家庭基本需求後,多餘的漁獲可以賣錢,累積個人財富。
  4. 自然法則:池塘中的魚會根據設定的「增長率」進行繁殖,但過度捕撈將導致魚群數量下降,甚至崩潰。

這個簡單的循環可以用來討複雜的社會經濟議題。


教師的角色:說故事的人,從觀察者到引導者

教師是這場模擬的「村長」與引導者,有後台工具可以塑造不同的情境。工具的設計目的在於循序漸進地引導學生思考。






1. 基礎設定:打造你的村莊

在遊戲開始可以設定村莊的初始條件,例如:

  • 池塘魚數量:資源的豐裕程度。
  • 魚群增加率:資源的恢復能力。
  • 維持家庭最少魚數:村民的生存底線。
  • 魚價:個人利益的誘因強度。



2. 資訊透明度:知識就是力量

你可以決定學生能看到多少資訊,這是教學策略的關鍵:

  • [可見其他人捕魚狀態]:開啟後,學生能看到上一回合所有人的捕撈記錄。這會引發「社會壓力」——當看見有人過度捕撈時,其他人會選擇跟進還是約束?
  • [可見魚群變化圖]:開啟後,學生能看到魚群總量的歷史曲線圖。資訊的透明化,能否促使學生產生自律行為?

3. 政策與法規:模擬治理的藝術

你可以隨時介入,引入村莊的「法規」:

  • [總量管制]:設定每年全村的捕撈上限,模擬政府的永續管理。
  • [個人捕撈上限]:限制每個村民的捕撈數量,探討配額制度的公平性。
  • [禁漁處罰]:你可以對特定學生設置「禁漁年限」,作為過度捕撈的懲罰,引導學生討論規則與執法的重要性。

4. 公共投資:走向永續的道路

當學生累積一定財富後,你可以開啟「公共投資」功能,讓遊戲進入更深層次的討論:

  • 投資魚池維護:學生可以花錢提升魚群的「增長率」。
  • 投資魚苗放養:學生可以花錢直接增加池塘的魚隻數量。

這個機制將挑戰從「如何不耗盡資源」提升到「如何共同讓資源變得更豐饒」,觀察從消極限制到積極建設的永續發展理念如何進行。


你可以怎麼教?

這裡有一個四階段體驗設計,我試了好幾個班,認為這個挺不錯的,循序漸進的方式,讓學生在不同情境下感受局勢的變化。

第一階段:體驗純粹的悲劇

  • 設定:關閉所有資訊與法規限制。
  • 目標:讓學生在資訊不透明的情況下,憑藉個人直覺決策。通常,這會很快導致魚群崩潰。
  • 討論:為什麼資源會耗盡?當時大家在想什麼?如果重來一次,你會怎麼做?

第二階段:資訊的力量

  • 設定:重置遊戲,但開啟「可見魚群變化圖」與「可見其他人捕魚狀態」。
  • 目標:觀察在資訊透明後,學生的行為是否會產生變化。他們會開始自我約束,還是演變成更激烈的「捕撈競賽」?
  • 討論:資訊的公開對你的決策有什麼影響?「社會壓力」是有效的嗎?

第三階段:法規的介入

  • 設定:在遊戲中途開啟「總量管制」或「個人捕撈上限」。
  • 目標:讓學生體驗法規的限制作用,並思考其利弊。
  • 討論:這個規定公平嗎?如果你是村長,你會如何設定這個上限?對於違反規定的村民,應該有什麼樣的懲罰?

第四階段:邁向永續經營

  • 設定:開啟「公共投資」功能。
  • 目標:挑戰學生們從競爭轉向合作,共同規劃如何利用累積的財富,讓村莊的未來更加富足。
  • 討論:你願意犧牲個人眼前的利益,來投資公共建設嗎?如何建立信任機制,確保大家共同投入?

一個激發思辨的動態教室

這個互動程式「大家的村莊」具有高度的互動性,也有即時的數據反饋,身為一個會說故事的教師,你可以用各種後台工具去塑造這個故事走向,像是各種災難危機出現,導致魚群減少,或是其他因素導致魚群大增。讓學生在模擬環境中,體驗個人的決策、社會的趨勢對整體造成的影響,用系統性的角度去思考複雜的資源管理議題。

最終的目標不是找到一個「標準答案」,而是透過這個過程,激發學生的批判性思維,引導他們實際體驗從永續發展、社會合作與政策制定等議題。

怎麼開始玩?

我覺得你看了以上的說明,應該想要嘗試吧?

線上版本

我在render.com部署了這個線上遊戲

https://biogo.onrender.com/ 進去後點[Start a Room] ,用QRCODE讓學生登入後,活動列表選[commons]就可以進去遊戲了。

區網版本

如果你要教室網路玩這個,透過教師機當伺服器也可以,我之前都是這樣玩,自由度更高。你要教師機安裝node.js,然後安裝我的程式並執行,然後讓學生個人或分組用平板連上教師機。

https://github.com/ChihHsiangChien/bioGO


在瀏覽器中復刻 Gakken GMC-4 四位元微電腦

在個人電腦與智慧型手機普及的今天,我們很難想像一個只有 80 位元組(Bytes)程式記憶體、運算核心只有 4 位元(bit)的電腦是什麼樣子。

2009年的Gakken 推出了這個 GMC-4 (Gakken Micro Computer 4-bit)的微電腦,收錄在大人的科學第24期https://otonanokagaku.net/magazine/vol24/index.html

它的特別之處,就是讓電子愛好者親手接觸電腦程式底層邏輯-機器碼。好幾年前我買了這本書之後,我其實沒弄懂這到底在幹嘛?

不過後來學習了計算機組織與結構之後,我終於懂了那是做什麼了。原來是透過用機器碼寫程式。我們目前用的java script、python都是高階語言,是給人類看的語言。

這些高階語言在背後,其實最終都會被轉譯成低階的機器語言,才能由電腦硬體實際執行。而 GMC‑4 正是一台設計用來讓你跳過所有抽象層、直接「對硬體說話」的教具型微電腦。 你需要手動輸入一行一行的機器碼,設定暫存器、跳躍條件、控制流程,才能讓它執行一個最簡單的加減乘除、閃燈或倒數計時任務。沒有作業系統,沒有變數宣告,甚至連除錯器都沒有。你要完全理解它的 15 條指令集(OPCode),知道 A、B 暫存器、Y 記憶體指標與旗標(Flag)的角色,才能成功寫出一段程式。 也就是說,GMC‑4 可以讓你真實感受到「什麼叫做電腦」的機器,而正因為它的限制明確、架構單純,反而成為理解電腦本質、教學用模擬器與入門編碼邏輯的最佳起點。想真正理解「為什麼程式碼能跑起來」,都可以用這台小小的 GMC‑4來理解。不過純硬體的架構下,其實不容易理解裡頭寫了什麼,後來我就動起念頭想要把硬體做成網頁上的模擬器,重現這台經典的 4 位元微電腦。

想了解計算機原理的人或只是單純好奇,都可以玩玩這個 4 位元電腦。

模擬器介面巡禮


打開模擬器,您會看到一個復古風格的介面,有著 GMC-4 的主要硬體元件:


  1. 7 段顯示器 (7-Segment Display):這是主要的輸出裝置,用來顯示一個 4 位元的十六進位數字 (0-F)。

  2. 位址 LED (Address LEDs):這 7 顆綠色 LED 燈以二進位形式即時顯示「程式計數器 (Program Counter, PC)」的位址。

  3. 2-pin LEDs:這 7 顆黃色 LED 燈主要由 CAL 系列指令控制,用於顯示程式狀態或作為簡單的圖形輸出。

  4. 十六進位鍵盤 (Hex Keypad):從 0F 的按鍵,是您輸入程式碼和資料的主要工具。

  5. 功能鍵

  • A SET:設定記憶體位址。

  • INCR:將輸入的數值寫入當前記憶體位址,並將位址加一。

  • RUN:執行程式。

  • RESET:重置 CPU 狀態,但保留記憶體內容。

  • HARD RESET:清空所有記憶體並重置 CPU。

  1. 記憶體檢視器 (Memory View)

  • 左欄 (Raw):顯示程式與資料記憶體的原始十六進位碼。

  • 右欄 (Disassembled):將機器碼反組譯成人類可讀的助憶碼,有了它你更知道硬體裡在做什麼。

核心概念:4 位元電腦如何「思考」?

GMC-4 的核心是 4 位元架構,這意味著:


  • 暫存器寬度:CPU 內部的暫存器(如 A, Y)一次只能儲存一個 4 位元的數值(也就是 0-15,或十六進位的 0-F)。

  • 資料處理:所有運算都以 4 位元為單位。這也是為什麼它的鍵盤和顯示器都以十六進位為基礎。

  • 記憶體:它擁有極小的記憶體空間,分為 0x000x4F 的程式區和 0x500x5F 的資料區。

入門教學:撰寫你的第一個程式

接下來動手操作,感受一下最原始的程式設計方式。

暖身:寫入與讀取記憶體

我們的第一個目標是將數值 A 寫入記憶體位址 10,並驗證它。


操作步驟


  1. 按下 HARD RESET 清空所有狀態。7 段顯示器會顯示 F

  2. 依序按下 10A SET

  • 這個動作將程式計數器 (PC) 設定到 0x10。注意看,7 顆綠色的 Address LEDs 會顯示 0010000,也就是 16 的二進位表示法 (0x10 = 16)。7 段顯示器則會顯示 F,這是位址 10 目前的內容。

  1. 按下 AINCR

  • 解說:這會將數值 A 寫入 0x10 位址,然後 PC 自動前進到 0x11。您會看到右方的記憶體檢視器中,10: 的位置出現了 A


驗證:先RESET,將PC指回00,再次按下 10A SET 將 PC 指回 0x10。看看 7 段顯示器,是不是顯示 A 了呢?恭喜,你完成了最基本的記憶體操作!你作的事情就是指定記憶體的位址,寫入A,然後再回到記憶體的初始位置,然後再去檢查剛剛那個位址寫了什麼。

第一個程式:永不停止的計數器(0x1)

現在,來寫一個真正的程式。這個程式會讓 7 段顯示器從 1 開始,不斷地顯示到 6,然後再從 1 開始循環。


我有把這個程式寫成內建的,你先按下 RESET,再按下 1 (代表這組計數程式),最後按下 RUN,就可以載入這組程式並執行。

程式邏輯


位址

指令碼

反組譯

說明

00

8 1

TIA 1

將立即值 1 載入 A 暫存器 (A=1)

02

1

AO

將 A 暫存器的值輸出到 7 段顯示器

03

E 9

CAL SHTS

播放一個短音 (讓數字顯示有間隔)

05

9 1

AIA 1

將 A 暫存器的值加上立即值 1 (A=A+1)

07

C 7

CIA 7

比較 A 暫存器與立即值 7

09

F 0 2

JUMP 02

如果上一步比較結果不相等 (A != 7),則跳轉到 02 位址

0C

8 1

TIA 1

(如果 A=7) 重新將 1 載入 A 暫存器

0E

F 0 2

JUMP 02

無條件跳轉回 02,形成主迴圈


如果要自己輸入的話,就是這樣的操作步驟


  1. 按下 RESET (或 HARD RESET) 讓 PC 歸零。

  2. 依照上表的「指令碼」欄位,依序輸入: 8 INCR 1 INCR 1 INCR E INCR 9 INCR 9 INCR 1 INCR C INCR 7 INCR F INCR 0 INCR 2 INCR 8 INCR 1 INCR F INCR 0 INCR 2 INCR

  3. 輸入完成後,再次按下 RESET 將 PC 指回 00

  4. 按下 RUN


現在,您應該能看到 7 段顯示器上循環顯示 16 的數字,並伴隨著嗶嗶聲。您可以隨時按下 PAUSE 暫停,或 STEP 來逐一指令執行,觀察暫存器和記憶體的變化。

內建程式-電子琴 Organ(0x9)

本模擬器還有內建了一些範例程式。


操作步驟


  1. 按下 RESET

  2. 按下 9 (代表 Organ 程式)。

  3. 按下 RUN


此時,整個程式記憶體會被載入 Organ 程式的機器碼,按下 1-F 的按鍵會發出不同音階。看右方的反組譯碼,可以試著理解這個電子琴程式是如何運作的!


逐行解析一下它的機器碼。


位址

指令碼

反組譯

說明

00

0x0

KA

Keypad to A register。讀取鍵盤輸入,將按下的數字 (0-F) 存入 A 暫存器。如果沒有按鍵,則將 Flag 設為 1。

01

0xF 0x0 0x0

JUMP 00

如果 Flag 為 1 (表示上一步沒有按鍵),則跳轉回位址 00,形成一個等待迴圈。

04

0xE 0xB

CAL SUND

如果有按鍵 (程式執行到此),則執行 CAL 子指令 SUND,播放 A 暫存器中數值對應的音階。

06

0xF 0x0 0x0

JUMP 00

播放完音階後,無條件跳轉回位址 00,等待下一次按鍵。


這個程式展示的是電腦底層的基本輸入、條件判斷和輸出流程。


程式:音樂播放器 (Music Player - 0xA)

這個程式比電子琴複雜一些,它會自動播放儲存在資料記憶體中的一串音符,直到遇到結束標記。


資料 (data array): [1, 1, 5, 5, 6, 6, 5, 4, 4, 3, 3, 2, 2, 1, 0] 這串數字代表了「小星星」的音符序列。0 在這裡作為音樂結束的標記。


程式碼 (code array):


位址

指令碼

反組譯

說明

00

0xA 0x0

TIY 0

Transfer Immediate to Y。將立即值 0 存入 Y 暫存器。Y 暫存器在這裡當作資料記憶體的指標。

02

0x5

MA

Memory to A register。讀取記憶體位址 0x50 + Y 的內容到 A 暫存器。第一次執行時,Y=0,所以讀取 0x50 的內容 (音符 1)。

03

0xC 0x0

CIA 0

Compare Immediate with A。比較 A 暫存器的值和立即值 0。如果不相等 (A!=0),則 Flag 設為 1。

05

0xF 0x0 0xD

JUMP 0D

如果 Flag 為 1 (表示還沒到音樂結尾),則跳轉到 0D 位址去播放音符。

08

0xE 0x7

CAL ENDS

如果 A 等於 0,表示音樂結束,播放結束音效。

0A

0xF 0x1 0x8

JUMP 18

跳轉到程式結尾的停止迴圈。

0D

0xE 0xB

CAL SUND

播放音符。播放 A 暫存器中音符對應的音階。

0F

0xB 0x1

AIY 1

Add Immediate to Y。Y = Y + 1,讓指標指向下一個音符。

11

0x8 0x9

TIA 9

設定一個固定的延遲時間。

13

0xE 0xC

CAL TIMR

執行延遲,作為音符之間的間隔。

15

0xF 0x0 0x2

JUMP 02

無條件跳轉回主迴圈的開頭,讀取下一個音符。

18

0xF 0x1 0x8

JUMP 18

程式停止。一個無限迴圈,讓程式停在這裡。


這個程式利用 Y 暫存器作為指標來循序讀取資料,是進階的程式設計技巧。


現在,你可以參考指令集來修改程式,或是設計簡單的機器碼小程式了。像是試著修改計數器程式,讓它數到 F載入其他的內建程式,研究它們的程式碼。