简体   繁体   中英

Memory Game doesn't restart after winning

I'm trying to rebrand this cool Memory Game developed by Nate Wiley.

I'm having an issue with it though. When you win, it allows you to restart, but the game become unplayable when the cards re-appear for a second time.

The restart button code calls this function:

reset: function(){
    this.hideModal();
    this.shuffleCards(this.cardsArray);
    this.setup();
    this.$game.show();
},

This correctly hides the modal, shuffles the card, runs the setup function, and shows the game again.

The Setup Function looks like this:

setup: function(){
    this.html = this.buildHTML();
    this.$game.html(this.html);
    this.$memoryCards = $(".card");
    this.paused = false;
    this.guess = null;
},

I'm not getting any errors in the console. How would I go about diagnosing an error in this situation?

I've created a codepen with only 2 matching pairs to make testing a lot quicker but I'm at a loss for how to figure this out.

https://codepen.io/nolaandy/pen/wPeGgo

Udpated Codepen .

All you need to do is binding the click event using the event delegation on like :

$('body').on("click", ".card", this.cardClicked);

Instead of :

this.$memoryCards.on("click", this.cardClicked);

So when you reset the cards dynamically from the reset() function, the click event will persist and could deal with the new card elements.

Hope this help.

When you don't have errors in the console you need to think about what you'd expect the code to do and work back from there. In you example, I'd expect the game to do something when I click on the card, but it doesn't so I added a console.log() in the click handler and I noticed that nothing was being logged in the console so I though "probably the card element get's rebuilt from scratch, so it looses it's event listener", so I tried delegating the event to the body, with

$('body').on("click", ".card", this.cardClicked);

and I noticed that now the click event worked, so I knew I was getting somewhere. I still wanted to keep the click code the way it was so I noticed that in the setup function he doesn't call the binding function, which is the one that attaches click events to elements, so I tried calling this.binding(); inside the setup function and sure enough it works.

