<style>
/* ゲームコンテナのスタイル */
#game-container {
display: grid;
grid-template-columns: repeat(3, 100px);
gap: 5px;
margin-bottom: 5px;
}
/* タイルのスタイル */
.tile {
width: 100px;
height: 100px;
background-color: #4a90e2;
border: 1px solid #000;
cursor: pointer;
transition: background-color 0.3s;
display: flex;
justify-content: center;
align-items: center;
font-size: 24px;
font-weight: bold;
color: white;
}
.tile:disabled {
background-color: #ccc;
}
/* 空白のタイルのスタイル */
.empty {
background-color: #f0f0f0;
border: 0px;
}
/* メッセージ表示のスタイル */
#message {
margin: 10px 0;
font-weight: bold;
color: #4caf50;
}
/* ボタンのスタイル */
#newGame {
margin-top: 10px;
padding: 5px 10px;
font-size: 16px;
}
</style>
<h1>スライドパズル</h1>
<div id="game-container"></div>
<div id="message"></div>
<button id="newGame">新しいゲーム</button>
<script>
// DOM要素の取得
const gameContainer = document.getElementById('game-container');
const message = document.getElementById('message');
const newGameButton = document.getElementById('newGame');
// ゲームの状態を管理する変数
let tiles = [];
let gameWon = false;
// 正解の配置(0は空白を表す)
const correct = [1, 2, 3, 4, 5, 6, 7, 8, 0];
// シャッフル関数
function shuffle(array) {
const newArray = array.slice();
for (let i = newArray.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[newArray[i], newArray[j]] = [newArray[j], newArray[i]];
}
return newArray;
}
// 解決可能かどうか判定する関数
function isSolvable(puzzle) {
let inversions = 0;
// 空白(0)を除外
const flatPuzzle = puzzle.filter(num => num !== 0);
for (let i = 0; i < flatPuzzle.length; i++) {
for (let j = i + 1; j < flatPuzzle.length; j++) {
if (flatPuzzle[i] > flatPuzzle[j]) {
inversions++;
}
}
}
return inversions % 2 === 0;
}
// ランダムな解決可能な状態を生成する関数
function generateRandomState() {
let coordinate;
do {
coordinate = shuffle([...correct]); // correct配列をコピーしてシャッフル
} while (!isSolvable(coordinate));
return coordinate;
}
// ゲームボードを初期化する関数
function initializeBoard() {
tiles = generateRandomState();
gameWon = false;
renderBoard();
message.textContent = '';
}
// ゲームボードを描画する関数
function renderBoard() {
gameContainer.innerHTML = '';
tiles.forEach((tile, index) => {
const button = document.createElement('button');
button.className = 'tile';
if (tile === 0) {
button.classList.add('empty');
button.disabled = true;
} else {
button.textContent = tile;
button.onclick = () => handleMove(index);
}
gameContainer.appendChild(button);
});
}
// タイルをクリックした際の処理を行う関数
function handleMove(index) {
if (gameWon) return;
const emptyIndex = tiles.indexOf(0);
if (canMove(index, emptyIndex)) {
// タイルを入れ替え
[tiles[index], tiles[emptyIndex]] = [tiles[emptyIndex], tiles[index]];
renderBoard();
checkWin();
}
}
// タイルが移動可能か判断する関数
function canMove(index, emptyIndex) {
return (
(index === emptyIndex - 1 && emptyIndex % 3 !== 0) || // 左への移動
(index === emptyIndex + 1 && emptyIndex % 3 !== 2) || // 右への移動
index === emptyIndex - 3 || // 上への移動
index === emptyIndex + 3// 下への移動
);
}
// ゲームクリア条件を確認する関数
function checkWin() {
if (JSON.stringify(tiles) === JSON.stringify(correct)) {
gameWon = true;
message.textContent = 'おめでとうございます!パズルを解きました!';
}
}
// 「新しいゲーム」ボタンにクリックイベントを設定
newGameButton.addEventListener('click', initializeBoard);
// ページ読み込み時にゲームを初期化
initializeBoard();
</script>
コメント