はじめに
今回初めてのQitta記事を書くにあたってゲームを作りたいと考え、私が好きな「Hit&Blow」というゲームを作ってみました。
「Hit&Blow」を簡単に説明すると3桁などの重複しない数字を当てる推理ゲームです。本来「Hit&Blow」は二人で行うもので、各々秘密の3桁の数字を持っていて、片方ずつ相手の数字を予測して数字を言います。相手側は数字と場所が当たっている数を「ヒット」・数字は当たっているが場所が当たってない数を「ブロー」と答えます。それをもとに相手の桁数を先に当てれば勝ちのゲームです。詳しくはこちら:ヒットアンドブローゲームのルールと遊び方
このルールを参考に今回は、JavaScriptを主に用いて作成してみました。
プログラム
HTML
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hit & Blow Game</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<h1>Hit & Blow</h1>
</header>
<div class = "game">
<p>4桁の数字を当ててください(重複なし)</p>
<input type = "text" id = "guess" maxlength = "4" placeholder = "1234">
<div id = "Inputbtns">
<button class="num">1</button>
<button class="num">2</button>
<button class="num">3</button>
<button class="num">4</button>
<button class="num">5</button>
<button class="num">6</button>
<button class="num">7</button>
<button class="num">8</button>
<button class="num">9</button>
<button class="num">0</button>
</div>
<button id = "btn">判定</button>
<button id = "delbtn">←</button>
<div id = "result"></div>
<div class = "log"></div>
</div>
<footer>
<div id = "clear"></div>
<button id = "Resetbtn">リセット</button>
</footer>
<script src="main.js"></script>
</body>
</html>
CSS
body {
text-align: center;
background: #b6fef8;
padding: 40px;
}
.game {
background: rgb(254, 251, 246);
width: 350px;
margin: 0 auto;
padding: 20px;
border-radius: 10px;
box-shadow: 0 0 10px #ccc;
}
input {
font-size: 20px;
width: 150px;
padding: 5px;
margin-top: 10px;
}
button ,
#Resetbtn{
font-size: 16px;
padding: 10px 20px;
margin-left: 10px;
margin-top: 10px;
}
.log {
margin-top: 20px;
text-align: left;
font-size: 18px;
}
#Resetbtn{
display: none;
}
JavaScriptがメインなので、HTMLとCSSは出来るだけシンプルにしました。
JavaScript
//答えになる4桁の値を0~9からランダムに作る
function answer()
{
let digits = ["0","1","2","3","4","5","6","7","8","9"];
//digitsの配列を並び替える(ランダムに)
for(let i = digits.length - 1; i > 0; i--)
{
let j = Math.floor(Math.random() * (i + 1)); // 0 ~ i+1 未満の整数の中でjの値をランダムに決める
[digits[i], digits[j]] = [digits[j], digits[i]]; //配列の値入れ替え
}
return digits.slice(0, 4).join(""); //joinを使って文字列にする
}
//ヒット・ブローを判定
function Check(Ans,guess)
{
let hitcount = 0;
let blowcount = 0;
for(let i = 0; i < 4; i ++)
{
if(guess[i] === Ans[i])
hitcount ++;
else if(Ans.includes(guess[i])) //includesでAnsの文字列の中にguess[i]があるか検索
blowcount++;
}
return {hitcount,blowcount};
}
//数字ボタンのリセット
function Resetbuttons()
{
document.querySelectorAll(".num").forEach(numbtn =>{
numbtn.disabled = false;
});
}
/*main
--------------------------------------------------------*/
function main()
{
let btn = document.getElementById("btn");
let guess = document.getElementById("guess");
let resultArea = document.getElementById("result");
let inputnum = document.querySelectorAll(".num");
let Ans = answer();
// console.log("ans = ", Ans);
inputnum.forEach(numbtn => {
numbtn.addEventListener("click", () => {
if(guess.value.length < 4) //4桁以上にならないようにする
{
guess.value += numbtn.textContent;
numbtn.disabled = true;
}
})
});
//判定ぼたんを押した後の処理
btn.addEventListener("click", function()
{
if(guess.value.length === 4) //入力された値が4桁じゃないとクリックしても何も起きない
{
let result = Check(Ans,guess.value);
resultArea.innerHTML += `[${guess.value}] : ヒット:${result.hitcount} ブロー:${result.blowcount}<br>`
//入力が答えとあっていた時
if(result.hitcount === 4)
{
let clear = document.getElementById("clear");
clear.innerHTML = `<div style = "margin-top: 30px;color : red ;
font-size: 35px; font-weight: bold;">★クリア!!おめでとう🎉★`;
document.getElementById("Resetbtn").style.display = "inline-block" //リセットボタンを表示する
return;
}
guess.value = "";
Resetbuttons();
}
});
// 削除ボタン「←」を押したときの処理
// 1文字削除
let delbtn = document.getElementById("delbtn");
delbtn.addEventListener("click", () => {
let last = guess.value.slice(-1); // 直前の数字
guess.value = guess.value.slice(0, -1);
inputnum.forEach(numbtn => {
if (numbtn.textContent === last) {
numbtn.disabled = false;
}
});
});
//リセットボタン
let resetbtn = document.getElementById("Resetbtn");
resetbtn.addEventListener("click",function(){
resultArea.innerHTML = ""; //ディスプレイに表示されているヒットとブローの履歴削除
guess.value = "";
clear.innerHTML = ""; //ディスプレイに表示されているクリア文字を削除
Ans = answer(); //新しい四桁の答えを作成
// console.log("next ans = ",Ans);
this.style.display = "none";
Resetbuttons(); //押した数字を再び押せるようにする
});
}
main();
答えは4桁の数字で作ったので、4桁の数字以外の入力では判定ボタンを押しても何も動作しない様にしています。また、重複なしというルールにしたので、0~9どれかの数字ボタンを押すと判定ボタンを押した後の処理が行われるまでは押すことが出来ない様にしています。
これで完成です!
終わりに
今回は純粋に作りたいと思ったゲームを作りました。「Hit&Blow」自体がゲームとして凄く面白いので、誰でも楽しめると思います。プログラムの中身に関しては、私が気づかない部分で改善点があると思うのでコメントで教えていただけると嬉しいです。
