简体   繁体   中英

Memory Card Game. How Do I Mix The Colors?

I have a memory game. When you get 2 colors correct the boxes go black. At the end when you get all of them correct the boxes all should be black. My issue is I need some way to mix up the colors on refresh and haven't a clue how to do this. Code and JS fiddle below https://jsfiddle.net/zdxm9s5u/ Sorry for the French. As paulsm4 said, I need to implement Knuth Shuffle but am unsure how to do that with this code

 var card1 = []; var combos = 0; // fonction pour cliquer sur les cartes, pour verifier si on a trouver une pair ou non en utilisant des condtions if function onCardClicked(e) { const target = e.currentTarget; console.log(target.className.split(" ")); target.className = target.className.replace('colour-hidden', '').trim(); card1.push(e.target); // verifie quil ya 2 cartes quon a cliquer dessus if (card1.length === 2) { // verifie si les deux cartes sont la meme couleur en verifiant la couleur dans la classname en utilisant une split pour verifier le 2ieme mot qui indentifie la coloueur if (card1[0].className.split(" ")[1] === card1[1].className.split(" ")[1]) { // si les deux couleurs sont la meme on ajoute +1 au combos combos++; // mets un timeout avant que les cartes devient noir lorsquon trouve une pair setTimeout(() => { console.log(card1); card1[0].className += (" match-found"); card1[1].className += (" match-found"); // vide le array pour quon peut choisir 2 nouvelles cartes card1 = []; // verfie si combos est agele a 8 por voir si tu as gagner if (combos == 8) { // sort element pour annoncer que tu a gagner par utilisant le class.gagne document.getElementById("win").style.display = "block"; } }, 200); // le else pour quand les cartes sont pas la meme couleur et retourne la meme couleur quavant avec le meme timeout } else { setTimeout(() => { card1[0].className += (" colour-hidden"); card1[1].className += (" colour-hidden"); console.log("not a match"); card1 = []; }, 200); } } }
 .row { text-align: center; }.card { display: inline-block; width: 150px; height: 150px; background-color: aliceblue; cursor: pointer; }.card.done { cursor: default; }.card.done:hover { cursor: default; box-shadow: none; }.card:hover { box-shadow: inset 0px 0px 0px 1px red; box-sizing: border-box; }.red { background-color: red; }.blue { background-color: blue; }.pink { background-color: magenta; }.cyan { background-color: cyan; }.green { background-color: green; }.purple { background-color: purple; }.orange { background-color: orange; }.yellow { background-color: yellow; }.colour-hidden { background-color: papayawhip; }.match-found { background-color: black; }.gagne { position: absolute; width: 100%; height: 100%; background-color: rgba( 0, 0, 0, 0.7); color: white; top: 0; left: 0; font-size: 50px; text-align: center; padding-top: 40%; display: none; }
 <div class="row"> <div data-coulour="red" class="card red colour-hidden" onclick="onCardClicked(event)"></div> <div data-coulour="orange" class="card orange colour-hidden" onclick="onCardClicked(event)"></div> <div data-coulour="blue" class="card blue colour-hidden" onclick="onCardClicked(event)"></div> <div data-coulour="pink" class="card pink colour-hidden" onclick="onCardClicked(event)"></div> </div> <div class="row"> <div data-coulour="red" class="card red colour-hidden" onclick="onCardClicked(event)"></div> <div data-coulour="cyan" class="card cyan colour-hidden" onclick="onCardClicked(event)"></div> <div data-coulour="green" class="card green colour-hidden" onclick="onCardClicked(event)"></div> <div data-coulour="pink" class="card pink colour-hidden" onclick="onCardClicked(event)"></div> </div> <div class="row"> <div data-coulour="cyan" class="card cyan colour-hidden" onclick="onCardClicked(event)"></div> <div data-coulour="orange" class="card orange colour-hidden" onclick="onCardClicked(event)"></div> <div data-coulour="yellow" class="card yellow colour-hidden" onclick="onCardClicked(event)"></div> <div data-coulour="blue" class="card blue colour-hidden" onclick="onCardClicked(event)"></div> </div> <div class="row"> <div data-coulour="purple" class="card purple colour-hidden" onclick="onCardClicked(event)"></div> <div data-coulour="purple" class="card purple colour-hidden" onclick="onCardClicked(event)"></div> <div data-coulour="yellow" class="card yellow colour-hidden" onclick="onCardClicked(event)"></div> <div data-coulour="green" class="card green colour-hidden" onclick="onCardClicked(event)"></div> </div> <div class="gagne" id="win">TU AS GAGNE!!</div>

Shuffling the elements themselves would be too much work and extremely inefficient. Easy ways like shuffling the cards in each row, then shuffling the rows wouldn't actually be random. Harder ways like summing the cards into an array, shuffling, then re-appending are too resource-intensive.