PS: In my opinion it would make sense to call the buinding() function inside the setup() function, because I probably want my click events to be attached to the buttons every time I set up a game, but I kept it the way it was to leave the code as similar as possible as the original one.

 // Memory Game // © 2014 Nate Wiley // License -- MIT // best in full screen, works on phones/tablets (min height for game is 500px..) enjoy ;) // Follow me on Codepen (function(){ var Memory = { init: function(cards){ this.$game = $(".game"); this.$modal = $(".modal"); this.$overlay = $(".modal-overlay"); this.$restartButton = $("button.restart"); this.cardsArray = $.merge(cards, cards); this.shuffleCards(this.cardsArray); this.setup(); this.binding(); }, shuffleCards: function(cardsArray){ this.$cards = $(this.shuffle(this.cardsArray)); }, setup: function(){ this.html = this.buildHTML(); this.$game.html(this.html); this.$memoryCards = $(".card"); this.binding(); this.paused = false; this.guess = null; }, binding: function(){ this.$memoryCards.on("click", this.cardClicked); $("button.restart").unbind().click( $.proxy(this.reset, this)); }, // kinda messy but hey cardClicked: function(){ var _ = Memory; var $card = $(this); if(!_.paused && !$card.find(".inside").hasClass("matched") && !$card.find(".inside").hasClass("picked")){ $card.find(".inside").addClass("picked"); if(!_.guess){ _.guess = $(this).attr("data-id"); } else if(_.guess == $(this).attr("data-id") && !$(this).hasClass("picked")){ $(".picked").addClass("matched"); _.guess = null; } else { _.guess = null; _.paused = true; setTimeout(function(){ $(".picked").removeClass("picked"); Memory.paused = false; }, 600); } if($(".matched").length == $(".card").length){ _.win(); } } }, win: function(){ this.paused = true; setTimeout(function(){ Memory.showModal(); Memory.$game.fadeOut(); }, 1000); }, showModal: function(){ this.$overlay.show(); this.$modal.fadeIn("slow"); }, hideModal: function(){ this.$overlay.hide(); this.$modal.hide(); }, reset: function(){ this.hideModal(); this.shuffleCards(this.cardsArray); this.setup(); this.$game.show(); }, // Fisher--Yates Algorithm -- https://bost.ocks.org/mike/shuffle/ shuffle: function(array){ var counter = array.length, temp, index; // While there are elements in the array while (counter > 0) { // Pick a random index index = Math.floor(Math.random() * counter); // Decrease counter by 1 counter--; // And swap the last element with it temp = array[counter]; array[counter] = array[index]; array[index] = temp; } return array; }, buildHTML: function(){ var frag = ''; this.$cards.each(function(k, v){ frag += '<div class="card" data-id="'+ v.id +'"><div class="inside">\\ <div class="front"><img src="'+ v.img +'"\\ alt="'+ v.name +'" /></div>\\ <div class="back"><img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/74196/codepen-logo.png"\\ alt="Codepen" /></div></div>\\ </div>'; }); return frag; } }; var cards = [ { name: "php", img: "https://s3-us-west-2.amazonaws.com/s.cdpn.io/74196/php-logo_1.png", id: 1, }, { name: "css3", img: "https://s3-us-west-2.amazonaws.com/s.cdpn.io/74196/css3-logo.png", id: 2 }, ]; Memory.init(cards); })(); 
 * { box-sizing: border-box; } html, body { height: 100%; } body { background: black; min-height: 100%; font-family: "Arial", sans-serif; } .wrap { position: relative; height: 100%; min-height: 500px; padding-bottom: 20px; } .game { transform-style: preserve-3d; perspective: 500px; min-height: 100%; height: 100%; } @keyframes matchAnim { 0% { background: #bcffcc; } 100% { background: white; } } .card { float: left; width: 16.66666%; height: 25%; padding: 5px; text-align: center; display: block; perspective: 500px; position: relative; cursor: pointer; z-index: 50; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } @media (max-width: 800px) { .card { width: 25%; height: 16.666%; } } .card .inside { width: 100%; height: 100%; display: block; transform-style: preserve-3d; transition: 0.4s ease-in-out; background: white; } .card .inside.picked, .card .inside.matched { transform: rotateY(180deg); } .card .inside.matched { animation: 1s matchAnim ease-in-out; animation-delay: 0.4s; } .card .front, .card .back { border: 1px solid black; backface-visibility: hidden; position: absolute; top: 0; left: 0; width: 100%; height: 100%; padding: 20px; } .card .front img, .card .back img { max-width: 100%; display: block; margin: 0 auto; max-height: 100%; } .card .front { transform: rotateY(-180deg); } @media (max-width: 800px) { .card .front { padding: 5px; } } .card .back { transform: rotateX(0); } @media (max-width: 800px) { .card .back { padding: 10px; } } .modal-overlay { display: none; background: rgba(0, 0, 0, .8); position: fixed; top: 0; left: 0; width: 100%; height: 100%; } .modal { display: none; position: relative; width: 500px; height: 400px; max-height: 90%; max-width: 90%; min-height: 380px; margin: 0 auto; background: white; top: 50%; transform: translateY(-50%); padding: 30px 10px; } .modal .winner { font-size: 80px; text-align: center; font-family: "Anton", sans-serif; color: #4d4d4d; text-shadow: 0px 3px 0 black; } @media (max-width: 480px) { .modal .winner { font-size: 60px; } } .modal .restart { font-family: "Anton", sans-serif; margin: 30px auto; padding: 20px 30px; display: block; font-size: 30px; border: none; background: #4d4d4d; background: linear-gradient(#4d4d4d, #222); border: 1px solid #222; border-radius: 5px; color: white; text-shadow: 0px 1px 0 black; cursor: pointer; } .modal .restart:hover { background: linear-gradient(#222, black); } .modal .message { text-align: center; } .modal .message a { text-decoration: none; color: #28afe6; font-weight: bold; } .modal .message a:hover { color: #56c0eb; border-bottom: 1px dotted #56c0eb; } .modal .share-text { text-align: center; margin: 10px auto; } .modal .social { margin: 20px auto; text-align: center; } .modal .social li { display: inline-block; height: 50px; width: 50px; margin-right: 10px; } .modal .social li:last-child { margin-right: 0; } .modal .social li a { display: block; line-height: 50px; font-size: 20px; color: white; text-decoration: none; border-radius: 5px; } .modal .social li a.facebook { background: #3b5998; } .modal .social li a.facebook:hover { background: #4c70ba; } .modal .social li a.google { background: #d34836; } .modal .social li a.google:hover { background: #dc6e60; } .modal .social li a.twitter { background: #4099ff; } .modal .social li a.twitter:hover { background: #73b4ff; } footer { height: 20px; position: absolute; bottom: 0; width: 100%; z-index: 0; } footer .disclaimer { line-height: 20px; font-size: 12px; color: #727272; text-align: center; } @media (max-width: 767px) { footer .disclaimer { font-size: 8px; } } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="wrap"> <div class="game"></div> <div class="modal-overlay"> <div class="modal"> <h2 class="winner">You Rock!</h2> <button class="restart">Play Again?</button> <p class="message">Developed on <a href="https://codepen.io">CodePen</a> by <a href="https://codepen.io/natewiley">Nate Wiley</a></p> <p class="share-text">Share it?</p> <ul class="social"> <li><a target="_blank" class="twitter" href="https://twitter.com/share?url=https://codepen.io/natewiley/pen/HBrbL"><span class="fa fa-twitter"></span></a></li> <li><a target="_blank" class="facebook" href="https://www.facebook.com/sharer.php?u=https://codepen.io/natewiley/pen/HBrbL"><span class="fa fa-facebook"></span></a></li> <li><a target="_blank" class="google" href="https://plus.google.com/share?url=https://codepen.io/natewiley/pen/HBrbL"><span class="fa fa-google"></span></a></li> </ul> </div> </div> <footer> <p class="disclaimer">All logos are property of their respective owners, No Copyright infringement intended.</p> </footer> </div><!-- End Wrap --> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM