質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

2回答

1216閲覧

イベント処理がある関数を繰り返したい。

suissuis

総合スコア0

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2020/08/25 08:00

編集2020/08/25 08:12

関数を一定回数繰り返したい

JavaScript で作っているものがあります。プログラミングは始めて三ヶ月くらいなので自分で書いてわからないコードは極力書きたくないないと思ってます。jQuery(?)というものがあるようですがそれも使ってません。node.js もまだなのでライブラリも使える状況ではありません。自分初の作品として js のみで完結する簡単なじゃんけんゲームを作っています。

大体は書けたのですが、あと一息というとこで躓いています。
「最初はぐー」と表示する関数、「じゃんけんぽん」などのメインの処理をする関数があるのですが、一回目以降から「じゃんけんぽん」のところの serectedAndJudgment 関数を数回繰り返したいです。
for 文で回そうとしたらおそらく onclick のところで詰まってしまったのかと。onclick は任意なので js 側は待ってはくれず表示部分が先に何回も繰り返されてしまったのかと思います。下の「試したこと」にも書きました。

発生している問題・エラーメッセージ

特に出てはないです。

該当のソースコード

HTML

1<!DOCTYPE html> 2<html lang="ja"> 3 4<head> 5 <meta charset="UTF-8"> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 <title>後出しじゃんけんゲーム</title> 8 <link rel="stylesheet" href="copy.css"> 9</head> 10 11<body> 12 <h1 id="title">後出しじゃんけんゲーム!</h1> 13 <button id="start-button">スタート</button> 14 <h1 id="signal-text"></h1> 15 <div id="signal-image"></div> 16 <div id="judgment-area" class="judgment"></div> 17 <h2 id="score-area" class="score"></h2> 18 <div id="janken-area"></div> 19 <script src="copy.js"></script> 20</body> 21 22</html>

JavaScript

1'use strci'; 2const title = document.getElementById('title'); 3const startButton = document.getElementById('start-button'); 4const signalText = document.getElementById('signal-text'); 5const signalImage = document.getElementById('signal-image'); 6const judgmentArea = document.getElementById('judgment-area'); 7const scoreArea = document.getElementById('score-area'); 8const jankenArea = document.getElementById('janken-area'); 9 10// ぐー、ちょき、ぱーの画像 11const images = [ 12 './img/gu.png', // ぐーの画像 13 './img/pa.png', // ぱーの画像 14 './img/choki.png' // ちょきの画像 15]; 16 17// CPU 側のじゃんけん表示エリアを作成 18const opponentImage = document.createElement('img'); 19 20// 関数のトリガー 21startButton.onclick = () => { 22 23 title.remove(); 24 startButton.remove(); 25 //scoreArea.innerText = '0 勝'; 26 27 signal(); 28 serectedAndJudgment(); 29}; 30 31 32//「最初はぐーじゃんけん」の呼びかけの処理 33function signal() { 34 signalText.innerText = '最初はぐー'; 35 opponentImage.src = images[0]; // ぐーを固定化 36 opponentImage.width = "300"; 37 opponentImage.height = "300"; 38 signalImage.appendChild(opponentImage); 39}; 40 41 42// 「ぽん」の呼びかけと遊びの本体の処理 43function serectedAndJudgment() { 44 45 setTimeout(() => { 46 signalText.innerText = 'じゃんけん'; 47 }, 1500); 48 49 setTimeout(() => { 50 // 相手側の表示の処理 51 let imageNo = Math.floor(Math.random() * images.length); // 画像表示時の添え字をランダムで生成 52 signalText.innerText = 'ぽん'; 53 opponentImage.src = images[imageNo]; // 生成した添え字で画像を表示 54 signalImage.appendChild(opponentImage); 55 56 // 正解「〇」不正解「✕」の判定画像の表示エリアを作成 57 const judgment = document.createElement('img'); 58 judgment.width = "300"; 59 judgment.height = "300"; 60 judgmentArea.appendChild(judgment); 61 judgment.style.display = 'none'; 62 63 // 開始時の時刻をメモ 64 let startTime = Date.now(); 65 66 // じゃんけんメインエリアの作成 67 for (let i = 0; i < images.length; i++) { 68 let serect = document.createElement('input'); 69 jankenArea.appendChild(serect); 70 serect.type = "image"; 71 serect.src = images[i]; // iを添え字として画像を表示 72 serect.width = "300"; 73 serect.height = "300"; 74 serect.onclick = () => { 75 jankenArea.children[0].disabled = true; // ぐーを一回限りのボタンに 76 jankenArea.children[1].disabled = true; // ぱーを一回限りのボタンに 77 jankenArea.children[2].disabled = true; // ちょきを一回限りのボタンに 78 if ((Date.now() - startTime) > 1000) { // 2秒以内に押せないなら時間切れ 79 judgment.style.display = ''; 80 judgment.src = './img/time.png'; // 時間切れ 81 82 } else if (imageNo === i) { 83 judgment.style.display = ''; 84 judgment.src = './img/aiko.png'; // あいこ 85 // scoreArea.innerText = 86 } else if (imageNo === 0 && i === 1 || imageNo === 1 && i === 2 || imageNo === 2 && i === 0) { 87 judgment.style.display = ''; 88 judgment.src = './img/maru.png'; 89 //scoreArea.innerText = `${score} 勝`; // 勝ち 90 } else { 91 judgment.style.display = ''; 92 judgment.src = './img/batu.png'; 93 //scoreArea.innerText = '負け'; // 負け 94 } 95 signalText.innerText = "次!"; 96 removeAllChildren(jankenArea); 97 removeAllChildren(judgmentArea); 98 serectedAndJudgment(); 99 } 100 }; 101 }, 2500); 102}; 103 104 105/** 106 * 指定した要素の子どもを全て削除する 107 * @param {HTMLElement} element HTMLの要素 108 */ 109function removeAllChildren(element) { 110 setTimeout(() => { 111 while (element.firstChild) { 112 element.removeChild(element.firstChild); 113 } 114 }, 1000); 115}; 116

試したこと

最初に for 文内で serectedAndJudgment 関数を10 回程度回そうと思っていたのですが、調べたところ js は基本的には非同期だそうなので自分が思っていた通りには動きませんでした。表示部分の画像を三枚 input タグで作るところが 10 回先に繰り返されてしまいました。
Promise や await(?) なども調べてなんども挑戦しましたが自分ではどうしたらいいか…。

今回関係ない部分の詳細

画像を表示するのになんで input タグになっているのかは disabled を付けたかったからです。この辺もあまいところなのかなって思います。
スタートボタンを押したらゲームが開始されるようになっています。一番最初の signal 関数ですが、これは初めの一回しか出番がないの後ほどスタートボタンの処理の中に直接書こうかなって思ってます。
ご教授願います。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yambejp

2020/08/25 08:03

HTMLの例示と、このjsをどのタイミングで呼び出しているか提示ください
guest

回答2

0

  • onclickで関数を指定するのは基本NG
  • setTimeoutをなぜ利用しているか不明、おそらく不要
  • まずはimgとか使わずにもっとソリッドな作りにしてあとで拡張した方がよいです

投稿2020/08/25 08:07

yambejp

総合スコア114839

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

suissuis

2020/08/25 08:22

ご意見ありがとうございます。 setTimeout は表示部分のタイミングを変えています。「最初はぐー」や「じゃんけん」のところを遅らせてます。おそらく分かられているのだと思いますが...。 自分で書いたコードなのに自信がなくて申し訳ございません。
guest

0

自己解決

回答していただきありがとうございました。自己解決できましたので閉じたいと思います。ご意見ありがとうございました!!

JavaScript

1'use strict'; 2const title = document.getElementById('title'); 3const numberOfTimes = document.getElementById('number-of-times'); 4const startButton = document.getElementById('start-button'); 5const ruleArea = document.getElementById('rule-area'); 6const signalTextArea = document.getElementById('signal-text-area'); 7const signalImageArea = document.getElementById('signal-image-area'); 8const judgmentArea = document.getElementById('judgment-area'); 9const jankenArea = document.getElementById('janken-area'); 10const restartButton = document.getElementById('restart-button'); 11 12 13let count = 0; // 勝負数をカウントする変数 14let wins = 0; // 勝った回数をカウントする変数 15 16 17// ぐー、ちょき、ぱーの画像 18const images = [ 19 './img/gu.png', // ぐーの画像 20 './img/pa.png', // ぱーの画像 21 './img/choki.png' // ちょきの画像 22]; 23 24 25// 画像の配列の添え字を格納している配列 26const num = [0, 1, 2]; 27 28 29// CPU 側のじゃんけん表示エリアを作成 30const opponentImage = document.createElement('img'); 31 32 33/** 34 * 指定した要素の子どもを全て削除する 35 * @param {HTMLElement} element HTMLの要素 36 */ 37function removeAllChildren(element) { 38 setTimeout(() => { 39 while (element.firstChild) { 40 element.removeChild(element.firstChild); 41 } 42 }, 1000); // 要素を視認できるよう1秒後に処理 43}; 44 45 46// じゃんけんゲームのメインの関数 47function serectAndJudgment() { 48 49 // inputの入力数値を number に変換 50 let nOT = parseFloat(numberOfTimes.value); 51 52 // 勝負の結果報告 53 if (count === nOT) { 54 setTimeout(() => { 55 alert(`${nOT}回勝負中${wins}回勝利しました!\n「タイトルへ」をクリックしてください。`); 56 signalTextArea.innerText = 'GAME OVER\n豆知識:GAME OVERは実はゲーム終了という意味合いが強い'; 57 startButton.innerText = 'タイトルへ'; 58 restartButton.appendChild(startButton); 59 restartButton.onclick = () => { 60 location.reload(); // リロードでタイトルへ戻る 61 } 62 }, 1000); 63 return; 64 } 65 66 // 「じゃんけん」の呼びかけ 67 setTimeout(() => { 68 signalTextArea.innerText = 'じゃんけん'; 69 }, 1500); 70 71 // この関数のメイン処理 72 setTimeout(() => { 73 // 相手側の表示の処理 74 let imageNo = Math.floor(Math.random() * images.length); // 画像表示時の添え字をランダムで生成 75 signalTextArea.innerText = 'ぽん'; 76 opponentImage.src = images[imageNo]; // 生成した添え字で画像を表示 77 signalImageArea.appendChild(opponentImage); 78 79 // 正解「〇」不正解「✕」の判定画像の表示エリアを作成 80 const judgment = document.createElement('img'); 81 judgment.width = "300"; 82 judgment.height = "300"; 83 judgment.style.display = 'none'; 84 judgmentArea.appendChild(judgment); 85 86 let startTime = Date.now(); // 開始時の時刻をメモ 87 88 // じゃんけんのメインエリアの作成 89 for (let i = num.length - 1; i >= 0; i--) { 90 let serect = document.createElement('input'); 91 let rand = Math.floor(Math.random() * (i + 1)); 92 [num[i], num[rand]] = [num[rand], num[i]]; // シャッフル 93 serect.width = "300"; 94 serect.height = "300"; 95 serect.type = "image"; 96 serect.src = images[num[i]]; // num[i]を添え字として画像をランダム表示 97 jankenArea.appendChild(serect); 98 serect.onclick = () => { 99 count++; // 勝負数をカウント 100 jankenArea.children[0].disabled = true; // ぐーを一回限りのボタンに 101 jankenArea.children[1].disabled = true; // ぱーを一回限りのボタンに 102 jankenArea.children[2].disabled = true; // ちょきを一回限りのボタンに 103 if ((Date.now() - startTime) > 1000) { // 2秒以内に押せないなら時間切れ 104 judgment.style.display = ''; 105 judgment.src = './img/time.png'; // 時間切れ 106 } else if (imageNo === num[i]) { 107 judgment.style.display = ''; 108 judgment.src = './img/aiko.png'; // あいこ 109 } else if (imageNo === 0 && num[i] === 1 || imageNo === 1 && num[i] === 2 || imageNo === 2 && num[i] === 0) { 110 wins++; // 勝った数を記録 111 judgment.style.display = ''; 112 judgment.src = './img/maru.png'; // 勝ち 113 } else { 114 judgment.style.display = ''; 115 judgment.src = './img/batu.png'; // 負け 116 } 117 signalTextArea.innerText = "次!"; 118 removeAllChildren(jankenArea); 119 removeAllChildren(judgmentArea); 120 removeAllChildren(signalImageArea); 121 serectAndJudgment(); 122 } 123 }; 124 }, 2500); 125}; 126 127 128// 関数のトリガー 129startButton.onclick = () => { 130 131 let inputNumber = numberOfTimes.value; 132 if (inputNumber.length === 0) { 133 return // 数字の入力がなかったら処理を中断 134 } 135 136 // タイトルとルール文、スタートボタン、インプットエリアを削除 137 title.remove(); 138 ruleArea.remove(); 139 startButton.remove(); 140 numberOfTimes.remove(); 141 142 //「最初はぐーじゃんけん」の呼びかけの処理 143 signalTextArea.innerText = '最初はぐー'; 144 opponentImage.src = images[0]; // ぐーを固定化 145 opponentImage.width = "300"; 146 opponentImage.height = "300"; 147 signalImageArea.appendChild(opponentImage); 148 149 // メインの関数を実行 150 serectAndJudgment(); 151}; 152 153 154// 入力欄でEnterキーが押されてもゲームを実行 155numberOfTimes.onkeydown = event => { 156 if (event.key === 'Enter') { 157 startButton.onclick(); 158 } 159}; 160

投稿2020/08/28 10:58

suissuis

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問