Skip to content

👍 202608 神経衰弱 勉強会資料 - #51

Open
m-sato-310 wants to merge 2 commits into
mainfrom
add/shinkei-suijaku-2026
Open

👍 202608 神経衰弱 勉強会資料#51
m-sato-310 wants to merge 2 commits into
mainfrom
add/shinkei-suijaku-2026

Conversation

@m-sato-310

Copy link
Copy Markdown
Contributor

JavaScript で 4×4 の神経衰弱ゲームを作る中級講座の資料です。
所要時間 180 分、オンライン開催、経験者コース向けに作成しました。

目的

ゲームを作る過程で、Webアプリを支える 3 つの考え方を体験することを目的にしています。

  • 状態 — 今どうなっているかを変数で表す
  • イベント — ユーザー操作に反応する
  • 時間 — タイマーや待ち時間で画面を動かす

この 3 つが、静的な Webページと Webアプリの一番大きな違いです。
神経衰弱を作り切ること自体は目的ではないので、アルゴリズムの詳細やフレームワークの設計思想は扱いません。

対象

何らかの言語で変数・if・関数・配列を書いたことがあれば参加できます。
JavaScript は初めてでも構いません。
HTML と CSS は配布コードに含めてあるので、参加者は script.js に集中します。

構成

  • Chapter 1: JS で画面を組み立てる (23 分) — カードを盤面に並べる
  • Chapter 2: イベントと状態 (27 分) — クリックでカードをめくる
  • Chapter 3: 状態遷移と非同期 (28 分) — 一致判定と待ち時間
  • 休憩 (10 分)
  • Chapter 4: カードをシャッフル (10 分) — 毎回ちがう並びで遊べるようにする
  • Chapter 5: 時間で動く画面 (28 分) — タイマー、手数、クリア判定
  • Chapter 6: 状態を初期化する (15 分) — リセット機能

章の合計が 131 分、導入とまとめが 22.5 分、休憩が 10 分で 163.5 分。
末尾の応用課題 4 枚 (8 分) を全部話すと 171.5 分で、180 分枠に収まります。
付録 7 枚は当日飛ばす前提です。

