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

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

ただいまの
回答率

91.36%

  • JavaScript

    11189questions

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

関数の定義と呼び出しの記述について

解決済

回答 3

投稿 2017/12/01 20:13 ・編集 2017/12/02 01:20

  • 評価
  • クリップ 0
  • VIEW 118

narururu

score 12

実現したいこと

スタートボタンを押すとpairsで定義した全ての枚数のカードが裏返しになる。

現状

スタートボタンを押しても何も変化なし。

ソースコード

html

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>Memory Game</title>
  <link rel="stylesheet" href="css/styles.css">
</head>
<body>
  <div class="container">
    <div id="score">0.00</div>
    <div id="stage">
      <!-- <div class="card-container">
        <div class="card">
          <div class="card-front">1</div>
          <div class="card-back">?</div>
        </div>
      </div> -->
    </div>
    <div id="btn">スタート</div>
  </div>
  <script src="js/main.js"></script>
</body>
</html>


css

body {
  background: #3498db;
  font-family: Arial, sans-serif;
  font-size: 16px;
  font-weight: bold;
}

.container {
  width: 360px;
  margin: 20px auto;
}

#stage {
  display: flex;
  flex-wrap: wrap;
}

.card-container {
  perspective: 100px;
  width: 50px;
  height: 70px;
  margin: 5px;
}

.card {
  cursor: pointer;
  width: 100%;
  height: 100%;
  transition: 0.8s;
  position: relative;
  transform-style: preserve-3d;
}

.card-front,
.card-back {
  width: 100%;
  height: 100%;
  text-align: center;
  line-height: 70px;
  border-radius: 8px;
  position: absolute;
  top: 0;
  left: 0;
  backface-visibility: hidden;
  box-shadow: 0 5px 0 rgba(0, 0, 0, 0.2);
}

.card-back {
  background: #f1c40f;
  color: #fff;
}
.card-back:hover {
  opacity: 0.8;
}

.card-front {
  background: #fff;
  color: #f1c40f;
  transform: rotateY(180deg);
}

.card.open {
  transform: rotateY(180deg);
}

.container div {
  display: inline-block;
}
.container p {
  font-size: 20px;
  color: #fff;
  text-align: left;
  margin: 0 5px 10px 0;
  width: 150px:
}

#score {
  font-size: 20px;
  color: #fff;
  text-align: right;
  margin: 0 5px 10px 0;
  width: 150px:
}

#btn {
  background: gray;
  color: #fff;
  height: 40px;
  border-radius: 20px;
  line-height: 40px;
  text-align: center;
  font-size: 18px;
  margin: 15px auto 0;
  box-shadow: 0 5px 0 rgba(0, 0, 0, 0.2);
  width: 300px;
  cursor: pointer;
}

js

(function() {
  'use strict';

  var pairs = 2;
  var cards = [];

  var flipCount = 0;
  var firstCard = null;
  var secondCard = null;

  var startTime;
  var isRunning = false;
  var correctCount = 0;
  var timeoutId;


  function init() {
    var i;
    var card;
    for (i = 1; i <= pairs; i++) {
      cards.push(createCard(i));
      cards.push(createCard(i));
      // document.getElementById('stage').appendChild(createCard(i));
      // document.getElementById('stage').appendChild(createCard(i));
    }
    while (cards.length) {
      card = cards.splice(Math.floor(Math.random() * cards.length), 1)[0];
      document.getElementById('stage').appendChild(card);
    }
  }

  function createCard(num) {
    var container;
    var card;
    var inner;
    inner = '<div class="card-front">' + num + '</div><div class="card-back">?</div>';
    card = document.createElement('div');
    card.innerHTML = inner;
    card.className = 'card';
    card.addEventListener('click', function() {
      flipCard(this);
      if (isRunning === true) {
        return;
      }
      isRunning = true;
      startTime = Date.now();
      runTimer();
      document.getElementById('restart').className = '';
    });
    container = document.createElement('div');
    container.className = 'card-container';
    container.appendChild(card);
    return container;
  }

  function flipCard(card) {
    if (firstCard !== null && secondCard !== null) {
      return;
    }
    if (card.className.indexOf('open') !== -1) {
      return;
    }
    card.className = 'card open';
    flipCount++;
    if (flipCount % 2 === 1) {
      firstCard = card;
    } else {
      secondCard = card;
      secondCard.addEventListener('transitionend', check);
    }
  }

  function check() {
    if (
      firstCard.children[0].textContent !==
      secondCard.children[0].textContent
    ) {
      firstCard.className = 'card';
      secondCard.className = 'card';
    } else {
      correctCount++;
      if (correctCount === pairs) {
        clearTimeout(timeoutId);
      }
    }
    secondCard.removeEventListener('transitionend', check);
    firstCard = null;
    secondCard = null;
  }

  function runTimer() {
    document.getElementById('score').textContent = ((Date.now() - startTime) / 1000).toFixed(2);
    timeoutId = setTimeout(function() {
      runTimer();
    }, 10);
  }

  init();
})();

