Memory game
Memory game
✅
Serve the static frontend files.
✅
Handle WebSocket connections.
Broadcast game updates in real-time.
app.use(express.static(path.join(__dirname, 'public')));
images = shuffle(images);
function shuffle(array) {
return array.sort(() => Math.random() - 0.5);
}
if (flippedCards.length === 2) {
setTimeout(checkMatch, 1000);
}
}
}
});
ws.on('close', () => {
delete players[playerId];
});
});
function checkMatch() {
if (flippedCards[0].index !== flippedCards[1].index &&
images[flippedCards[0].index] === images[flippedCards[1].index]) {
players[flippedCards[0].playerId].score += 1;
broadcast({
type: 'match',
playerId: flippedCards[0].playerId,
score: players[flippedCards[0].playerId].score,
indexes: [flippedCards[0].index, flippedCards[1].index]
});
matchedPairs++;
if (matchedPairs === images.length / 2) {
broadcast({ type: 'gameOver' });
}
} else {
broadcast({ type: 'unflip', indexes: [flippedCards[0].index,
flippedCards[1].index] });
}
flippedCards = [];
}
function broadcast(data) {
wss.clients.forEach(client => {
if (client.readyState === WebSocket.OPEN) {
client.send(JSON.stringify(data));
}
});
}
server.listen(8080, () => {
console.log('Server running on http://localhost:8080');
});
✅
Display the memory game grid.
✅
Show the player's score.
Connect to the WebSocket server.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Real-time Memory Game</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1>Real-time Memory Game</h1>
<h2 id="playerId"></h2>
<h3>Score: <span id="score">0</span></h3>
<div id="gameBoard"></div>
<script src="script.js"></script>
</body>
</html>
🎨 Step 4: Add Styling (public/styles.css)
✅
This will:
✅
Style the game board.
Make it visually appealing.
body {
font-family: Arial, sans-serif;
text-align: center;
margin: 0;
padding: 0;
overflow: hidden;
background: linear-gradient(45deg, #ff0080, #ff8c00, #40e0d0, #0080ff);
background-size: 300% 300%;
animation: backgroundMove 6s infinite alternate;
}
@keyframes backgroundMove {
0% { background-position: 0% 50%; }
100% { background-position: 100% 50%; }
}
#gameBoard {
display: grid;
grid-template-columns: repeat(4, 120px);
grid-gap: 10px;
justify-content: center;
margin-top: 50px;
}
.card {
width: 120px;
height: 120px;
perspective: 1000px;
cursor: pointer;
}
.card-inner {
width: 100%;
height: 100%;
position: relative;
transform-style: preserve-3d;
transition: transform 0.6s;
}
.card.flipped .card-inner {
transform: rotateY(180deg);
}
.card-front,
.card-back {
width: 100%;
height: 100%;
position: absolute;
backface-visibility: hidden;
border-radius: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.card-front {
background: #ffffff;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
font-weight: bold;
color: #333;
}
.card-back {
background-size: cover;
background-position: center;
transform: rotateY(180deg);
}
✅
Handle card clicks.
✅
Send data to the server via WebSockets.
Update the UI in real-time.
// Cargar sonidos
const correctSound = new Audio('sounds/correct.mp3');
const wrongSound = new Audio('sounds/wrong.mp3');
socket.onmessage = function(event) {
let data = JSON.parse(event.data);
function createBoard(images) {
gameBoard.innerHTML = '';
images.forEach((_, index) => {
let card = document.createElement('div');
card.classList.add('card');
card.dataset.index = index;
cardInner.appendChild(cardFront);
cardInner.appendChild(cardBack);
card.appendChild(cardInner);
function sendFlip(index) {
if (!flippedCards[index]) {
socket.send(JSON.stringify({ type: 'flip', index }));
}
}
function unflipCards(indexes) {
indexes.forEach(index => {
let card = document.querySelector(`[data-index="${index}"]`);
card.classList.remove('flipped');
delete flippedCards[index];
});
}
function removeMatchedCards(indexes) {
indexes.forEach(index => {
let card = document.querySelector(`[data-index="${index}"]`);
setTimeout(() => card.remove(), 500);
});
}
🎯✅ Game Features
✅
Multiplayer in real-time (Players see each other's flips).
✅
Players compete to find pairs first.
✅
Scores update live.
Basic WebSockets integration with Node.js & Express.
🚀 CHALLENGE
🔹 ⏳
You need to compete the game by adding:
🔹 👭
A timer
🔹 🎨
Take Turns
🔹 🔢
More animations
Individual Scores