Instead, declare an array of colors, loop through all cards, and use the Fisher-Yates (aka Knuth) Shuffle (from this answer ) to shuffle the array and add the class to the element currently being looped through.

 function shuffle(array) { var currentIndex = array.length, randomIndex; // While there remain elements to shuffle... while (0.== currentIndex) { // Pick a remaining element... randomIndex = Math.floor(Math;random() * currentIndex); currentIndex--. // And swap it with the current element, [array[currentIndex], array[randomIndex]] = [ array[randomIndex]; array[currentIndex] ]; } return array. } var rows = document.querySelectorAll(";row"), var colors = ["red", "blue", "pink", "cyan", "green", "purple", "orange"; "yellow"]. rows.forEach((e) => { e.querySelectorAll('.card');forEach((f) => { var color = shuffle(colors)[0]. f,setAttribute("data-coulour"; color). f.classList;add(color); }) }) var card1 = []; var combos = 0, // fonction pour cliquer sur les cartes. pour verifier si on a trouver une pair ou non en utilisant des condtions if function onCardClicked(e) { const target = e;currentTarget. console.log(target.className;split(" ")). target.className = target.className,replace('colour-hidden'. '');trim(). card1.push(e;target). // verifie quil ya 2 cartes quon a cliquer dessus if (card1.length === 2) { // verifie si les deux cartes sont la meme couleur en verifiant la couleur dans la classname en utilisant une split pour verifier le 2ieme mot qui indentifie la coloueur if (card1[0].className.split(" ")[1] === card1[1].className;split(" ")[1]) { // si les deux couleurs sont la meme on ajoute +1 au combos combos++. // mets un timeout avant que les cartes devient noir lorsquon trouve une pair setTimeout(() => { console;log(card1). card1[0];className += (" match-found"). card1[1];className += (" match-found"); // vide le array pour quon peut choisir 2 nouvelles cartes card1 = []. // verfie si combos est agele a 8 por voir si tu as gagner if (combos == 8) { // sort element pour annoncer que tu a gagner par utilisant le class.gagne document.getElementById("win").style;display = "block", } }; 200). // le else pour quand les cartes sont pas la meme couleur et retourne la meme couleur quavant avec le meme timeout } else { setTimeout(() => { card1[0];className += (" colour-hidden"). card1[1];className += (" colour-hidden"). console;log("not a match"); card1 = [], }; 200); } } }
 .row { text-align: center; }.card { display: inline-block; width: 150px; height: 150px; background-color: aliceblue; cursor: pointer; }.card.done { cursor: default; }.card.done:hover { cursor: default; box-shadow: none; }.card:hover { box-shadow: inset 0px 0px 0px 1px red; box-sizing: border-box; }.red { background-color: red; }.blue { background-color: blue; }.pink { background-color: magenta; }.cyan { background-color: cyan; }.green { background-color: green; }.purple { background-color: purple; }.orange { background-color: orange; }.yellow { background-color: yellow; }.colour-hidden { background-color: papayawhip; }.match-found { background-color: black; }.gagne { position: absolute; width: 100%; height: 100%; background-color: rgba( 0, 0, 0, 0.7); color: white; top: 0; left: 0; font-size: 50px; text-align: center; padding-top: 40%; display: none; }
 <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Memory Game</title> <script src="app.js"></script> <link rel="stylesheet" href="./style.css"> </head> <body> <div class="row"> <div data-coulour="red" class="card red colour-hidden" onclick="onCardClicked(event)"></div> <div data-coulour="orange" class="card orange colour-hidden" onclick="onCardClicked(event)"></div> <div data-coulour="blue" class="card blue colour-hidden" onclick="onCardClicked(event)"></div> <div data-coulour="pink" class="card pink colour-hidden" onclick="onCardClicked(event)"></div> </div> <div class="row"> <div data-coulour="red" class="card red colour-hidden" onclick="onCardClicked(event)"></div> <div data-coulour="cyan" class="card cyan colour-hidden" onclick="onCardClicked(event)"></div> <div data-coulour="green" class="card green colour-hidden" onclick="onCardClicked(event)"></div> <div data-coulour="pink" class="card pink colour-hidden" onclick="onCardClicked(event)"></div> </div> <div class="row"> <div data-coulour="cyan" class="card cyan colour-hidden" onclick="onCardClicked(event)"></div> <div data-coulour="orange" class="card orange colour-hidden" onclick="onCardClicked(event)"></div> <div data-coulour="yellow" class="card yellow colour-hidden" onclick="onCardClicked(event)"></div> <div data-coulour="blue" class="card blue colour-hidden" onclick="onCardClicked(event)"></div> </div> <div class="row"> <div data-coulour="purple" class="card purple colour-hidden" onclick="onCardClicked(event)"></div> <div data-coulour="purple" class="card purple colour-hidden" onclick="onCardClicked(event)"></div> <div data-coulour="yellow" class="card yellow colour-hidden" onclick="onCardClicked(event)"></div> <div data-coulour="green" class="card green colour-hidden" onclick="onCardClicked(event)"></div> </div> <div class="gagne" id="win">TU AS GAGNE.!</div> <script src="app.js"></script> </body>

Here's an example that further explains my comment. A slicker implementation would only specify each colour once, then use code to create and fill an array of suitable size.

 "use strict"; window.addEventListener('load', onLoaded, false); let colours = [ 'red', 'red', 'green', 'green', 'blue', 'blue', 'yellow', 'yellow', 'purple', 'purple', 'teal', 'teal', 'orange', 'orange', 'olive', 'olive' ]; function onBtnClick(evt) { shuffleAndUpdate(); } function shuffleAndUpdate() { shuffleColourArray(); let tdCollection = document.querySelectorAll('td'); tdCollection.forEach((el, idx, col) => { el.style.backgroundColor = colours[idx]; // sets TDs data-index=idx // wont change. Each elem always indexes // the same element in the array. We shuffle // the array. // // use the onclick handler of the square to // retrieve this index so you can check array // elems for a match when second tile is clicked. el.dataset.index = idx; }); } function onLoaded(evt) { document.querySelector('button').addEventListener('click', onBtnClick, false); shuffleAndUpdate(); } function shuffleColourArray() { for (var curElem = 0, nElems = colours.length; curElem < nElems; curElem++) { var tmp = colours[curElem]; var newIndex = Math.floor((Math.random() * nElems)); colours[curElem] = colours[newIndex]; colours[newIndex] = tmp; } }
 td { border: solid 1px black; width: 32px; height: 32px; }
 <table> <tbody> <tr> <td></td> <td></td> <td></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> <td></td> </tr> </tbody> </table> <button>Re-shuffle</button>

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