//ここのコードです
function startBtn(btn) {
  btn.addEventListener("click", function(){
    card.className = "card open";
  });
}
startBtn();
//ここまで


どなたか、ご回答よろしくお願いいたします。

追記

エラーメッセージは以下の通りです。画面をキャプチャしました。
ご確認お願いいたします。
https://i.gyazo.com/ad85ab2371a0e99421607a1d49f94c02.png
https://i.gyazo.com/ca8988669dc4ff155ec34705ed36eb45.png

皆様、本当にご丁寧なアドバイスありがとうございました。
皆様にベストアンサーを差し上げたいところですが、今回は実現したい内容をコードとして提示してくださった方をベストアンサーとさせていただきます。
本当にありがとうございました(>_<)

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • defghi1977

    2017/12/01 20:24

    少なくともエラーを吐いているはずなので, まずはどのようなエラーか確認して下さい

    キャンセル

  • 退会済みユーザー

    2017/12/01 20:27

    複数のユーザーから「やってほしいことだけを記載した丸投げの質問」という意見がありました
    「質問を編集する」ボタンから編集を行い、調査したこと・試したことを記入していただくと、回答が得られやすくなります。

回答 3

+4

プログラムを学ぶ上でエラーの内容を理解することは重要です. 大抵は英語で出力されるためとっつきにくいかもしれませんが, 内容そのものはさほど難しくない(中学英語で十分理解できる範囲)ですので頑張って下さい. 


さて, エラーが発生している原因ですがエラーメッセージのとおりです. つまり
"Can not read property 'addEventListener' of undefined"
訳すと
undefinedのプロパティaddEventListenerを読み込むことが出来ません」
です. 

で, なぜこのようなエラーが発生しているのかというと当該コードにおいて,

//ここのコードです
function startBtn(btn) {
  btn.addEventListener("click", function(){
    card.className = "card open";
  });
}
startBtn();//←???
//ここまで

関数startBtnを定義した後, 呼び出し時の引数として何も渡していません. これをJavaScriptではundefinedが渡された」と解釈します. (「りんごがない」を「りんごが0個ある」と言い換えるのと同じです.)

従って関数startBtn定義部の引数であるbtn変数にはundefinedが渡されます. ここでundefined何もないことを表す定数ですから, そこにaddEventListenerメソッドは存在しません. にもかかわらず, あなたはaddEventListenerメソッドを呼び出そうとしました. 

このことで先ほどのエラー"Can not read property 'addEventListener' of undefined"が発生したのです.

つまり, この問題は関数startBtnaddEventListenerメソッドをもつ何かを渡せばよかったのです.

そうすると次には「addEventListenerメソッドをもつ何か」とは何だろうとなります. そこでs8_chuさんが提示したようなコードが現れるのです.

//ここのコードです
function startBtn(btn) {
  btn.addEventListener("click", function(){
    card.className = "card open";
  });
}
startBtn(document.getElementById("btn"));//←ここにボタンを渡している
//ここまで

しかし、頂いたコードでは、スタートボタンをクリックしても全てのカードが裏返しになることはありませんでした。

