「Hit & Blow」をプレイしてみる。
まず今回の動画で制作した「Hit & Blow」をプレイしてみようという方は、コチラからどうぞ。
スマホでのプレイに対応するためのコードを追加していますが、基本的な流れは動画と同じですm(_ _)m
JavaScriptで簡単なゲームを。
JavaScriptの入門講座も第8回になりました。
今回は「HIT & BLOW」という数あてゲームをプログラミングしています。
正直、ちょちょいと簡単に終わると思っていたんだけれど、ちょっと数字入力の仕組みなんかにこだわった結果、尺も長いしその上どうにも・・・なんだかスッキリとまとまってないなぁ・・・という感じになってしまいました。
そんなこともあって、このブログ記事で少しフォローの解説を入れることにいたしました。
その動画本編はコチラ
ポイントごとにコードとその解説を書いていきます。また、全コードは下の方に掲載しておりますm(_ _)m
HTMLとCSSで大体の体裁を整える
Hit & Blow !
<button id=”startBtn” onclick=”newGame()”>
START
</button>
</div>
40ピクセルの青地で「Hit & Blow !」を表示。タイトルの横には「START」ボタンを設置しています。ボタンにはonClick属性でnewGame()関数を紐づけています。
「choiceNumber」というidで作ったdiv要素。
ここに、ユーザーが選択した数字を表示します。
idなしのdivタグ。
ゲームの操作方法を表示しておきます。
「field」というidで作ったdiv要素。
ここには、ヒットとブローの判定結果を表示します。
これが<body></body>タグ内に書いたHTMLの部品の全体像です。
一部の装飾は、<head></head>内に<style></style>要素を作って記述しています。
それが下記。
#choiceNumber{
font-size:60px;
width:300px;
height:80px;
background-color:lavender;
text-align:center;
border:solid 3px blueviolet;
}
#field{
background-color:burlywood;
font-size:20px;
}
</style>
関数newGame()
STARTボタンがクリックされたときに呼び出される関数です。
ansNum = [“*”,”*”,”*”,”*”];
turn = 1;
disNum = document.getElementById(“choiceNumber”);
disNum.innerText = ansNum[0]+ansNum[1]+ansNum[2]+ansNum[3];
document.getElementById(“startBtn”).style.visibility = “hidden”;
document.addEventListener(“keydown”, keyPush);
selectNumber();
}
まずは disNum = document.getElementById(“choiceNumber”);でエレメントをオブジェクトとして取得して、
disNum.innerText = ansNum[0]+ansNum[1]+ansNum[2]+ansNum[3]; でinnerTextを設定して表示します。
document.getElementById(“startBtn”).style.visibility = “hidden”;
ここで、スタートボタンを「hidden」つまり非表示にしています。
document.addEventListener(“keydown”, keyPush);
ここで、キーを押したときに起動するイベントリスナーを設定。
関数selectNumber()
出題する4つの数字をランダムに生成する関数です。
do{
let numList = [“0″,”1″,”2″,”3″,”4″,”5″,”6″,”7″,”8″,”9”];
for(let i=0; i<4; i++){
let ran = Math.floor(Math.random()*numList.length);
queNum[i] = numList[ran];
numList.splice(ran,1);
}
}
while(queNum[0]==0);
console.log(queNum);
}
今回は、0~9までの数字を格納した配列からランダムに選んでいきます。一度選んだ数字はqueNumに代入後、もとの配列から削除するので、重複しません。do~while文で先頭の数字が0だった場合は再度選びなおします。
最後のconsole.logは、確認用です。
関数keyPush()
addEventListener()で設定した関数です。
キーボードのキーが押されたときに呼び出されます。
if (e.key==”Enter”){judge();}
if (e.key==”Delete” || e.key==” “){
ansNum = [“*”,”*”,”*”,”*”];
disNum.innerText = ansNum[0]+ansNum[1]+ansNum[2]+ansNum[3];
return;
}
if (Number.isInteger(Number(e.key))==false){return;}
if (ansNum.indexOf(“*”)!=-1){
ansNum[ansNum.indexOf(“*”)] = e.key;
disNum.innerText = ansNum[0]+ansNum[1]+ansNum[2]+ansNum[3];
}
}
keyPush(e)
この「e」は、発生したイベント自体を表すオブジェクトです。
.keyプロパティはオブジェクトが持っている値を表しているので、e.keyでどのキーが押されたのか判断できます。
Number.isInteger(Number(e.key))はちょっと複雑に見えるかもしれません。
Number(e.key)は、もしe.keyが「1」「2」などの数字の文字列だったなら、その値を数値に変換します。
そしてNumber.isInteger(Number(e.key))は、引数のNumber(e.key)が数値なら「true」を、数値でないなら「false」を返します。
この処理で、e.keyが数値(正確には数字の文字列)の場合に限り、次の処理に移ります。
.indexOf(“*”)は、「*」がどの位置にあるかを返して、ansNum[ansNum.indexOf(“*”)] = e.key;で、その「*」を数字(の文字列)に置き換えます。
関数judge()
これが最後の関数。
ヒットとブローの判定をします。
if (ansNum[3]==”*”){return;}
hit = 0;
blow = 0;
for (let i=0; i<4; i++){
if (ansNum[i]==queNum[i]){hit += 1;}
ここでヒットの判定。
そしてコッチでブローの判定をしています。
ここからは、判定後の表示を。
let result = document.createElement(“div”);
result.innerText = turn + “回目のチャレンジ[ ” + str + ” ] ” + hit + ” HIT / ” + blow + ” BLOW”;
field.appendChild(result);
ここからが、ゲームクリアの表示ですね。
window.alert(“おめでとうございます。\n” + turn + “回目で正解しました。”);
document.getElementById(“startBtn”).style.visibility = “visible”;
field.innerText = “”;
ansNum = [“”, “”, “”, “”];
disNum.innerText = ansNum[0]+ansNum[1]+ansNum[2]+ansNum[3];
document.removeEventListener(“keydown”, keyPush);
}
まだクリアでないときは、ここで回数を+1、数字選択をリセットして再びキーイベントを待ちます。
turn += 1;
ansNum = [“*”,”*”,”*”,”*”];
disNum.innerText = ansNum[0]+ansNum[1]+ansNum[2]+ansNum[3];
return;
}
最後に全コードをまとめて掲載してきます。
<!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">
<title>Hit & Blow</title>
<style>
#choiceNumber{
font-size:60px;
width:300px;
height:80px;
background-color:lavender;
text-align:center;
border:solid 3px blueviolet; }
#field{
background-color:burlywood;
font-size:20px; }
</style>
</head>
<body>
<div style="font-size:40px; color:blue;">
Hit & Blow !
<button id="startBtn" onclick="newGame()">START</button>
</div>
<div id="choiceNumber"></div>
<div>決定:ENTER / クリア:DEL</div>
<div id="enter"></div>
<div id="field"></div>
<script>
let arrayChoice = ["0","1","2","3","4","5","6","7","8","9","Delete","Enter"];
for (let i=0; i<12; i++){
let newBtn = document.createElement("button");
newBtn.textContent = arrayChoice[i];
newBtn.onclick = btnClick;
enter.appendChild(newBtn); }
let ansNum = [], queNum = [], disNum = [], turn, hit, blow;
function newGame(){
ansNum = ["*","*","*","*"];
turn = 1;
disNum = document.getElementById("choiceNumber");
disNum.innerText = ansNum[0]+ansNum[1]+ansNum[2]+ansNum[3];
document.getElementById("startBtn").style.visibility = "hidden";
document.addEventListener("keydown", keyPush);
selectNumber(); }
function selectNumber(){
do{
let numList = ["0","1","2","3","4","5","6","7","8","9"];
for(let i=0; i<4; i++){
let ran = Math.floor(Math.random()*numList.length);
queNum[i] = numList[ran];
numList.splice(ran,1);
}
}while(queNum[0]==0);
console.log(queNum); }
function keyPush(e){
if (e.key=="Enter"){judge();}
if (e.key=="Delete" || e.key==" "){
ansNum = ["*","*","*","*"];
disNum.innerText = ansNum[0]+ansNum[1]+ansNum[2]+ansNum[3];
return; }
if (Number.isInteger(Number(e.key))==false){return;}
if (ansNum.indexOf("*")!=-1){
ansNum[ansNum.indexOf("*")] = e.key;
disNum.innerText = ansNum[0]+ansNum[1]+ansNum[2]+ansNum[3]; } }
function btnClick(e){
let pushNum = e.target.textContent;
if (pushNum=="Enter"){judge();}
if (pushNum=="Delete" || pushNum==" "){
ansNum = ["*","*","*","*"];
disNum.innerText = ansNum[0]+ansNum[1]+ansNum[2]+ansNum[3];
return; }
if (Number.isInteger(Number(pushNum))==false){return;}
if (ansNum.indexOf("*")!=-1){
ansNum[ansNum.indexOf("*")] = pushNum;
disNum.innerText = ansNum[0]+ansNum[1]+ansNum[2]+ansNum[3]; } }
function judge(){
if (ansNum[3]=="*"){return;}
hit = 0;
blow = 0;
for (let i=0; i<4; i++){
if (ansNum[i]==queNum[i]){hit += 1;}
else if (queNum.indexOf(ansNum[i])!=-1){blow += 1;} }
let str = ansNum[0]+ansNum[1]+ansNum[2]+ansNum[3];
let result = document.createElement("div");
result.innerText = turn + "回目のチャレンジ[ " + str + " ] " + hit + " HIT / " + blow + " BLOW";
field.appendChild(result);
if (hit==4){
window.alert("おめでとうございます。\n" + turn + "回目で正解しました。");
document.getElementById("startBtn").style.visibility = "visible";
field.innerText = "";
ansNum = ["", "", "", ""];
disNum.innerText = ansNum[0]+ansNum[1]+ansNum[2]+ansNum[3];
document.removeEventListener("keydown", keyPush); }
else{
turn += 1;
ansNum = ["*","*","*","*"];
disNum.innerText = ansNum[0]+ansNum[1]+ansNum[2]+ansNum[3];
return; } }
</script>
</body>
</html>