close

DEV Community

Prajwal Dhande
Prajwal Dhande

Posted on

Hello everyone! 👋

Hello everyone! 👋

A few weeks ago, I launched NodeClash – a real-time multiplayer platform where developers can battle each other in Data Structures and Algorithms (DSA).

Getting the initial idea was easy. But making sure that both players see each other's keystrokes, test case results, and AI constraints in real-time without the server crashing? That was the real challenge.

Today, I want to share how I structured the WebSocket matchmaking logic using Node.js and Socket.io.

🏗️ The Matchmaking Problem

When a user clicks "Start Battle", the server needs to:

  1. Check if there's an existing player waiting in the queue.
  2. If yes, pair them up, generate a unique Room ID, and send both players to the same battle arena.
  3. If no, put the player in a waiting state.

💻 The Socket.io Approach

Instead of complex polling, I relied heavily on Socket.io's rooms feature. Here is a simplified version of my backend matchmaking logic:


javascript
// A simple queue to hold waiting players
let waitingPlayers = [];

io.on('connection', (socket) => {
  console.log(`User connected: ${socket.id}`);

  socket.on('join_queue', (userData) => {
    if (waitingPlayers.length > 0) {
      // Opponent found!
      const opponent = waitingPlayers.pop();
      const roomId = `battle_${opponent.id}_${socket.id}`;

      // Put both players in the same isolated room
      socket.join(roomId);
      io.sockets.sockets.get(opponent.id).join(roomId);

      // Broadcast to both players that the match is starting
      io.to(roomId).emit('match_found', { roomId, problem: generateRandomDSA() });
    } else {
      // No one waiting, join the queue
      waitingPlayers.push({ id: socket.id, user: userData });
    }
  });
});
Enter fullscreen mode Exit fullscreen mode

Top comments (0)