少なくともこれで, エラーは一つ解決しました. ですから今度はあなたが動かない原因をもう一度見つけ, それが解決できないのであれば改めて質問されると良いでしょう. 

プログラムを行う上で大事なことは, いつも小さなコードを作ってそれが正しく動くことを確認していき, それを集めて大きなプロダクトにしていくことです. ですから, 今回あなたが提示したように「大きなコード」を動かないからと言ってそのまままるごと「動きません。なぜですか?」と言われても, 答える側としては, 「それは問題の切り分けが出来ていないあなたの責任」といったように見えてしまっているのです.  

勿論、これ以上回答を依頼することはしません。私自身で考え問題解決するよう努めさせていただきます。

むしろ, 積極的に質問して下さい. もちろん何がわからないのか・どこに詰まっているかが判るように「必要最低限のコードで」という条件付きではありますが, 答えやすい問であれば皆さん快く回答してくださるはずです. 

投稿 2017/12/02 00:53

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/02 01:11

    ご回答ありがとうございます。
    今回の質問は私自身で考えず、答えだけを求めている内容になってしまいました。コード量も多く、質問する側がきちんと把握できていない証拠です。
    今後は、回答者様が答えやすい問いになるように、エラーメッセージから自分で考え検証するというプロセスを経て、質問していきます。
    ご丁寧なアドバイスありがとうございます。

    キャンセル

checkベストアンサー

+3

質問者さんが実現したいことは以下のようにすることで行えると思います。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <title>Memory Game</title>
    <style type="text/css">
        body {
            background: #3498db;
            font-family: Arial, sans-serif;
            font-size: 16px;
            font-weight: bold;
        }

        .container {
            width: 360px;
            margin: 20px auto;
        }

        #stage {
            display: flex;
            flex-wrap: wrap;
        }

        .card-container {
            perspective: 100px;
            width: 50px;
            height: 70px;
            margin: 5px;
        }

        .card {
            cursor: pointer;
            width: 100%;
            height: 100%;
            transition: 0.8s;
            position: relative;
            transform-style: preserve-3d;
        }

        .card-front,
        .card-back {
            width: 100%;
            height: 100%;
            text-align: center;
            line-height: 70px;
            border-radius: 8px;
            position: absolute;
            top: 0;
            left: 0;
            backface-visibility: hidden;
            box-shadow: 0 5px 0 rgba(0, 0, 0, 0.2);
        }

        .card-back {
            background: #f1c40f;
            color: #fff;
        }

        .card-back:hover {
            opacity: 0.8;
        }

        .card-front {
            background: #fff;
            color: #f1c40f;
            transform: rotateY(180deg);
        }

        .card.open {
            transform: rotateY(180deg);
        }

        .container div {
            display: inline-block;
        }

        .container p {
            font-size: 20px;
            color: #fff;
            text-align: left;
            margin: 0 5px 10px 0;
            width: 150px; /* コロンではなく、セミコロン */
        }

        #score {
            font-size: 20px;
            color: #fff;
            text-align: right;
            margin: 0 5px 10px 0;
            width: 150px; /* コロンではなく、セミコロン */
        }

        #btn {
            background: gray;
            color: #fff;
            height: 40px;
            border-radius: 20px;
            line-height: 40px;
            text-align: center;
            font-size: 18px;
            margin: 15px auto 0;
            box-shadow: 0 5px 0 rgba(0, 0, 0, 0.2);
            width: 300px;
            cursor: pointer;
        }

        .hidden {
            display: none !important;
        }
    </style>
</head>
<body>
<div class="container">
    <div id="score">0.00</div>
    <div id="stage">
        <!-- <div class="card-container">
          <div class="card">
            <div class="card-front">1</div>
            <div class="card-back">?</div>
          </div>
        </div> -->
    </div>
    <div id="btn">スタート</div>
    <div id="restart" class="hidden">restart</div>
