1

*{
  box-sizing: border-box;
}

.clear {
  clear: both;
}



section {
  border: 1px solid black;
  height: 200px;
  width: 50%; 
  float: left; 
}
<!DOCTYPE html>
<html lang="en">
    <head>
    <meta charset="utf-8">
    <!--<meta name="description" content="Your description goes here">
    <meta name="keywords" content="one, two, three">-->
        <meta name="viewport" content="width=device-width, initial-scale=1">
        
        <title>Card Game</title>

        <!-- external CSS link -->
        <link rel="stylesheet" href="css/normalize.css">
        <link rel="stylesheet" href="css/style.css">
    </head>
    <body>
        <h1>Match-The-Cards</h1>
        <h2 id = "results"></h2>

    
            <section id="one" class="one"></section>
            <section id="two"  class="one"></section>
            <section id="three"class="one"></section>
            <section id="four" class="one"></section>
            <section id="five" class="one"></section>
            <section id="six"  class="one"></section>
            <section id="seven"class="one"></section>
            <section id="eight"class="one"></section>
            <section id="nine" class="one"></section>
            <section id="ten"  class="one"></section>
            
        




        <script type="text/javascript" src="js/main.js"></script>
    </body>
</html>

I am writing a code where the items are randomized and then removed, once used twice. I am trying to write a for or while loop but keep getting infinite loops.

I did some research and it said to make an object of 0-4, then use object.key. I am new to JS, so any assistance would help.

const theFlipSide = {
    cardOne: "🚕",
    cardTwo: "🗽",
    cardThree: "🌃",
    cardFour: "🍕",
    cardFive: "🍎"

}
console.log(theFlipSide);
const eachSection = Object.values(theFlipSide)
console.log(eachSection);
eachSectionReturn()

function eachSectionReturn() {
    let items


    let randomNumber = Math.floor(Math.random() * eachSection.length )
    let theIndex = [0,1,2,3,4]
    let randomEachSection = []
    console.log(randomNumber, 'Random number');
    console.log(theIndex, 'The index');
    console.log(randomEachSection, 'random each section');
    
        {
    
    
        
        if (theIndex.find((e) => e == randomNumber) != undefined){
            randomEachSection.push(eachSection[randomNumber] )
            theIndex = theIndex.filter((e) => e != randomNumber) 
console.log(theIndex,'filtered');
console.log(randomNumber, 'w/n if');
        
    
    



    //return eachSection[Math.floor(Math.random() * eachSection.length)]
    // allow that item to be outputted twice and then remove it from list 
    //_ => Math.random() - 0.5);
}
        }


document.querySelectorAll('.one').forEach(section => section.addEventListener('click', theGame))
function theGame(e) {
    

    let theSquares = eachSectionReturn()
    e.target.innerText = (theSquares)

}
}

1
  • 1
    Thank you. I updated it. This is my goal, to make a 10-card memory game - users must be able to select two cards and check if they are a match. If they are a match, they stay flipped. If not, they flip back over. The game is done when all cards are matched and flipped over. Commented Apr 6 at 22:44

1 Answer 1

1

I think it makes sense to cut up your problem in to three parts:

  1. Randomizing your game's tile layout
  2. Creating an interactive grid of tiles and responding to clicks
  3. Implementing the rules/logic of the game

1. Creating the random game state

The keys of your theFlipSize object aren't really important, so you're probably better of using an array to store the symbols.

The snippet below implements two functions that deal with arrays:

  • shuffled takes any array of values and returns them in a random order (e.g. [1,2,3] -> [3,1,2])
  • repeat takes any array of values and chains them to itself (e.g. [1,2,3] -> [1,2,3,1,2,3])

const shuffled = (array) => array
  // Assign a random rank to each v alue
  .map(value => ({ rank: Math.random(), value }))
  // Sort by those ranks
  .sort((a,b) => a.rank - b.rank)
  // Extract values
  .map(a => a.value);

const repeat = (array) => array
  // Create a new array by concatenating the array's contents to itself
  .concat(array);

// Define the unique symbols of the game
const symbols = ["🚕","🗽","🌃","🍕","🍎"];

// Repeat them to create cards
const cards = repeat(symbols);

// Shuffle them to create the layout
const layout = shuffled(cards);

// Inspect the random layout:
console.log(layout);

2. An interactive grid

There are many ways to create your game grid. Here's an example that defines ten elements in HTML. It's important that the number of elements matches your number of cards in JS.

In the snippet below you can see that depending on which card gets clicked, a different index is logged to the console. We'll use this index later to look up what symbol should be on the card!

You'll also notice we've introduced a bit of state to our game: we keep track of the last clicked card in a javascript variable.

let activeCard = null;


document
  .querySelectorAll(".card")
  .forEach((card, index) => {
    card.addEventListener("click", e => {
      // Invalid selection
      if (activeCard === index) {
        return;
      }
      // Selecting a first card
      if (activeCard === null) {
        activeCard = index;
        console.log(`Selected first card ${activeCard}`);
      } 
      // Selecting a second card
      else {
        console.log(`Selected pair ${activeCard} and ${index}`);
        activeCard = null;
      }
    });
  });
.grid {
  display: grid;
  grid-template-rows: repeat(2, 1fr);
  grid-template-columns: repeat(5, 1fr);
  gap: 1rem;
}

.card {
  background: #efefef;
  border: 1px solid black;
  aspect-ratio: 1;
  cursor: pointer;
}
<div class="grid">
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
</div>

3. Game logic

Now that we have a random tile layout and a set of interactive tiles, we can tie the two together. This is where I would advice you to not take my code but make your own implementation. Some advice:

  • Use separate functions for:
    • Handling a click
    • Updating your game state
    • Visualizing your game state in the HTML document

In the snippet below I created a game state that holds some information for each card: its HTML element, whether it's turned around / correctly guessed / incorrect, etc.

const shuffled = (array) => array
  // Assign a random rank to each v alue
  .map(value => ({ rank: Math.random(), value }))
  // Sort by those ranks
  .sort((a,b) => a.rank - b.rank)
  // Extract values
  .map(a => a.value);

const repeat = (array) => array
  // Create a new array by concatenating the array's contents to itself
  .concat(array);


// Define the unique symbols of the game
const symbols = ["🚕","🗽","🌃","🍕","🍎"];

// Shuffle them to create the layout
const layout = shuffled(repeat(symbols));

// Target elements:
const cardElements = document.querySelectorAll(".card");

// Game state:
let game = Array
  .from(cardElements)
  .map((element, index) => ({
    symbol: layout[index],
    element,
    state: "hidden"
  }));

// Handle a click
const onCardClicked = (card) => {
  // No clicks allowed when showing an incorrect pair
  if (game.some(card => card.state === "incorrect")) return;
  
  // Turn a hidden card when it's clicked
  if (card.state === "hidden") {
    card.state = "turned";
  }
  
  // Handle when 2 cards are turned
  const turned = game.filter(card => card.state === "turned");
  if (turned.length === 2) {
    const [ a, b ] = turned;

    if (a.symbol === b.symbol) {
      a.state = "correct";
      b.state = "correct";
    } else {
      a.state = "incorrect";
      b.state = "incorrect";
      
      // Give the player some time to see the cards
      setTimeout(() => {
        a.state = "hidden";
        b.state = "hidden";
        render();
      }, 1500);
    }
  }
  
  // Render the game
  render();
}

// Update the UI
const render = () => {
  game.forEach(card => {
    const text = card.state === "hidden" ? "" : card.symbol;
    const color = (
      card.state === "correct"   ? "greenyellow" :
      card.state === "incorrect" ? "lightcoral"  :
      "lightgrey"
    );
    
    card.element.innerText = text;
    card.element.style.background = color;
    
  });
}

// Hook up click listeners
game.forEach(card => {
  card.element.addEventListener("click", () => onCardClicked(card));
});

// Render the initial state
render();
.grid {
  display: grid;
  grid-template-rows: repeat(2, 1fr);
  grid-template-columns: repeat(5, 1fr);
  gap: 1rem;
}

.card {
  border: 1px solid black;
  aspect-ratio: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 3rem;
}
<div class="grid">
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
</div>

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.