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

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

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

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

Q&A

解決済

1回答

1226閲覧

【JavaScript】神経衰弱でカードを開いたときの処理に枚数チェックと比較関数に飛ぶようにしたいです

Matt007

総合スコア8

JavaScript

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

0グッド

0クリップ

投稿2019/12/24 12:49

編集2019/12/24 23:45

神経衰弱のルール

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

実現したいこと

現状、カードをクリックするたびにcompare関数に値を投げて処理を書いてますが、compareするのは2枚目をクリックしたときだと書き終わったときに気付きました。

そうすると、
$('.firstOpen').length == 0
この辺の処理が不要になるというところまでは理解できました。

そうなると、クリックイベントではなく、カードオープンの処理には枚数チェックと比較関数へ飛ばす処理を書けば良いと思うんですが、以下の比較関数の記事を参考にやってみましたが、上手く処理を書けず困っています。
https://www.sejuku.net/blog/62904
※該当のソースコードは動作するコードです。

該当のソースコード

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

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

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

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

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

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

Lhankor_Mhy

2019/12/25 01:02

つまり、if($('.firstOpen').length == 0){} を、compare関数の外に出したい、ということですか?
Matt007

2019/12/25 01:21

質問ありがとうございます。 少なくともcompare関数の外に出す形で実装したいと考えてます。
guest

回答1

0

ベストアンサー

処理の流れを、
現在:click() => open() => compare()[ココで比較が必要か判断]
変更:click() => open()[ココで比較が必要か判断] => compare()
にしたいという事かなと受け取りまして、以下のような形でしょうか?

もろもろ省略したりしてます。

CODEPENご参照ください。

javascript

1$(function() { 2 let cardNum = []; 3 let totalCard = 16; 4 let f = false; 5 6 function open($card) { 7 $card 8 .css("pointer-events", "none") 9 .text($card.data("num")) 10 .addClass("fliped"); //openが走ったら、クラスはすべてに付与 11 if ($(".fliped").length === 2) compare(); //2枚flipされていたら比較 12 } 13 14 function close($card) { 15 $(".fliped") 16 .css("pointer-events", "") 17 .text("?") 18 .removeClass("fliped"); //closeの時にしかflipedは変更しないのでココに 19 } 20 21 function compare() { 22 let $firstCard = $(".fliped").eq(0); //比較対象1枚目 23 let $secondCard = $(".fliped").eq(1); //比較対象2枚目  24 25 let firstNum = $firstCard.data("num"); 26 let secondNum = $secondCard.data("num"); 27 28 if (firstNum === secondNum) { 29 $firstCard.add($secondCard).removeClass("unopened fliped"); //ココ追加flipedの消し忘れ 30 31 if ($(".unopened").length === 0) { 32 alert("Game Over"); 33 } 34 } else { 35 setTimeout(function() { 36 close(); 37 }, 1000); 38 } 39 } 40 41 //初期配置 42 (() => { 43 for (var i = 1; i <= totalCard / 2; i++) cardNum.push(i, i); 44 cardNum 45 .sort(() => { 46 return Math.random() - Math.random(); 47 }) 48 .map(num => { 49 return "<li class='unopened' data-num='" + num + "'>?</li>"; 50 }) 51 .forEach(element => { 52 $(".lists").append(element); 53 }); 54 })(); 55 56 //クリックイベント 57 $(".lists li").on("click", function() { 58 if ($(".fliped").length > 1) return; 59 open($(this)); 60 61 /*フラグの判定が拾えなかったので、上記に修正しました 62 if (f) return; 63 f = true; //フラグが散らばっていたので、ココに集約 64 open($(this)); 65 f = false; 66 */ 67 }); 68}); 69

css

1.lists > li { 2 list-style-type: none;/*ココ追加*/ 3 float: left; 4 width: 25%; 5 background-color: pink;/*ココ変更*/ 6 border-top: 2px #ccc solid; 7 border-right: 2px #ccc solid; 8 font-size: 20px; 9 font-weight: bold; 10 line-height: 75px; 11 text-align: center; 12 cursor: pointer; 13 -webkit-box-sizing: border-box; 14 box-sizing: border-box; 15} 16.lists > li:nth-child(-n + 4) { 17 border-top: none; 18} 19.lists > li:nth-child(4n) { 20 border-right: none; 21} 22.unopened { 23 background-color: #eee!important; /*ココ追加*/ 24} 25.fliped { 26 background-color: orange!important; /*ココ追加*/ 27}

投稿2019/12/25 01:10

編集2019/12/26 05:57
satoshi_tajima

総合スコア337

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

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

Matt007

2019/12/25 11:38 編集

1ペア完成した後にカードの判定ができてなかったです。
Matt007

2019/12/25 11:39 編集

後、カードを判定したときに3枚目のカードが開いてしまいます。
satoshi_tajima

2019/12/26 05:57

失礼しました。回答の一部を修正しました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問