</div>
<script>
    (function () {
        'use strict';

        var pairs = 2;
        var cards = [];

        var flipCount = 0;
        var firstCard = null;
        var secondCard = null;

        var startTime;
        var isRunning = false;
        var correctCount = 0;
        var timeoutId;


        function init() {
            var i;
            var card;
            for (i = 1; i <= pairs; i++) {
                cards.push(createCard(i));
                cards.push(createCard(i));

                // document.getElementById('stage').appendChild(createCard(i));
                // document.getElementById('stage').appendChild(createCard(i));
            }

            while (cards.length) {
                card = cards.splice(Math.floor(Math.random() * cards.length), 1)[0];
                document.getElementById('stage').appendChild(card);
            }
        }


        function createCard(num) {
            var container;
            var card;
            var inner;
            inner = '<div class="card-front">' + num + '</div><div class="card-back">?</div>';
            card = document.createElement('div');
            card.innerHTML = inner;
            card.className = 'card';
            card.addEventListener('click', function () {
                flipCard(this);
                if (isRunning === true) {
                    return;
                }
                isRunning = true;
                startTime = Date.now();
                runTimer();
                document.getElementById('restart').className = '';
            });
            container = document.createElement('div');
            container.className = 'card-container';
            container.appendChild(card);
            return container;
        }

        function flipCard(card) {
            if (firstCard !== null && secondCard !== null) {
                return;
            }
            if (card.className.indexOf('open') !== -1) {
                return;
            }
            card.className = 'card open';
            card.querySelector(".card-back").style.zIndex = -1;
            flipCount++;
            if (flipCount % 2 === 1) {
                firstCard = card;
            } else {
                secondCard = card;
                secondCard.addEventListener('transitionend', check);
            }
        }

        function check() {
            if (
                firstCard.children[0].textContent !==
                secondCard.children[0].textContent
            ) {
                firstCard.className = 'card';
                secondCard.className = 'card';
            } else {
                correctCount++;
                if (correctCount === pairs) {
                    clearTimeout(timeoutId);
                }
            }
            secondCard.removeEventListener('transitionend', check);
            firstCard = null;
            secondCard = null;
        }

        function runTimer() {
            document.getElementById('score').textContent = ((Date.now() - startTime) / 1000).toFixed(2);
            timeoutId = setTimeout(function () {
                runTimer();
            }, 10);
        }

        init();

        //ここのコードです
        function startBtn(btn) {

            btn.addEventListener("click", function () {


                for (var i = 0, e = document.querySelectorAll(".card-container .card"); i < e.length; i++) {
                    e[i].className = "card open";
                    e[i].querySelector(".card-back").style.zIndex = -1;
                }
            });
        }

        startBtn(document.getElementById("btn"));
        //ここまで
    })();
</script>
</body>
</html>

投稿 2017/12/01 23:43

編集 2017/12/02 00:44

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/02 00:07

    ご回答ありがとうございます。
    丸投げな質問に対し、ご丁寧にコードまで記述していただき恐縮です。
    しかし、頂いたコードでは、スタートボタンをクリックしても全てのカードが裏返しになることはありませんでした。
    勿論、これ以上回答を依頼することはしません。私自身で考え問題解決するよう努めさせていただきます。
    貴重なアドバイス、ありがとうございました。

    キャンセル

  • 2017/12/02 00:56 編集

    > 頂いたコードでは、スタートボタンをクリックしても全てのカードが裏返しになることはありませんでした。... 私自身で考え問題解決するよう努めさせていただきます。
    念のため回答を修正しておきました。

    キャンセル

  • 2017/12/02 01:01

    s8_chuさん、わざわざありがとうございます。
    参考にさせていただきます。
    いつもいつも、本当に助かります!
    このコードを基にいろいろ試してみます☺
    私はちゃんと勉強しないと(>_<)

    キャンセル

+2

cardやbtnがつかめてないですね。
idを指定してオブジェクトをつかむ方式に
document.querySelector('#hoge')と
document.getElementById('hoge')があるので
そのあたりから学習されるとよいでしょう

投稿 2017/12/01 20:49

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/01 21:03

    ご回答ありがとうございます。
    そうですね。
    私はまず、きちんと学習することから始めます。
    丸投げ質問にならないよう気を付けます。

    キャンセル

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

ただいまの回答率

91.36%

関連した質問

同じタグがついた質問を見る

  • JavaScript

    11189questions

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