🐙 三位漁夫平分籮筐 - 運算思維遊戲
大家好,這裡介紹一個「三位漁夫」經典謎題的 HTML + JavaScript 實作, 透過簡單的前端互動,體驗如何運用「運算思維」解決「每人分得相同重量」的難題。
🐟 問題描述
甲、乙、丙三位漁夫出海捕魚,帶了 21 隻籮筐回來: 7 筐滿 (滿筐魚)、7 筐半 (半筐魚)、7 筐空 (沒有魚) 。 假設每 7 筐滿魚的重量相同,每 7 筐半魚的重量相同, 該怎麼在不重新倒魚的前提下,把這些籮筐平分成 3 份,且每人都剛好拿到魚的總量 = 3.5 筐?
也就是說,最終分配結果需同時滿足:
- 每位漁夫有 7 隻籮筐
- 籮筐內的魚總量 = 3.5 筐 (對照: 滿筐=1 筐, 半筐=0.5 筐, 空筐=0 筐)
🧮 解題思維
我們在程式中,先以陣列記錄 21 隻籮筐各自的型態 (滿/半/空);再透過操作,使每位漁夫領取不同數量的筐。 檢查時,只要確定「每位漁夫 7 筐」且「魚量 = 3.5 筐」,即判定成功。
以下範例提供基本的點擊互動 (或可擴充為拖拉), 讓你體驗將籮筐分給不同漁夫的過程。 最後按下「檢查」按鈕,檢測是否正確。
🔧 程式範例
<!DOCTYPE html>
<html lang="zh-Hant">
<head>
<meta charset="UTF-8">
<title>三位漁夫平分籮筐 - 小遊戲</title>
<style>
/* 略: 與上面程式碼中 CSS 類似,這裡可自行調整外觀 */
</style>
</head>
<body>
<h1>三位漁夫平分籮筐</h1>
<div id="pool" class="basket-area"></div>
<div class="fisher-container">
<div class="fisher-column">
<h3>漁夫 A</h3>
<div id="aArea" class="fisher-area"></div>
</div>
<div class="fisher-column">
<h3>漁夫 B</h3>
<div id="bArea" class="fisher-area"></div>
</div>
<div class="fisher-column">
<h3>漁夫 C</h3>
<div id="cArea" class="fisher-area"></div>
</div>
</div>
<div class="button-row">
<button id="checkBtn">檢查</button>
<button id="resetBtn">重置</button>
</div>
<div id="message" class="message"></div>
<script>
// 資料結構: 21 籮筐 (7 滿、7 半、7 空)
let baskets = [];
function initBaskets() {
baskets = [];
for(let i=0; i<7; i++){
baskets.push({ type: 'full', emoji: '🈵', owner: 'pool' });
baskets.push({ type: 'half', emoji: '🈶', owner: 'pool' });
baskets.push({ type: 'empty', emoji: '🈳', owner: 'pool' });
}
}
function renderAll() {
// DOM
const pool = document.getElementById('pool');
const aArea = document.getElementById('aArea');
const bArea = document.getElementById('bArea');
const cArea = document.getElementById('cArea');
pool.innerHTML = '';
aArea.innerHTML = '';
bArea.innerHTML = '';
cArea.innerHTML = '';
baskets.forEach((b, idx) => {
const span = document.createElement('span');
span.className = 'basket';
span.textContent = b.emoji;
// 點擊 => 輸入要把此籮筐給誰
span.addEventListener('click', () => {
assignBasket(idx);
});
if(b.owner === 'pool') {
pool.appendChild(span);
} else if(b.owner === 'A') {
aArea.appendChild(span);
} else if(b.owner === 'B') {
bArea.appendChild(span);
} else {
cArea.appendChild(span);
}
});
}
// 點擊 => 使用者輸入要分給誰 (A/B/C/pool)
function assignBasket(index) {
const target = prompt("要分給哪位漁夫? (A/B/C), 或輸入 'pool' 放回尚未分配.\n目前持有者: "
+ baskets[index].owner.toUpperCase());
if(!target) return;
const t = target.trim().toUpperCase();
if(['A','B','C','POOL'].indexOf(t) === -1) {
alert("請輸入 A/B/C/pool 其中之一");
return;
}
// 檢查是否超過 7 筐
if(t !== 'POOL') {
const countTarget = baskets.filter(b => b.owner === t).length;
// 若原本不在該區 且 目標區已滿 => 報錯
if(countTarget >= 7 && baskets[index].owner !== t) {
alert(t + " 已有 7 個籮筐, 無法再放!");
return;
}
}
baskets[index].owner = (t === 'POOL') ? 'pool' : t;
renderAll();
}
// 按下「檢查」
function checkResult() {
const A = baskets.filter(b => b.owner === 'A');
const B = baskets.filter(b => b.owner === 'B');
const C = baskets.filter(b => b.owner === 'C');
if(A.length !== 7 || B.length !== 7 || C.length !== 7) {
showMessage("分配錯誤: 每位漁夫都要有 7 個籮筐!", false);
return;
}
// 計算魚量
const fishCount = arr => {
let sum = 0;
arr.forEach(bb => {
if(bb.type === 'full') sum += 1;
if(bb.type === 'half') sum += 0.5;
});
return sum;
};
const fA = fishCount(A);
const fB = fishCount(B);
const fC = fishCount(C);
// 都要是 3.5
if(Math.abs(fA - 3.5) < 0.0001 && Math.abs(fB - 3.5) < 0.0001 && Math.abs(fC - 3.5) < 0.0001) {
showMessage("恭喜! 成功分配, 每人都拿到 3.5 筐魚!", true);
} else {
showMessage(
"每人都要 3.5 筐魚才行! A="+fA+" B="+fB+" C="+fC,
false
);
}
}
function showMessage(msg, success) {
const m = document.getElementById('message');
m.textContent = msg;
if(success) {
m.classList.add('success');
} else {
m.classList.remove('success');
}
}
function resetGame() {
initBaskets();
renderAll();
showMessage("", false);
}
document.getElementById('checkBtn').addEventListener('click', checkResult);
document.getElementById('resetBtn').addEventListener('click', resetGame);
// 初始化
resetGame();
</script>
</body>
</html>
🔑 解題邏輯
- 先以陣列
baskets[]建立 21 筆籮筐資料 (7x「滿」、7x「半」、7x「空」),並以owner屬性表示該筐的持有者 ('pool','A','B','C')。 - 透過點擊籮筐,呼叫
assignBasket(),彈出一個prompt讓使用者輸入目標所有者。若該漁夫已有 7 筐,則不允許再放。 - 按下「檢查」時,驗證每位漁夫是否拿到 7 筐,以及籮筐中魚量是否剛好是 3.5 筐(滿=1.0、半=0.5、空=0)。
- 若全部符合,顯示「恭喜!」,否則指出錯誤原因。
🤔 運算思維教學重點
-
資料結構:將 21 個籮筐以物件方式紀錄 (屬性包含
type、emoji、owner), 便於動態更新與查詢。 - 條件與限制:每位漁夫不得超過 7 個籮筐;魚量總數需為 3.5 筐。 這些都需在操作 (點擊籮筐) 與驗證 (檢查) 時進行判斷。
-
狀態更新:每次點擊籮筐,就修改
owner,再重新渲染網頁 (DOM 操作)。 - 邏輯推理:用運算思維 (程式判斷) 取代人在紙上計算或手動分配,實現遊戲化互動。
🎉 結語
透過以上 HTML + JavaScript 教學範例,我們將「三位漁夫平分籮筐」的問題遊戲化, 不但可以更直觀地操作籮筐分配,也可透過程式的「檢查機制」輔助我們檢驗正確性。
希望這個示例能幫助你熟悉運算思維、條件判斷以及前端互動設計。
有興趣的朋友可再進一步優化介面,如改成拖曳操作或加入更多動畫與提示。
祝大家學習愉快,Happy Coding!