0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Reactで今さらズンドコキヨシなコンポーネントを実装してみる

Posted at

「ズンドコキヨシ」って、その昔に何度もこすり倒されたネタだから「今さら?」感は満載だけど、まぁそんな忘れたころにリバイバルする、みんな大好きズンドコキヨシだよね。

ランダム生成明確な終了条件があるおかげで、ちょっとしたコードのサンプルにするにはちょうどいい題材だよね。

今回の記事では、F-Boxという「値を箱に詰める」コンセプトのライブラリを使って、このズンドコキヨシを TypeScript と React で淡々と再現してみるよ。
F-Box 自体は決して「React 専用の状態管理ライブラリ」ってわけじゃないんだけど、RBoxという仕組みを使えば状態管理ができるようになってて、さらにf-box-reactを組み合わせると React のコンポーネントと自然に連携できるようになるんだ。

ズンドコキヨシとは?

一応流れをおさらいすると、こんな感じだね。

  1. 「ズン」か「ドコ」をランダムで並べる
  2. 直近 5 回が「ズン」「ズン」「ズン」「ズン」「ドコ」になったら
  3. 「キ・ヨ・シ!」を出して終了

この単純なロジックがいいよね。
最後の「キ・ヨ・シ!」が出るまでひたすらズンドコし続ける感じが妙にクセになるんだ。

全体コード

では、まずは完成版のコードをまとめて載せるね。
TypeScript と React を前提にしていて、F-Box のRBoxと、その React 用のフックであるuseRBoxを使っているよ。
後の解説でポイントを補足するからサラッと眺めてみて。

import { RBox } from "f-box-core"
import { useRBox } from "f-box-react"

type ZUNDOKO = "ズン" | "ドコ" | "キ・ヨ・シ!"

const zun = "ズン"
const doko = "ドコ"
const kiyoshi = "キ・ヨ・シ!"

const zundokoBox = RBox.pack<ZUNDOKO[][]>([])

const rnd = () => Math.random() < 0.5

const zundoko = (s: ZUNDOKO[]): ZUNDOKO =>
  s.slice(-5).join("") === zun.repeat(4) + doko ? kiyoshi : rnd() ? zun : doko

const next = (s: ZUNDOKO[]) => RBox.pack([...s, zundoko(s)])

const run = (s: ZUNDOKO[]): RBox<ZUNDOKO[]> =>
  s.includes(kiyoshi)
    ? RBox.pack(s)
    : RBox.pack(s)
        [">>="](next)
        [">>="](run)

const set = (s: ZUNDOKO[]) => {
  zundokoBox.setValue((prev) => [...prev, s])
  return zundokoBox
}

const start = () =>
  RBox.pack([])
    [">>="](run)
    [">>="](set)

export default function ZunDokoKiyoshi() {
  const [zundoko] = useRBox(zundokoBox)

  return (
    <>
      <button onClick={start}>ズンドコキヨシ</button>
      <ol>
        {zundoko.map((v, i) => (
          <li key={i}>{v.join(" ")}</li>
        ))}
      </ol>
    </>
  )
}

デモ

image.png

コード解説

ZUNDOKO 型

type ZUNDOKO = "ズン" | "ドコ" | "キ・ヨ・シ!"
  • まずは「ズン」か「ドコ」か「キ・ヨ・シ!」な文字列を表すユニオン型を定義しておくよ。

F-Box と RBox

import { RBox } from 'f-box-core';

const zundokoBox = RBox.pack<ZUNDOKO[][]>([])

この RBox が F-Box の中心となる型で、「箱」の概念を扱えるようになるんだ。

  • RBox.pack は、与えられた値を箱に詰めてRBoxを返す関数。
  • zundokoBoxZUNDOKO[][]を初期値にしたRBox。ここに結果の値をセットしてコンポーネント上でリスト表示する。

F-Box 自体はただの箱を扱うだけなんだけど、RBoxを使うとリアクティブに値が変わる仕組みがあって、f-box-reactuseRBox と組み合わせると、React のコンポーネントでその値を購読できるようになるよ。

useRBox

import { useRBox } from "f-box-react"

export default function ZunDokoKiyoshi() {
  const [zundoko] = useRBox(zundokoBox)
  ...
  • Reactコンポーネントの中で useRBox を呼び出すと、zundokoBox に詰めた配列の最新の状態を受け取れる。
  • 値が更新されるとコンポーネントが再レンダリングされる。

ランダム判定と zundoko 関数

const rnd = () => Math.random() < 0.5
  • シンプルに 1/2 の確率で true / false
  • 「ズン」か「ドコ」をランダムで決めるのに使ってるだけ。
const zundoko = (s: ZUNDOKO[]): ZUNDOKO =>
  s.slice(-5).join("") === zun.repeat(4) + doko ? kiyoshi : rnd() ? zun : doko
  • もし直近 5 回が「ズン」「ズン」「ズン」「ズン」「ドコ」だったら「キ・ヨ・シ!」。
  • そうでなければランダムに「ズン」か「ドコ」。
  • slice(-5).join('') で末尾 5 つを文字列連結して判定してるだけだよ。

ループ処理

const next = (s: ZUNDOKO[]) => RBox.pack([...s, zundoko(s)])
  • 配列 s の末尾に「ズン」「ドコ」または「キ・ヨ・シ!」を 1 つ追加して、新しい配列を箱に詰める。
  • “次のステップへ進む”って感じの処理だね。
const run = (s: ZUNDOKO[]): RBox<ZUNDOKO[]> =>
  s.includes(kiyoshi)
    ? RBox.pack(s)
    : RBox.pack(s)
        [">>="](next)
        [">>="](run)
  • もし s にすでに「キ・ヨ・シ!」が含まれていたら終了。
  • 含まれてなければ next で 1 ステップ進めて、その結果をさらに run に渡す。
  • この ['>>='](...) って書き方はちょっと特殊だけど、「箱の中身を次の関数に渡して、新しい箱を返す」ってイメージで読むとわかりやすいと思うよ。

結果のセットと実行

const set = (s: ZUNDOKO[]) => {
  zundokoBox.setValue((prev) => [...prev, s])
  return zundokoBox
}
  • run の最終結果(ズンドコの流れが終わった配列)を、zundokoBox にまとめて保存してる。
  • ボタンを押すたびに結果をリストアップしていくために、履歴を蓄積してるんだ。
const start = () =>
  RBox.pack([])
    [">>="](run)
    [">>="](set)
  • ボタンが押されたらこの関数が呼ばれる。
  • 空の配列を用意して run でズンドコを開始し、最終的に set で完了。
  • この一連の流れが['>>=']で繋がってるのが面白いところだね。

実行してみると

  • 「ズンドコキヨシ」ボタンを押すと、画面に「ズン」「ドコ」とかがランダムで生成されて、最後に「キ・ヨ・シ!」が登場するまで続く。
  • 終了すると、その結果がリストに追加されるので、何度でも「ズンドコ」できるよ。

おわりに

F-Box の RBoxを使うと、箱に詰めた値を「次の処理」「その次の処理」と渡していく仕組みがシンプルに書けるし、f-box-reactを併用すれば React コンポーネントとも簡単に連携できるよ。

興味を持ったら、ぜひあなたなりにズンドコをアレンジしてみたり、全然別のネタでも RBox を使って試してみると面白いと思う。

それじゃ、ズンドコライフを楽しんでね!

F-Box ドキュメント

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?