JavaScriptでじゃんけんゲームをつくります。
Contents
HTML部分
HTML部分を示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>鳩でもわかる叩いてかぶってジャンケンゲーム</title> <meta name = "viewport" content = "width=device-width, initial-scale = 1.0"> <link rel = "stylesheet" href = "./style.css" type = "text/css" media = "all"> </head> <body> <div id = "container"> <div id = "field"> <div id = "image"></div> <div id = "message"></div> <div id = "remaining-time"></div> <button id = "start">ゲーム開始</button> <button id = "rock" class = "button1">グー</button> <button id = "scissors" class = "button1">チョキ</button> <button id = "paper" class = "button1">パー</button> <button id = "knock" class = "button2">叩く</button> <button id = "defense" class = "button2">防御</button> </div> </div> <script src= "./index.js"></script> </body> </html> |
style.css
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
body { color: #fff; background-color: #000; } #container { width: 360px; } #field { position: relative; height: 480px; } /* グーチョキパーのイメージ */ #image { position: absolute; width: 200px; height: 200px; left: 80px; top: 20px; } /* メッセージの表示 */ #message { position: absolute; top: 90px; left: 50%; transform: translateX(-50%); -webkit-transform: translateX(-50%); -ms-transform: translateX(-50%); font-size: 18px; text-align: center; } /* 残り時間の表示 */ #remaining-time { position: absolute; top: 220px; left: 50%; transform: translateX(-50%); -webkit-transform: translateX(-50%); -ms-transform: translateX(-50%); font-size: 18px; text-align: center; } /* スタートボタン */ #start { position: absolute; width: 180px; height: 70px; left: 90px; top: 250px; } /* グーチョキパーのボタン */ .button1 { position: absolute; width: 100px; height: 80px; display: none; } #rock { left: 10px; top: 250px; } #scissors { left: 130px; top: 250px; } #paper { left: 250px; top: 250px; } /* 叩くかぶるのボタン */ .button2 { position: absolute; width: 120px; height: 70px; display: none; } #knock { left: 40px; top: 370px; } #defense { left: 190px; top: 370px; } |
JavaScript部分
グローバル変数と定数
グローバル変数と定数を示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
// DOM要素 const $start = document.getElementById('start'); const $rock = document.getElementById('rock'); const $scissors = document.getElementById('scissors'); const $paper = document.getElementById('paper'); const $knock = document.getElementById('knock'); const $defense = document.getElementById('defense'); const $image = document.getElementById('image'); const $message = document.getElementById('message'); const $remainingTime = document.getElementById('remaining-time'); // 効果音 const winSound = new Audio('./sounds/win.mp3'); const loseSound = new Audio('./sounds/lose.mp3'); // イメージ const rockImage = new Image(200, 200); const scissorsImage = new Image(200, 200); const paperImage = new Image(200, 200); const handImages = [rockImage, scissorsImage, paperImage]; // じゃんけんの結果 // 0:グー、1:チョキ、2:パーとして // rpsResult[自分の手][コンピュータ側の手]が1なら勝ち、-1なら負け、0ならあいこ const rpsResult = [ [0, 1, -1], [-1, 0, 1], [1, -1, 0], ]; const INIT_MAX_REMAINING_TIME = 3000; // 「叩く」「かぶる」を選択する残り時間の初期値 let winCount = 0; // 連勝数 let situation = 0; // じゃんけんの結果(1:プレーヤーの勝ち、-1:負け、0:あいこ) let intervalID = null; // clearInterval関数に渡す引数 let maxRemainingTime = INIT_MAX_REMAINING_TIME; // 「叩く」「かぶる」を選択する制限時間 let remainingTime = 0; // 残り時間 |
ページを読み込まれたときの処理
ページが読み込まれたら画像を読み込む処理とイベントリスナを追加する処理をおこないます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
window.onload = () => { initImages(); addEventListeners(); } function initImages(){ rockImage.src = './images/rock.png'; scissorsImage.src = './images/scissors.png'; paperImage.src = './images/paper.png'; } function addEventListeners(){ // ゲームスタートのボタンをクリックしたとき $start.addEventListener('click', (ev) => gameStart()); // じゃんけんの手を出すボタンをクリックしたとき $rock.addEventListener('click', (ev) => rockPaperScissors(0)); $scissors.addEventListener('click', (ev) => rockPaperScissors(1)); $paper.addEventListener('click', (ev) => rockPaperScissors(2)); // 叩く、かぶるのボタンをクリックしたとき $knock.addEventListener('click', (ev) => action(true)); $defense.addEventListener('click', (ev) => action(false)); } |
ゲーム開始の処理
連勝数を0にリセットし、「叩く」「かぶる」を選択する制限時間に初期値を設定します。そしてスタートボタンを非表示にするとともに、じゃんけんの手を出すためのボタンを表示させます。
1 2 3 4 5 6 7 8 9 |
function gameStart(){ winCount = 0; maxRemainingTime = INIT_MAX_REMAINING_TIME; situation = 0; // 0ならじゃんけんの勝敗はついていない $start.style.display = 'none'; $message.innerHTML = ''; showHandsButtons(true); } |
showActionButtons関数はじゃんけんの手を出すためのボタンを表示させたり非表示にするためのものです。
1 2 3 4 5 |
function showActionButtons(show){ const display = show == true ? 'block' : 'none'; $knock.style.display = display; $defense.style.display = display; } |
showHandsButtons関数は「叩く」「かぶる」のボタンを表示させたり非表示にするためのものです。
1 2 3 4 5 6 |
function showHandsButtons(show){ const display = show == true ? 'block' : 'none'; $rock.style.display = display; $scissors.style.display = display; $paper.style.display = display; } |
じゃんけんをする処理
じゃんけんの手を出すボタンがクリックされたら乱数でコンピュータ側の手を確定させ、どちらがじゃんけんに勝ったのかを確定させます。
これでじゃんけんの勝敗がつく場合があるので、叩くかぶるのボタンを表示します。このボタンをあいこのときにクリックするとゲームオーバーになります。じゃんけんの勝敗がついている状態では叩くかぶるのボタン以外は反応しないようにします。
そのあとタイマーで残り時間を減算させていきます。もしじゃんけんの勝敗がついている状態であれば、残り時間が0になるまでに叩くかかぶる行動を取らなければなりません。なにもしないで残り時間が0になった場合はゲームオーバーの処理をおこないます。onLose関数になぜ負けなのかを表示する文字列を渡します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
function rockPaperScissors(hand){ $message.innerText = ''; // じゃんけんの勝敗がついているかもしれないので、叩くかぶるのボタンを表示する showActionButtons(true); // 「あいこ」の場合以外はボタンをクリックしても何もしない if(situation != 0) return; // タイマー動作中はいったん止める if(intervalID != null){ clearInterval(intervalID); intervalID = null; } // コンピュータ側の手を確定させ、どちらがじゃんけんに勝ったのかを確定させる const r = Math.floor(Math.random() * 3); changeImage(handImages[r]); situation = rpsResult[hand][r]; // 残り時間を表示 remainingTime = maxRemainingTime; $remainingTime.innerHTML = remainingTime; // タイマーで残り時間を減算させていく intervalID = setInterval(() => { remainingTime -= 20; // 残り時間を表示 if(remainingTime > 0) $remainingTime.innerHTML = remainingTime; else $remainingTime.innerHTML = ''; // じゃんけんの勝敗がついているのに残り時間が0になったらゲームオーバー if(remainingTime < 0){ clearInterval(intervalID); intervalID = null; changeImage(null); if(situation > 0) onLose('勝ったときは叩きましょう'); if(situation < 0) onLose('じゃんけんに負けたあなたは叩かれました'); } }, 20); } |
changeImage関数はグーチョキパーのイメージを入れ替える処理をおこないます。
1 2 3 4 5 6 |
function changeImage(image){ if($image.childElementCount > 0) $image.children[0].remove(); if(image != null) $image.appendChild(image); } |
「叩く」「防御」のボタンをクリックしたときの処理
「叩く」「防御」のボタンをクリックしたときの処理を示します。プレーヤーの行動が適切だった場合は勝ち、それ以外のときはonLose関数を呼び出してゲームオーバーの処理をおこないます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// 「叩く」をクリックしたときはtrue、「防御」をクリックしたときはfalseが渡される function action(knock){ $message.innerText = ''; if(intervalID != null){ clearInterval(intervalID); intervalID = null; } // プレーヤーの行動が適切だったか? if((situation > 0 && knock) || (situation < 0 && !knock)) onWin(); else if(knock) onLose('勝ってないのに叩いてはいけません'); else onLose('負けてないのに逃げてはいけません'); } |
勝敗確定時の処理
勝ったときは連勝数を増やして制限時間を少し減らします。また連勝数を表示し、次戦に備えてじゃんけんの手を出すためのボタンを表示させます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
function onWin(){ // 連勝数を増やして制限時間を減らす winCount++; maxRemainingTime = Math.ceil(maxRemainingTime * 0.8); // じゃんけんの勝敗はついていない状態にする situation = 0; // 残り時間は非表示にしてゲームの結果を表示 $remainingTime.innerHTML = ''; $message.innerHTML = `あなたの勝ちです<br><br>連勝記録:${winCount}`; // 表示されているイメージをクリア changeImage(null); // じゃんけんの手を出すためのボタンを表示する showActionButtons(false); // 効果音 winSound.currentTime = 0; winSound.play(); } |
負けたときは即ゲームオーバーです。これまでのゲームオーバーであることを示す文字列と連勝数を表示し、ボタンをすべて非表示にします。そのあとゲーム開始ボタンを表示させます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
function onLose(message){ // 残り時間は非表示にしてゲームの結果を表示 $remainingTime.innerHTML = ''; $message.innerHTML = `GAME OVER<br><br>${message}<br><br>連勝記録:${winCount}` // 表示されているイメージをクリア // ボタンをすべて非表示にする changeImage(null); showActionButtons(false); showHandsButtons(false); // 効果音 loseSound.currentTime = 0; loseSound.play(); // ゲーム開始ボタンを表示させる setTimeout(() => { $start.style.top = '300px'; $start.style.display = 'block'; }, 3000); } |