Memory Card Game Using HTML, CSS, and JS

Nov 10, 2020

keyword-counter-hero

Why I made a memory card game

For a while now, I’ve been thinking about broadening my horizons to include languages other than Python. I love Python–don’t get me wrong (!), but as an aspiring software engineer, I realize that it’s good to have at least a passing acquaintance with more than one language. To that end, for the past few months, I’ve been learning HTML, CSS, and JavaScript. Because these are the primary languages of front-end web development, this seemed like a reasonable place to start.

After spending a couple of months learning the basics, I decided to put my new skills to the test and create a memory game. This was an idea I got from Andy Sterkowitz, a self-taught software developer and mentor in Chicago. The project is based on the children’s card game, where the player tries to match pairs of cards that are flipped over. I selected this game to test my understanding of the HTML, CSS, and JavaScript, and concepts like the document object model (DOM), object-oriented programming (OOP), and the model-view-controller (MVC) design pattern. It also allowed me to create a visual and interactive project that I could publish online.

A very brief overview of OOP and MVC

Object-oriented programming is a framework where, instead of writing a program that is organized exclusively around stand-alone functions divorced from data, the programmer creates objects that independently run the program. The program’s objects are responsible for everything from initiating the program, to interacting with the user, to determining next steps. To be very abstract about it, the developer essentially constructs a code universe and designs the elements that live in it and the rules that govern it. What happens when users interact with the code is just a natural playing out of the rules that have been put into place.

There are several different design patterns that developers can use to implement an object-oriented programming approach, but one of the most common ones is the MVC pattern. In this paradigm, the “universe” of the program and its rules are contained in three objects: the model, the view, and the controller. The model is the engineer; it manages the state of the program and stores the rules for how the state changes. The view is the presenter; it updates the display for the user. The controller plays the dual role of manager and messenger—it initiates the state of the program and communicates user interactions to the model. This is the model I used in my memory game.

Planning the memory game

Thinking about programming in an object-oriented way was a bit of a paradigm shift for me. Previously, I’ve thought about my programs as sequentially-based actions, but now, I needed to think about actions in terms of objects and methods.

To get started, I outlined the actions of the game play. These would become the methods contained in the model, view, and controller objects. Then I determined which properties I would need to execute those methods. Finally, I mapped those different properties and methods to the model, view, and controller objects.

Designing the game board

I designed the front and back of the game cards in Canva and downloaded them as png files. I also added components that would track the current score, the number of guesses, and reload the game. Finally, I created a “win” modal that would be displayed when the player correctly matched all of the cards. To create a more cohesive look, I used the same font and color palette from the blog.

The final design task was making the game board. The most important feature of this game was user interaction; the program needed to respond as the player clicked on the different cards. To create this interactivity, I needed to manipulate the DOM using JavaScript. The issue was two-fold: I had to randomly create matching pairs of cards and store their location. Then, based on where the player clicked on the board, I needed to reveal the correct card and flip it back over, if the player’s guess was wrong. To manage these tasks, I used a CSS table layout to position the cards. I also named the table divs in the HTML file in such a way that they could be easily transformed from strings to numbers in JavaScript. This allowed me to generate random positions for the card locations and also retrieve those positions when needed.

Designing the game play

I learned from previous projects that it is well worth the effort to plan things out before jumping in, and this project was no exception. Since I had already planned out beforehand what methods needed to be executed and where those methods would be stored, I could simply focus on the task of writing out the code.

To prepare the game board for the player, I created a method within the model to create a random array of non-repeating integers between 0 and the total number of cards on the game board (in this case, 12). These would be the locations for the cards. Then I segmented that list into pairs and assigned a pair to each card type.

I designed the program so that the controller object is responsible for storing player inputs and updates and the model object is responsible for managing the game play. Once the player selects a card to match, the position of the cards the player clicks is relayed to the showCard method in the view object and the player’s guess is captured in the userGuess property in the controller. Then, if there are two selections in the userGuess property, the cards are checked to see whether they match.

If the cards match, the player’s score is updated and the model checks whether the game has been won. If the cards don’t match, the cards are flipped back over. The game play continues until the player successfully matches all of the cards.

I designed the view object to manage the different pieces of information the player needed to see: 1) the face side of the card when clicked; 2) the score; 3) the number of guesses made; and 4) the win modal when the player won the game. The view is also responsible for turning both cards over if the player failed to select a pair.

Displaying the score, guesses and win modal was straightforward. The logic of showing and hiding the cards involved accounting for several factors. I designed the program so that when the player selects a card, the selection is added to the userGuess property in the controller. The program then checks to make sure that no more than 2 cards were in this property to ensure that only two cards can be shown at a time. If the card should be displayed, it finds the card in the cards property in the model object and displays it. Then, if the player has selected 2 cards, but they don’t match, the userGuess property is used to find the correct cards to flip over.

Concluding Thoughts

This was a rather challenging project because it required me to use a lot of new concepts and languages. But it was worth it. I’ve found that there’s no better way to solidify your grasp of a topic than to actually try to do something with that knowledge. This project helped me put some of the theory that I’d studied into practice.

Plus, it was a lot of fun! It was especially thrilling to complete the project and actually play with it. (I’ll admit to playing just for fun more than a couple of times!) I’m looking forward to digging into JavaScript further to see what else I can create.

Never miss a post!
Subscribe to the blog and get updates every two weeks!