Skip to content

Instantly share code, notes, and snippets.

@mrgarita
Last active March 29, 2023 06:30
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrgarita/05d0de0352d93b0da2d8390a9417a8db to your computer and use it in GitHub Desktop.
Save mrgarita/05d0de0352d93b0da2d8390a9417a8db to your computer and use it in GitHub Desktop.
JavaScript:8パズル
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="robots" content="INDEX,FOLLOW">
<meta name="description" content="シンプルな8パズルゲームです。クリアまでの時間計測つきです。">
<link rel="apple-touch-icon" href="icon.png" > <!--ホームアイコンの設定-->
<link rel="SHORTCUT ICON" href="favicon.ico"> <!-- PC用ホームアイコンの設定 --> <link rel="stylesheet" href="style.css">
<!-- Google Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Righteous&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap" rel="stylesheet">
<!-- /Google Fonts -->
<script src="main.js"></script>
<title>8puzzle</title>
</head>
<body>
<div class="timer">00:00</div>
<div class="board">
<div class="cell" data-number="0">1</div>
<div class="cell" data-number="1">2</div>
<div class="cell" data-number="2">3</div>
<div class="cell" data-number="3">4</div>
<div class="cell" data-number="4">5</div>
<div class="cell" data-number="5">6</div>
<div class="cell" data-number="6">7</div>
<div class="cell" data-number="7">8</div>
<div class="cell" data-number="8"></div>
</div>
<div class="btn"><button id="btnStart">START</button></div>
<div class="message"></div>
</body>
</html>
// -----------------------------
// 8パズル(数値版) main.js
// -----------------------------
let cells = null; // セル配列
let timer, startTime; // 経過時間計測用
let mode;
const WAIT = Symbol(); // 待機
const GAME = Symbol(); // ゲーム中
// セルを入れ替える
function swapCell(x, y){
console.log("入れ替え.");
[ cells[x].textContent, cells[y].textContent ] = [ cells[y].textContent, cells[x].textContent ];
// クリアしたか?
checkClear();
}
// セルが入れ替え可能かチェックする
function checkCell(number){
if(number >= 3 && cells[number-3].textContent === ""){ // 上と入れ替え
swapCell(number, number-3);
}
if(number <= 5 && cells[number+3].textContent === ""){ // 下と入れ替え
swapCell(number, number+3);
}
if(number % 3 != 2 && cells[number+1].textContent === ""){ // 右と入れ替え
swapCell(number, number+1);
}
if(number % 3 != 0 && cells[number-1].textContent === ""){ // 左と入れ替え
swapCell(number, number-1);
}
}
// クリアしたか?
function checkClear(){
if(mode === GAME){
// 1~8に並んでいるか?
let i=0;
for(; i<cells.length; i++){
let value = Number(cells[i].textContent);
console.log("textContent: " + value);
if(value !== (i+1)) break;
}
// 並んでいればクリア!
if(i === 8){
mode = WAIT;
document.querySelector(".message").textContent = "CLEAR!!";
clearTimeout(timer);
}
}
}
// 経過時間表示
function showPassedTime(){
// 現在時刻
const currentTime = new Date().getTime();
// スタートからの差分
const diff = new Date(currentTime - startTime);
const [minute, second] = [diff.getMinutes(), diff.getSeconds()];
// 分と秒を0埋め2桁に整形
const [txtMinute, txtSecond] = [
String(minute).padStart(2, "0"), String(second).padStart(2, "0")
]
// 表示
document.querySelector(".timer").textContent = `${txtMinute}:${txtSecond}`;
timer = setTimeout(showPassedTime, 250);
}
// 起動時の処理
window.addEventListener("load", ()=>{
// ゲームの状態
mode = WAIT;
// 9つのセルを取得
cells = document.querySelectorAll(".cell");
// セルのイベントを設定
for(let cell of cells){
cell.addEventListener("click", (e)=>{
// セルの番号を取得(data-numberプロパティ)
const number = Number(e.currentTarget.dataset.number);
console.log("cells[" + number + "] Click.");
// セルが入れ替え可能か?
checkCell(number);
}, false);
}
// スタートボタン
const btnStart = document.getElementById("btnStart");
btnStart.addEventListener("click", ()=>{
document.querySelector(".message").textContent = "";
// シャッフル
for(let i=0; i<1000; i++){
const r = Math.floor(Math.random() * 9);
checkCell(r);
}
// ゲーム開始
mode = GAME;
// タイマースタート
clearTimeout(timer);
startTime = new Date().getTime();
showPassedTime();
}, false);
});
/* style.css */
@charset "utf-8";
*{
margin: 0;
padding: 0;
}
body{
margin: 1em;
display: flex;
flex-direction: column;
font-size: 5vh;
font-family: 'Righteous', cursive;
}
.timer{
font-family: 'Courier Prime', monospace;
display: flex;
align-items: center;
justify-content: center;
}
.board{
display: grid;
grid-template-rows: 12vh 12vh 12vh;
grid-template-columns: 12vh 12vh 12vh;
background: orange;
justify-self: center; /* 横方向中央揃え */
align-self: center; /* 縦方向中央揃え */
}
.cell{
background: #be3455;
border: solid 1px white;
display: flex;
align-items: center;
justify-content: center;
color: white;
}
.btn{
display: flex;
align-items: center;
justify-content: center;
}
#btnStart{
font-family: 'Courier Prime', monospace;
width: 36vh;
padding: 1em;
font-size: 3vh;
}
.message{
display: flex;
align-items: center;
justify-content: center;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment