Create a Memory Game with Vue 3 and JavaScript

John Au-Yeung - Jan 17 '21 - - Dev Community

Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62

Subscribe to my email list now at http://jauyeung.net/subscribe/

Vue 3 is the latest version of the easy to use Vue JavaScript framework that lets us create front end apps.

In this article, we’ll look at how to create a memory game with Vue 3 and JavaScript.

Create the Project

We can create the Vue project with Vue CLI.

To install it, we run:

npm install -g @vue/cli
Enter fullscreen mode Exit fullscreen mode

with NPM or:

yarn global add @vue/cli
Enter fullscreen mode Exit fullscreen mode

with Yarn.

Then we run:

vue create memory-game
Enter fullscreen mode Exit fullscreen mode

and select all the default options to create the project.

We also need the uuid package to let us generate unique IDs for the tiles.

To do this, we run:

npm i uuid
Enter fullscreen mode Exit fullscreen mode

Create the Memory Game

To create the memory game, we write:

<template>
  <div class="container">
    <div v-for="a of answer" :key="a.id" class="tile" @click="onClick(a.id)">
      <div v-if="a.open">
        {{ a.value }}
      </div>
      <div v-else>&nbsp;</div>
    </div>
  </div>
</template>

<script>
import { v4 as uuidv4 } from "uuid";
const answer = [1, 1, 2, 2, 3, 3, 4, 4, 5, 5]
  .map((n) => {
    return {
      id: uuidv4(),
      open: false,
      value: n,
    };
  })
  .sort(() => Math.random() - 0.5);

export default {
  name: "App",
  data() {
    return {
      answer,
      itemIds: []
    };
  },
  methods: {
    onClick(id) {
      if (!this.itemIds.length < 2 && !this.itemIds.includes(id)) {
        this.itemIds.push(id);
      }
      const index = this.answer.findIndex((a) => a.id === id);
      this.answer[index].open = true;
      if (this.itemIds.length === 2) {
        const item1Index = this.answer.findIndex(
          (a) => a.id === this.itemIds[0]
        );
        const item2Index = this.answer.findIndex(
          (a) => a.id === this.itemIds[1]
        );
        if (this.answer[item1Index].value !== this.answer[item2Index].value) {
          this.answer[item1Index].open = false;
          this.answer[item2Index].open = false;
        }
      }
      if (this.itemIds.length === 2) {
        this.itemIds = [];
      }
    },
  },
};
</script>

<style scoped>
.container {
  display: flex;
}

.tile {
  border: 1px solid black;
  width: 20vw;
  height: 50px;
}
</style>
Enter fullscreen mode Exit fullscreen mode

We have a div with the class container which is a flex container.

Inside it, we have the tiles that we can click.

If 2 tiles have the same value, then they stay displayed.

Otherwise, we make them both blank again.

If a.open is true , we display the value.

Otherwise, we show an empty div.

In the script tag, we create the answer array with the number array.

We mao them to objects with the map method.

Each object has an id and the open value.

And then we sort them randomly with the sort method with a callback that returns a random number between -0.5 and 0.5.

In the data method, we return an object with the reactive properties.

answer is made reactive so that we can render it in the template.

itemId has the IDs of the tile object we clicked on.

Next, we add the onClick method which takes an id that we put into the itemIds reactive array if we have less than 2 items and the item isn’t already in the itemIds array.

Next, we get the index of the item with the given id value and set its open property to true to flip it.

If we have 2 items as indicated by this.itemIds.length === 2 , then we compare both items to see if they have the same value.

If they don’t, then we set open for each item back to false .

And in the last if statement, we set itemIds back to an empty if we already have 2 items in itemIds .

Now when we click on 2 tiles that match, we see them stay displayed with the value.

Otherwise, we see the tile going back to an empty tile.

Conclusion

We can create a memory game easily with Vue 3 and JavaScript.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .