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

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

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

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

Q&A

解決済

2回答

2353閲覧

【JavaScript】神経衰弱で2枚のカードの判定前に3枚目のカードをクリックできないようにしたい

Matt007

総合スコア8

JavaScript

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

0グッド

1クリップ

投稿2019/12/20 11:41

編集2019/12/20 12:05

神経衰弱のルール

動作の流れとしては以下の通りです。
① 16枚のカードの中から「?」と書かれたものをひとつクリック
② そのカードに書かれている「?」が「1」などの数字に変わる
③ もうひとつ「?」と書かれたものをクリックする
④ その要素に書かれている「?」が「1」などの数字に変わる
⑤ ②と④で表示された数字が一致している場合は、開いた数字はそのままで①に戻る。一致していない場合は1秒後に数字が「?」に戻り①にもどる。
⑥: 全ての要素が開かれたときにアラートで「Game Over」

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

現状、神経衰弱として動くところまではできていますが、2枚のカードの判定する前に3枚目のカードがクリックしたらカードが開いてしまいます。
以下のサイト参考にして作ってみましたが、どこに3枚目のカードが開かないようにカードをロックする処理を書けば良いかが分からず困っています。

該当のソースコード

html

1<!doctype html> 2<html> 3<head> 4<meta charset="UTF-8"> 5<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> 6<meta name="format-detection" content="telephone=no"> 7<title></title> 8<link rel="stylesheet" href="css/reset.css"> 9<link rel="stylesheet" href="css/base.css"> 10<link rel="stylesheet" href="css/style.css"> 11</head> 12<body> 13<ul class="lists clearfix"></ul> 14<script type="text/javascript" src="js/jquery.js"></script> 15<script type="text/javascript"> 16//jquery 17</script> 18</body> 19</html>

css

1.lists { 2 border: 10px #CCC solid; 3} 4.lists > li { 5 float: left; 6 width: 25%; 7 background-color: #EEE; 8 border-top: 2px #CCC solid; 9 border-right: 2px #CCC solid; 10 font-size: 20px; 11 font-weight: bold; 12 line-height: 75px; 13 text-align: center; 14 cursor: pointer; 15 -webkit-box-sizing: border-box; 16 box-sizing: border-box; 17} 18.lists > li:nth-child(-n + 4) { 19 border-top: none; 20} 21.lists > li:nth-child(4n) { 22 border-right: none; 23}

JavaScript

1/** 2 * (説明) 3 * @type {array} cardNum ← カードの配列 4 * @type {string} totalCard ← カードの枚数 5 * @param {object} $card ← カードの引数 6 * @type {string} $firstCard ← カードをめくる1枚目 7 * @type {string} $secondCard ← カードをめくる2枚目 8 * @type {firstNum} $firstNum ← カードに書かれている数字 9 * @type {secondNum} $secondNum ← カードに書かれてる数字 10 * @type {string} $openedCard ← めくられたカード 11 * 12 * 13**/ 14$(function(){ 15 let cardNum = []; 16 let totalCard = 16; 17 18 function open($card){ 19 $card.css('pointer-events', 'none'); 20 $card.text($card.data('num')); 21 } 22 23 function close($card){ 24 $card.css('pointer-events', ''); 25 $card.text('?'); 26 } 27 28 function compare($card){ 29 // 1枚目に開いたカードが存在するか確認 30 // 存在すれば、即ち、現在は2枚目のカードを開いたところ 31 if($('.firstOpen').length == 0){ 32 // 開いたカードが一枚目のカードであれば、 33 // この要素が1枚目であることがわかるようにするため、 34 // firstOpenのクラスを付与しておく 35 $card.addClass('firstOpen'); 36 }else{ 37 // 1枚目のカードのjQueryオブジェクト 38 let $firstCard = $('.firstOpen'); 39 // 2枚目のカードのjQueryオブジェクト 40 let $secondCard = $card; 41 42 // 1枚目のカードの数字 43 let firstNum = $firstCard.data('num'); 44 // 2枚目のカードの数字 45 let secondNum = $secondCard.data('num'); 46 47 // 1枚目識別用のクラスを削除 48 $firstCard.removeClass('firstOpen'); 49 50 // 一致している場合、両方からunopenedを削除する 51 // その後、unopenedが付与された要素の数を確認し、 52 // 0個であれば、アラートを表示する 53 if(firstNum === secondNum){ 54 $firstCard.removeClass('unopened'); 55 $secondCard.removeClass('unopened'); 56 57 if($('.unopened').length === 0){ 58 alert("Game Over"); 59 } 60 // 一致していない場合、二枚とも閉じる 61 }else{ 62 close($firstCard); 63 close($secondCard); 64 } 65 } 66 } 67 68 // カードの中身を作成 69 for (var i = 1; i <= totalCard/2; i++){ 70 cardNum.push(i,i); 71 } 72 73 // ランダムに並べ替えて 74 // li要素を作成して 75 // listに追加 76 77 cardNum 78 .sort(function(){ 79 return Math.random() - Math.random(); 80 }) 81 .map(function(num){ 82 return "<li class='unopened' data-num='" + num + "'>?</li>"; 83 }) 84 .forEach(function(element){ 85 $(".lists").append(element); 86 }); 87 88 $('.lists li').on('click', function(){ 89 // クリックされたカード(li要素)のjQueryオブジェクト 90 let $openedCard = $(this); 91 92 // カードをオープン 93 open($openedCard); 94 95 // カードを比較 96 // 1秒ほど待機させてから比較させる 97 // ※待機しないと二枚目のカードの番号が表示されるとほぼ同時ぐらいに比較が終わり 98 // 二枚目のカードの数字がわかりにくいため 99 setTimeout(function(){ 100 compare($openedCard); 101 }, 1000); 102 }); 103});

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

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

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

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

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

guest

回答2

0

ベストアンサー

色々なやり方があると思いますが、フラグを使った方法を示します。
サンプル

まず、compareの待機を消します。

js

1 $('.lists li').on('click', function(){ 2 // クリックされたカード(li要素)のjQueryオブジェクト 3 let $openedCard = $(this); 4 5 // カードをオープン 6 open($openedCard); 7 8 // カードを比較 9 compare($openedCard); 10 });

代わりに、カードを閉じる処理に待機時間を付けます。

js

1 // 一致していない場合、二枚とも閉じる 2 }else{ 3 setTimeout(function(){ 4 close($firstCard); 5 close($secondCard); 6 }, 1000); 7 }

これは、待機時間が必要なのは比較処理ではなくて、カードを閉じる処理であるはずだからです。

そして、フラグの定義をします。

js

1 let cardNum = []; 2 let totalCard = 16; 3 let f = false;

クリックイベント内で、フラグが立っているときには何もしない処理を書きます。

js

1 $('.lists li').on('click', function(){ 2 if (f) return;

こうすれば、フラグが立っているときにクリックされてもカードは開きません。

後は、適切にフラグの立て降ろしを書いていきます。
フラグを立てるのは、カードをめくった時。

js

1 // クリックされたカード(li要素)のjQueryオブジェクト 2 f = true; 3 let $openedCard = $(this);

フラグを下すのは、1枚目だった時と、

js

1 f = false; 2 $card.addClass('firstOpen');

2枚目で外れカードを閉じた時と、

js

1 f = false; 2 close($firstCard); 3 close($secondCard);

2枚目で当たりだった時。

js

1 // 一致している場合、両方からunopenedを削除する 2 // その後、unopenedが付与された要素の数を確認し、 3 // 0個であれば、アラートを表示する 4 if(firstNum === secondNum){ 5 f = false; 6 $firstCard.removeClass('unopened'); 7 $secondCard.removeClass('unopened');

以上です。

投稿2019/12/21 01:51

Lhankor_Mhy

総合スコア35865

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

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

Matt007

2019/12/21 06:41

回答ありがとうございます。 すごく分かりやすくて勉強になりました。 おかげさまで3枚目のカードをクリックしたときにカードが開かないようになりました。
guest

0

そこまで綺麗な実装ではないですが、あと何枚カードを開けるか、と言うのをtotalCard変数と同じスコープで保存すると言うのはどうでしょう?
totalCard = 2;

javascript

1open(){ 2 // 開くことができない時(=三枚目を開こうとした時) 3 if(totalCard === 0){ 4 // do nothing 5 }else{ 6 カードを開く処理 7 // 一枚めくったためdecrement 8 totalCard-- 9 } 10} 11 12compare(){ 13 比較が終わったらtotalCardを2に戻す 14 totalCard = 2; 15} 16

こんな感じでやってみてください

投稿2019/12/20 12:11

shinyaigeek

総合スコア112

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

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

Matt007

2019/12/20 12:21

回答ありがとうございます。 実際にやってみたんですが、2枚クリックしてカード判定の直後にカードをクリックすると3枚目のカードが開いてしまいます…
shinyaigeek

2019/12/20 13:10

上記のやつは2枚目のカードを開く->比較するの処理のブロックの最後にtotalCard = 2をやってくださいって意味でした。。わかりにくくてすみません。。
Matt007

2019/12/20 13:28

$(function(){ let cardNum = []; let totalCard = 16; function open($card){ $card.css('pointer-events', 'none'); $card.text($card.data('num')); // 開くことができない時(=三枚目を開こうとした時) if(totalCard === 0){ // do nothing }else{ カードを開く処理 // 一枚めくったためdecrement totalCard-- } } function close($card){ $card.css('pointer-events', ''); $card.text('?'); } function compare($card){ if($('.firstOpen').length == 0){ $card.addClass('firstOpen'); }else{ let $firstCard = $('.firstOpen'); let $secondCard = $card; let firstNum = $firstCard.data('num'); let secondNum = $secondCard.data('num'); $firstCard.removeClass('firstOpen'); if(firstNum === secondNum){ $firstCard.removeClass('unopened'); $secondCard.removeClass('unopened'); if($('.unopened').length === 0){ alert("Game Over"); } }else{ close($firstCard); close($secondCard); } } 比較が終わったらtotalCardを2に戻す totalCard = 2; } for (var i = 1; i <= totalCard/2; i++){ cardNum.push(i,i); } cardNum .sort(function(){ return Math.random() - Math.random(); }) .map(function(num){ return "<li class='unopened' data-num='" + num + "'>?</li>"; }) .forEach(function(element){ $(".lists").append(element); }); $('.lists li').on('click', function(){ let $openedCard = $(this); open($openedCard); setTimeout(function(){ compare($openedCard); }, 1000); }); }); とやってみましたが、やはり3枚目のカードが開いたままです。 どこが間違っているかをお手隙に教えていただけると幸いです。
Matt007

2019/12/21 01:19

やってみたんですが、やはり3枚目のカードが開いたままになってしまいます…
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問