3*3のスライドさせるあれをJavaScriptで作ってみた
正式名称良く分からないですが、スライドさせるパズルを作ってみました。
- HTML / CSS / JavaScript(vanillaJS)のフロントエンドのみの構成
- GitHubpagesでホスト
- クリックまたはタップのみのシンプル操作
- CSSトランジションで数字パネルをすーっと動かす感じに制御 #これがやってみたかった
デモ
ソース
htmlについて
html
<!DOCTYPE html>
<html lang="ja">
- HTML文書の開始。lang="ja" は日本語向けであることを明示します。
head
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Slide Puzzle</title>
<link rel="stylesheet" href="style.css" />
</head>
<head>
内の要素の意味:
要素 | 内容 |
---|---|
<meta charset="UTF-8"> |
日本語など多言語対応の文字コード設定 |
<meta name="viewport"...> |
スマホなど小画面でも拡大縮小せずに表示できる設定 |
<title> |
ブラウザのタブに表示されるページタイトル |
<link rel="stylesheet"...> |
外部CSS(style.css)を読み込む指定 |
- ★コメントでOGP対応の提案いただきました。是非確認してみてください★
body
<body>
<div class="container">
- container クラスで全体のレイアウトを中央揃え&縦方向に整えます(CSSに定義)
ステータス表示
<div class="status">
<span id="timerLabel">Time: <span id="timer">0.0</span> s</span>
<span id="clearMessage" class="hidden">Clear !!</span>
</div>
- タイマー表示:ゲーム中の経過時間を表示。初期は 0.0 秒
- クリアメッセージ:ゲームをクリアすると hidden が外れて "Clear !!" が表示されます
パズル盤面
<div id="board" class="board"></div>
- ここにJavaScriptがパネルを動的生成して挿入します
- 盤面は 3x3の正方形で、CSSの position: relative を使って中に absolute でタイルを配置します
ボタン(スタート/再挑戦)
<button id="startBtn" class="fixed-button">START</button>
- ゲーム開始/再挑戦をコントロールするボタン
- 状態に応じてラベルが「START」「Trying...」「Try again?」と変わります
- ボタンの幅は常に一定で、見た目がぶれません(CSS指定)
cssについて
style.css の構成と役割
1.body
設定 | 意味 |
---|---|
margin: 0 | ページ全体の余白をなくす |
font-family: sans-serif | スッキリしたフォントを使用 |
background-color: #121212 | ダークテーマ(背景を暗く) |
color: #ccc | 文字を白系に |
display: flex; justify-content: center; align-items: start; | 中央寄せ(横)+上から並べる |
height/min-height: 100vh | 画面の高さにぴったり合わせる |
padding-top: 5vh | 上に少し余裕を持たせる |
user-select: none | テキストを選択不可にする |
overflow: hidden | スクロールバーを出さない |
2. .container
.container {
text-align: center;
}
- 中の文字や要素を 中央揃えにします
3. .status
設定 | 意味 |
---|---|
display: flex | タイマーとクリアメッセージを横並びにする |
justify-content: space-between | 左右に均等配置 |
margin: 10px auto | 上下10px・中央寄せ |
width: 260px | 盤面と同じ幅に合わせて整える |
font-size/height | タイマー表示のサイズ感を調整 |
4. .board
設定 | 意味 |
---|---|
position: relative | 中の .tile を絶対位置で配置するための基準にする |
width/height: 255px | 正方形盤面(85px×3)+微調整 |
margin | 上下に余白・中央揃え |
background-color | 黒に近いパネル背景 |
5. .tile
設定項目 | 意味・目的 |
---|---|
background-color / border
|
パネルのダークな色合いと枠線を設定 |
font-size / font-weight
|
数字の見た目を強調して視認性アップ |
display: flex + 中央揃え |
数字をタイル中央に表示 |
cursor: pointer |
クリックできることを視覚的に示す |
will-change: transform |
アニメーションのパフォーマンスを向上させるヒント |
transition: transform 0.6s ease-in-out |
スライド移動のアニメーションを滑らかに設定 |
position: absolute |
.board 内での個別配置を可能にする |
width / height: 83px
|
盤面全体(255px)を 3×3 で均等に割り当てる |
6. button
- 見た目:角を丸くし、幅を一定(150px)にして統一感を演出
- 操作性:文字サイズと余白を確保し、スマホでもタップしやすく
- 無効時:背景色をグレー系に変更し、押せない状態であることを視覚的に伝える
- ホバー時(有効なとき):背景色を少し明るくして反応を視覚的に強調
7. .hidden
-
display: none;
によって、要素(例:クリアメッセージなど)を一時的に非表示にするための共通ユーティリティクラス
jsについて
jsについて
JavaScript(script.js)関数・変数解説
グローバル変数
-
tiles
タイルの状態を保持する配列(1〜8 + null)。現在の並びを記録する -
emptyIndex
空白(null)の位置インデックス(0〜8の整数) -
tileElements
数字キーを持つオブジェクト。各タイルDOM要素を保持し、transformの変更に使用 -
startTime
ゲーム開始時刻(経過時間の計算に使用) -
timerInterval
setInterval()
によるタイマー更新用のID -
playing
ゲームが現在プレイ中かどうかを示す真偽値。プレイ中のみクリックが有効になる
function createTiles()
- ゲームの初期状態を生成
- 数字 1〜8 と null を
tiles
配列にセット - 初期表示用の
initRender()
を呼び出す
function initRender()
-
tiles
に従って.tile
要素を生成し、DOMに配置 - 空白タイル(null)はDOMに描画しない
- 各タイルにクリックイベントを設定
-
tileElements
に DOM 要素を登録
function updateTilePositions()
-
tiles
の状態に合わせて、tileElements
に対応するタイルの位置(transform
)を更新 - CSSの
transition
がちょっと重い感じのタイルをすーっと移動させているような動きを実現
function getTransform(i)
- 位置インデックス
i
(0〜8)を元に、CSStransform: translate(x, y)
文字列を返す - タイルを盤面の正しい位置に表示するための補助関数
function moveTile(num)
- クリックされたタイル番号
num
を受け取り、その位置を取得 - 空白位置との隣接を確認し、隣接していれば
tiles
配列を交換 - 空白位置を更新し、
updateTilePositions()
を呼び出して表示を更新 - 完成していれば
checkClear()
→showResult()
を呼ぶ
function checkClear()
-
tiles
の0〜7
番目が[1,2,...,8]
になっているか確認 - パズル完成(クリア)していれば
true
を返す - ★コメントで改善案いただいているので是非ご確認ください★
function showResult()
- タイマー停止
-
playing
をfalse
にし、Clear !!
メッセージと再挑戦ボタンを表示
function shuffle(times = 20)
- ランダムに
tiles
配列をシャッフル - 一度にすべて変更せず、
setInterval()
を使って1手ずつ順に実行(誰かがバラバラにしてる風に) - 前回の空白位置と逆方向に戻らないようにする制御あり
-
updateTilePositions()
により移動を表示 - 終了後にゲーム開始・タイマー起動
function moveAllowed(from, to)
- 移動元と移動先の位置が「同じ行で隣接」または「上下に隣接」しているかを確認
-
true
なら移動可能と判定
startBtn.addEventListener("click", ...)
- 「START」ボタンを押すとゲーム初期化
- ボタン状態を
Trying...
にし、一定時間後にshuffle()
を実行 - 終了後はタイマー開始&プレイ可能な状態へ
関数間の関係図
処理の流れチャート
自動で解いてくれる機能を追加してみました。