2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

スライドパズルをJavaScriptで作ってみた

Last updated at Posted at 2025-04-24

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)を元に、CSS transform: translate(x, y) 文字列を返す
  • タイルを盤面の正しい位置に表示するための補助関数

function moveTile(num)

  • クリックされたタイル番号 num を受け取り、その位置を取得
  • 空白位置との隣接を確認し、隣接していれば tiles 配列を交換
  • 空白位置を更新し、updateTilePositions() を呼び出して表示を更新
  • 完成していれば checkClear()showResult() を呼ぶ

function checkClear()

  • tiles0〜7 番目が [1,2,...,8] になっているか確認
  • パズル完成(クリア)していれば true を返す
  • ★コメントで改善案いただいているので是非ご確認ください★

function showResult()

  • タイマー停止
  • playingfalse にし、Clear !! メッセージと再挑戦ボタンを表示

function shuffle(times = 20)

  • ランダムに tiles 配列をシャッフル
  • 一度にすべて変更せず、setInterval() を使って1手ずつ順に実行(誰かがバラバラにしてる風に)
  • 前回の空白位置と逆方向に戻らないようにする制御あり
  • updateTilePositions() により移動を表示
  • 終了後にゲーム開始・タイマー起動

function moveAllowed(from, to)

  • 移動元と移動先の位置が「同じ行で隣接」または「上下に隣接」しているかを確認
  • true なら移動可能と判定

startBtn.addEventListener("click", ...)

  • 「START」ボタンを押すとゲーム初期化
  • ボタン状態を Trying... にし、一定時間後に shuffle() を実行
  • 終了後はタイマー開始&プレイ可能な状態へ

関数間の関係図


処理の流れチャート


自動で解いてくれる機能を追加してみました。

https://qiita.com/kubo4ka/items/8e68d9c6c76fef03958e

2
3
4

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
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?