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?

神経衰弱ゲームを CSS 3D フリップとイミュータブル状態で実装した

0
Posted at

作ったもの

Memory Gamehttps://sen.ltd/portfolio/memory-game/

スクリーンショット

  • 4 難易度(12 / 16 / 36 / 64 枚)
  • 5 テーマ(絵文字 / 数字 / アルファベット / 図形 / ひらがな)
  • CSS 3D フリップアニメーション
  • 手数カウンタ + タイマー
  • 難易度別ベストスコア(localStorage)
  • クリア時に紙吹雪

vanilla JS、ゼロ依存、ビルド不要node --test で 38 ケース。

イミュータブル状態

{
  cards: [{ id, value, flipped, matched }],
  firstCard: null | cardId,
  moves, matches, started, startedAt
}

firstCard が「1 枚目めくって 2 枚目待ち」の状態を表す。全関数が新しい state を返す純関数。

クリック中の多重フリップを防ぐ

if (card.flipped || card.matched) return state;

このガードがあれば「判定中にクリックしても何も起きない」が自然に実現できる。個別にタイマー状態を持つより安全。

CSS 3D フリップ

.card-inner {
  transform-style: preserve-3d;
  transition: transform 0.4s;
}
.card.flipped .card-inner {
  transform: rotateY(180deg);
}
.card-front, .card-back {
  backface-visibility: hidden;
}
.card-back { transform: rotateY(180deg); }

backface-visibility: hidden が鍵。これがないと裏面と表面が重なって見える。正面を向いている方だけ描画される。

Fisher-Yates シャッフル

for (let i = arr.length - 1; i > 0; i--) {
  const j = Math.floor(Math.random() * (i + 1));
  [arr[i], arr[j]] = [arr[j], arr[i]];
}

全順列について一様。sort(() => Math.random() - 0.5) は偏るので絶対使わない。

シリーズ

100+ 公開ポートフォリオ シリーズの #99 — 目標まであと 1 つ。

0
0
1

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?