ファイル

  • slide.md / slide.html — Marp スライド 81 枚 (章内 59 / 章外 14 / 休憩 1 / 付録 7)
  • examples/start/ — 配布時のコード骨格。script.js
  • examples/complete/ — 完成コード。講師の答え合わせと参加者の最終参照用
  • examples/snapshots/ — 各章末の script.js (`ch1.j
  • examples/challenges/ — 応用課題のうち、分量が大きいものの実装例
  • diagrams/ — mermaid (.mmd) から生成した SVG
  • screenshots/ — 各チェックポイントの画面

演習

3 つのモードを使い分けます。

  • 自力 (2 箇所) — 要件とヒントだけを見て、コードを見ずに書く
  • 記述 (7 箇所) — 【A】 等の穴を埋める
  • コピペ — 完成コードをそのまま貼る

講座のコア概念は自力、ロジックの骨格は記述、道具立てはコピペに割り当てています。
演習の合計は 31 分です。

オンライン開催への対応

講師が参加者の手元を見られないので、脱落と進捗の把握を資料側で担保しています。

  • 各章のチェックポイントに追いつき用のコード (chN.js.js` を丸ごと置き換えれば次の章から合流できます
  • examples/*/debug.js に診断パネルを同梱しました。章ごとの進捗、直近のエラー、getElementById の id やイベント名の打ち間違いを表示し
    ます
  • 演習には制限時間を表示します。書けたらリアクションで知らせてもらい、時間になったら答えを出します

@m-sato-310

Copy link
Copy Markdown
Contributor Author

@takerucam @rough-github @koduno

経験者コースの勉強会資料です!!

長くなってしまいましたが、レビューお願いします 🙇 🙇 🙇

@koduno koduno left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Chapter 2まではみました 👀
気になる箇所コメント残してます 🙇


そこで HTML には空の入れ物だけ置いて、中身は JS が作ります。

DOM とは、ブラウザが持っている HTML のツリーのことです。JavaScript から読み書きできます。今日やるのは 2 つだけで、ツリーから要素を探す (1-2) と、新しい要素を作って差し込む (1-3) です。

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

「DOM とは、ブラウザが持っている HTML のツリーのことです」が伝わるかがちょっと不安です。

図などがあるとわかりやすくなるかもしれません

https://developer.mozilla.org/ja/docs/Web/API/Document_Object_Model

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a3b763b - DOM の導入を 2 枚に分けて盤面のツリー図を追加
7cf2b84 - DOM の説明を作る側に寄せる

index.html のツリー図を入れて、導入を「入れ物だけ置く」と「JS から作る」の 2 枚に分けました 🙏

}
```

`card` の中に `inner`、その中に `front` と `back` を入れた入れ子構造を組み立てて `return` します。

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

できあがるHTMLがあるとわかりやすいかも

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ac62336 - createCard ができあがらせる HTML を見せるスライドを追加
389d100 - DOM のツリーを図で見せる

createCard("🍎", 0) の戻り値の HTML を出すスライドと、その入れ子のツリー図を足しました 🙏


- `document.createElement("div")` — 新しい `<div>` 要素を作る
- `element.className = "..."` — class 属性を設定
- `element.textContent = "..."` — テキストとして中身を書き換える (安全)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(安全) ← 何に対して安全なのかが読み取れないかなと思ったが、喋りで説明するならOK

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

b56c5e2 - DOM API の説明から「安全」という表現を外す

「中身の文字列を置き換える」に書き換えました 🙏


`deck` の各要素をカードにして `#board` に並べる `renderBoard` 関数を書きます。今回初めて使うもの:

- `parent.replaceChildren()` — 親の中身を全部削除 (`innerHTML = ""` の安全版)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

innerHTML が安全でないという前提がありますが、innerHTMLの説明はなくその前提があるかがちょっとふわんです

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

b56c5e2 - DOM API の説明から「安全」という表現を外す

innerHTML への言及ごと外して、「親の中身を全部削除」だけにしました 🙏


<!-- _class: tight -->

## 名前のない関数 (アロー関数)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

名前のない関数はアロー関数ではなくどちらかというと無名関数かなと思いました。ただ、あまり最初の方に区別する必要はないのかな〜

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions#%E8%A7%A3%E8%AA%AC

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

abf1c59 - アロー関数の説明を 2-3 補足に統合する
3d8a728 - addEventListener の説明を使っているスライドに移す

独立していた「名前のない関数 (アロー関数)」のスライドをやめて、2-3 補足で addEventListener に渡す文脈だけを説明する形にしました 🙏

- `"1" == 1` は `true` (型を無視して比較)
- `"1" === 1` は `false` (型が違うので不一致)

`==` は自動で型変換をかけるため意図しない結果になりがち。特別な理由がない限り `===` を使うのが定石です。

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

型の概念をどこまで理解しているのか

具体例があるともっと理解しやすいかも

console.log(1 === 1);
// 予想される結果: true

console.log("1" == 1);
// 予想される結果: true

console.log("1" === 1);
// 予想される結果: false

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

32f086a - === の説明に型の意味を補う

型は文字列か数値かの区別であることを添えて、"1" === 1 が false になる理由をその場で説明しました 🙏


<!-- _class: lead -->

# Chapter 1

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

どこかで目次が欲しい

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

b9e910b - 目次をスライドに移して README を参加者向けの案内に絞る

「今日の流れ」として章一覧のスライドを追加しました 🙏

const boardEl = document.getElementById("board");
```

この資料では、DOM 要素を入れる変数の末尾に `El` を付けて統一します。

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

El の説明が欲しい

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

f3783ac - El が Element の略であることを補う

El (Element の略) と書き足しました 🙏


`dataset` は DOM 要素に自前のデータを紐付ける仕組みです。

- `card.dataset.symbol = "🍎"` と書くと HTML に `data-symbol="🍎"` として保存される

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dataset について、何を目的としてどんなことができるものなのかの説明がほしい

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

df429ff - 1-3 補足を DOM API 一覧と dataset の 2 枚に分ける

dataset だけで 1 枚にして、自分で決めた名前でデータを持たせられること、card.textContent だと ?🍎 になるので絵柄だけ取り出すために使っていることを書きました 🙏

<button class="timer-btn" data-delta="60">+</button>
</div>

```javascript

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

一旦コピーしないとだめ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

9bd2e02 - 1-4 でコードブロックをコピペしてもらうことを明記する

「コードブロックをそのまま script.js に貼って、【A】〜【B】を書き換えましょう」と明記しました 🙏

- すでにめくったカードは再クリックしても反応しない
- 2 枚めくったあとの判定中は、クリックしてもめくれないようにする (Chapter 3 で使う)

このために状態変数を導入します。

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

このために とあるがつながりが分かりづらいと思いました。

  • すでにめくったカードは再クリックしても反応しない
    • -> カードがクリックされたかどうかを記録する
  • 2 枚めくったあとの判定中は、クリックしてもめくれないようにする
    • -> 2枚めくったかどうかを記録する

上記2つの記録を変数として持ちます(状態変数)

のようにもう少しわかりやすく書いても良いのかなと思いました

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ab8252f - 状態変数を導入する理由を書く

いただいた流れに沿って、ルールを実装するには状態を変数に持つ必要がある → それを状態変数と呼ぶ、と繋げました 🙏


- A: `lockBoard` — 判定待ちの間はクリック無視。Chapter 3 で意味が生きる
- B: `"flipped"` — 配布 CSS がこのクラスで表向きアニメを流す
- C: `add` — B と反対の操作は `remove` (Chapter 3 で使う)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

B と反対の操作は remove

B と反対の操作 の意味がよくわからない🤔
どのB?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a84978e - 2-2 の説明から他章への参照を外す
07ba16e - クラスの付け外しのスライドを足す

「B」はミスです 🙏
「クラスを付けるのが add」と直接書く形に変えました。
あわせて classNameclassList の違いを説明するスライドを 2-1 の前に追加しています 🙏

<button class="timer-btn" data-delta="60">+</button>
</div>

`handleCardClick` の `secondCard = card;` と、3-1 で書いた `const isMatch = ...` の間に、2 枚目をめくった瞬間の処理を 2 行書きます。この 2 行が「状態を変えたら描画を更新する」という型です。

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ここもだけど、下にやることが書かれているのにここにもやることが書かれていて分かりづらいです。やることはまとめが方がいいかと思います

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

676fc66 - 演習の書き足し先を具体的に書く

本文は書く場所の指示だけに絞って、手順はやること側にまとめました 🙏


## 5-2 答え合わせ

```javascript

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

一応どのメソッド内かを書いたほうが親切です

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

676fc66 - 演習の書き足し先を具体的に書く
5402c1c - 5-2 答え合わせの書き足し位置を具体的に書く

答え合わせにも「handleCardClick の中、secondCard = card; の直後、判定の前です」を足しました 🙏


貼ったコードに出てくるものを押さえておきます。

- `startTime`: `Date.now()` で取った開始時刻 (ミリ秒)。経過秒は「今 − 開始」で出る

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

経過秒は「今 − 開始」で出る ですが、経過秒は Date.now() - startTime で出る、のほうがわかりやすいかなと思いました

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a0ae492 - 経過秒の求め方を式で書く

(Date.now() - startTime) / 1000 と式で書きました 🙏


## 5-4. タイマー開始を組み込む

<span class="tag-write">記述</span> `handleCardClick` の 1 枚目分岐に 1 行追加します。【A】を埋めましょう。

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1枚目分岐じゃわからないので具体的なコードを提示すべきかと思います

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

676fc66 - 演習の書き足し先を具体的に書く

handleCardClickif (!firstCard) の分岐」に書き換えました 🙏


## 5-4. タイマー開始を組み込む

<span class="tag-write">記述</span> `handleCardClick` の 1 枚目分岐に 1 行追加します。【A】を埋めましょう。

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

全体的にですが変数名と関数名を混乱しちゃう可能性があるので、変数名は xxxx、関数名は xxxx() のように () をつけるなどして区別しやすいようにしたほうがいいかもです

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

69e1b22 - 一覧のメソッドにカッコを付けて変数と区別する

まとめと付録の一覧で、メソッドに () を付けて変数と区別しました 🙏

@m-sato-310

Copy link
Copy Markdown
Contributor Author

ご指摘ありがとうございます 🙇🙇

まだまだ気になる点があるので今後別 PR で修正すると思います 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants