DEV Community

Cover image for Building Symbol matching game in React
vigneshiyergithub
vigneshiyergithub

Posted on

Building Symbol matching game in React

What is this post about ?

Hello fellow humanoids. Today we will try to implement a basic Symbol matching game in React Js. This post won't be focused much on the styling rather on the bare minimum logic required.

Check out the app here : Symbol Matching Game

Symbol matching game

Content

  • Rules
  • Start a new game
  • Reset the game
  • Building game logic

Lets go deep dive into each one and explore how it was implemented.

Rules

  • Select 2 tiles with same symbol for match
  • If tiles are not the same then they would be hidden away
  • Once all symbols are matched then game is complete

Start a new game

As soon as new game is started we need to create random sequences for the symbols which would be used in the game. For building this game we are considering 4 symbols and 8 tiles, i.e matching 2 tiles of same symbol. Symbols in consideration : @, #, $, %

Each tile needs to have certain params i.e state to implement the required functionalities

Tile state = {
  id,
  value, 
  isOpened, 
  isMatched
}
Enter fullscreen mode Exit fullscreen mode

For generating random sequences we use the below logic:

const SYMBOLS = ["@", "#", "$", "%"];
const l = [...SYMBOLS, ...SYMBOLS];
l.sort(function (a, b) {
      return 0.5 - Math.random();
});
Enter fullscreen mode Exit fullscreen mode

here l is the array used to represent the board used for the game

Reset the game

For implementing reset functionality we need to reset the state of the game. States that needs to be reset are :

  1. Generate a new board
  2. Reset the active opened tiles to empty list
  3. Reset the count to 0

Building game logic

Match when 2 tiles are same and Reset tiles when 2 tiles are different

We would calculate matching tiles as soon as the 2nd tile is opened. If the tiles opened are the same then it’s a match else we would close the opened tiles.

Event : on tile click

const onBoardItemClick = (id) => {
    setActiveOpeningItems((openedItems) => [...openedItems, id]);
    setBoard((b) =>
      b.map((_i) => {
        if (_i.id === id) {
          return {
            ..._i,
            isOpened: true,
          };
        }
        return _i;
      })
    );
  };
Enter fullscreen mode Exit fullscreen mode

Actions performed :

  1. Add the current tile in active opened items
  2. set isOpened state as true for the clicked tile

Event : Matching logic

useEffect(() => {
    if (activeOpenedItems.length === 2) { // trigger matching logic when there are 2 active opened tiles
      const fn = () => {
        const item1 = board.find(({ id }) => id === activeOpenedItems[0]);
        const item2 = board.find(({ id }) => id === activeOpenedItems[1]);
        const isMatch = item1.value === item2.value;
        if (isMatch) {
          setBoard((board) =>
            board.map((item) => {
              if (item.id === item1.id || item.id === item2.id) {
                return {
                  ...item,
                  isMatched: true,
                };
              }
              return item;
            })
          );
        } else {
          setBoard((board) =>
            board.map((item) => {
              if (item.id === item1.id || item.id === item2.id) {
                return {
                  ...item,
                  isOpened: false,
                };
              }
              return item;
            })
          );
        }
        setActiveOpeningItems([]); // Reset active opened after matching operations are completed
      };
      setTimeout(fn, 1500); // To provide a delay is selection for user experience 
    }
  }, [activeOpenedItems, board]);
Enter fullscreen mode Exit fullscreen mode

Actions performed :

  1. Tiles matched : set isMatched state to true for the active opened tiles
  2. Tiles not matched : set isOpened state to false for the active opened tiles
  3. Resetting active opened tiles to empty list
  4. Executing matching code in setTimeout to provide a delay for user experience of the game

Count the number of steps taken

To implement this feature we just increment the count on every title click

onBoardClick={() => {
                onBoardItemClick(b.id);
                setClicks((c) => c + 1); // Increment count on click
 }}
Enter fullscreen mode Exit fullscreen mode

Finish game when all tiles are matched

To check if the game is finished we need to calculate if all the tiles in the board are matched.

const finished =
    board.length > 0 &&
    board.filter((b) => b.isMatched).length === board.length;
Enter fullscreen mode Exit fullscreen mode

Conclusion

Implementing this game will allow you to learn about using state and side effects in React to implement the desired logic. This app was made as part of learning new components which are used in real life applications.
Stay safe and lend a hand to another :)

Top comments (0)