iT邦幫忙

2022 iThome 鐵人賽

DAY 13
0
Modern Web

為期 N 天的 react 小冒險系列 第 13

用react hook寫一個骰子遊戲吧-下-day 13

  • 分享至 

  • xImage
  •  

繼續把骰子遊戲寫完~回顧一下,昨天達成了
1. 產生隨機骰子點數的函式
2. 將骰子點數作為 property 傳送到子元件 Dice 中,讓子元件顯示出對應的點數面

接下來把這幾點補完

  1. 玩家選擇的答案(大/小)
  2. 遊戲是否為開始狀態(set start flag),未開始前得先選答案(大或小),才進行投骰子
  3. 遊戲結果為贏還是輸

新增 GameResult.js 作用為顯示遊戲結果,接收兩個 props(點數,本輪遊戲選擇的回答)
新增 AnsBtn.js 作用為玩家猜測點數答案的按鈕,接收兩個 props(本輪遊戲選擇的回答 , onClick AnsBtn 時執行的 function)

別忘了在 Dash.js 中補上 控制遊戲是否開始 / 設定本輪回答答案的 useState

const [gameStart, setStart] = useState(false);
const [answer, setAns] = useState(null);

新增要傳到 AnsBtn 中執行的 function handleAnsClick
handleAnsClick 中 要做的事

  1. 設定遊戲為開始狀態,當遊戲開始後才出現擲骰子按鈕
  2. 設定 本輪遊戲時選擇的回答

一樣在 Dash.js 內

...
function handleAnsClick(evt) {
    setStart(true);
    let ans = null;
    evt.target.innerHTML === "大" ? (ans = "big") : (ans = "small");
    setAns(ans);
  }
...

照慣例 import child component (GameResult / AnsBtn)到主界面 Dash.js 上,因應新增 GameStart 為 true|false 要 render 的項目,也修改要 return 的內容
特別注意的是,這裏將整個 handleAnsClick function 作為 props 傳入到 AnsBtn 這個子元件中

Dash.js

import GameResult from "./GameResult.js";
import AnsBtn from "./AnsBtn.js";
...
return (
    <>
      <Dice diceNumber={"0"} diceSrc={diceSrc} />
      {gameStart === true ? (
        <GameResult diceRes={diceNum} answer={answer} />
      ) : (
        <p>猜大還是猜小呢?</p>
      )}
      {gameStart === true ? (
        <button
          onClick={() => {
            let gameRes = generateDiceNumber();
            setDiceImg(gameRes.src);
            setDiceNUum(gameRes.diceNumber);
            setStart(false);
          }}
        >
          投骰子
        </button>
      ) : (
        <>
          <AnsBtn ans="big" onClick={handleAnsClick} />
          <AnsBtn ans="small" onClick={handleAnsClick} />
        </>
      )}
    </>
  );

切換到 AnsBtn.js

export default function AnsBtn(props) {
  const { ans, onClick } = props;
  return <button onClick={onClick}>{ans === "big" ? "大" : "小"}</button>;
}

GameResult.js
判定顯示結果為贏還是輸
骰出點數與回答有幾個可能,簡單列出來

回答大 回答小
骰出123
骰出456
export default function GameResult(props) {
  const { diceRes, answer } = props;
  let gameRes = "";

  if (diceRes > 3) {
    answer === "small" ? (gameRes = "輸") : (gameRes = "贏");
  } else {
    answer === "small" ? (gameRes = "贏") : (gameRes = "輸");
  }
  return (
    <>
      <p>
        骰出了{diceRes},你選擇{answer === "small" ? "小" : "大"},你{gameRes}了
      </p>
    </>
  );
}

這時候就可以開始進行骰子遊戲了~

今天的codesandbox在這裡

延長挑戰情境題..

  1. 目前這個版本有Bug XDDD 進行回答後會一併骰出下一輪的點數,需要修復
  2. 只有玩單顆骰子猜大小有點無聊,將遊戲改成常見的擲骰子遊戲-十八啦
  3. 讓骰子變成 3d 的樣子

補充十八啦玩法

一人丟四顆骰子
如果四顆點數皆不同,稱為無面,則重新擲(2,4,5,1 => 重丟)
如果有三顆同點數,則重丟骰子(2,2,2,5 => 重丟)
如果有兩顆同點數,則計算其他兩顆點數相加總和(1,1,3,6 => 9)
如果兩顆同,另兩顆也同,則取較大的那組重複點數相加總和(4,4,5,5 => 10)
如果四顆皆同點數 稱作豹子(1,1,1,1 => 最小的豹子 / 6,6,6,6 => 最大的豹子)
擲出豹子或兩顆為6+兩顆同點 則為最大,直接判定該局勝利

參考資料

https://stackoverflow.com/questions/55726886/react-hook-send-data-from-child-to-parent-component

3d dice layout
https://codepen.io/lenasta92579651/pen/yLeVmdW?editors=1111
https://codepen.io/johngaetani05/pen/wYEQoe


上一篇
用react hook寫一個骰子遊戲吧-上-day 12
下一篇
用 react hook 寫一個 bmi 計算機-day14
系列文
為期 N 天的 react 小冒險30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言