<पी> इस ट्यूटोरियल में, हम एक रियल-टाइम मल्टीप्लेयर टिक-टैक-टो गेम बनाएंगे। Node.js का उपयोग करना , सॉकेट.आईओ , और रेडिस . यह गेम दो खिलाड़ियों को अलग-अलग ब्राउज़र टैब से कनेक्ट होने, बारी-बारी से खेलने और खेलते समय वास्तविक समय के अपडेट देखने की अनुमति देता है। हम रेडिस का उपयोग करेंगे कई WebSocket सर्वरों पर गेम स्टेट सिंक्रोनाइज़ेशन को प्रबंधित करने के लिए, जिससे हमारा एप्लिकेशन स्केलेबल हो जाता है। <पी> अंत तक, आपके पास वास्तविक समय क्षमताओं के साथ एक पूरी तरह कार्यात्मक गेम होगा और स्केलेबल वास्तविक समय एप्लिकेशन बनाने के लिए वेबसॉकेट और रेडिस का उपयोग करने की ठोस समझ होगी। आप क्या सीखेंगे
- <पी> Socket.IO का उपयोग कैसे करें वास्तविक समय संचार के लिए।
- <पी> रेडिस पब/सब का उपयोग कैसे करें एकाधिक क्लाइंट में गेम स्थिति को सिंक्रनाइज़ करने के लिए।
- <पी> स्केलेबल वेबसॉकेट सर्वर आर्किटेक्चर कैसे सेट करें।
आवश्यकताएँ
<पी> शुरू करने से पहले, सुनिश्चित करें कि आपने निम्नलिखित इंस्टॉल कर लिया है: - <पी> Node.js (v16 या उच्चतर)
- <पी> रेडिस
- <पी> डॉकर (वैकल्पिक, कंटेनर में रेडिस चलाने के लिए)
- <पी> JavaScript, Node.js, और WebSockets का बुनियादी ज्ञान।
सामग्री तालिका
- <पी> परियोजना अवलोकन
- <पी> चरण 1:अपना विकास परिवेश स्थापित करना
- <पी> चरण 2:प्रोजेक्ट स्थापित करना
- <पी> चरण 3:Redis के साथ WebSocket सर्वर को कार्यान्वित करना
- <पी> चरण 4:रिएक्ट फ्रंटएंड इंटरफ़ेस लागू करें
- <पी> चरण 5:एप्लिकेशन चलाना
- <पी> चरण 6:रेडिस संदेशों को वास्तविक समय में देखना
- <पी> डेमो
- <पी> निष्कर्ष
प्रोजेक्ट अवलोकन
<पी> हम निम्नलिखित सुविधाओं के साथ एक वास्तविक समय का टिक-टैक-टो गेम बनाएंगे: - <पी> दो खिलाड़ी कनेक्ट कर सकते हैं और गेम खेल सकते हैं।
- <पी> गेम बोर्ड विभिन्न ब्राउज़र टैब पर वास्तविक समय में अपडेट होता है।
- <पी> जब बोर्ड भर जाता है तो खेल विजेता की घोषणा करता है या ड्रा की घोषणा करता है।
<पी> हम इसका उपयोग करेंगे: - <पी> Node.js सॉकेट.आईओ के साथ WebSocket कनेक्शन को संभालने के लिए।
- <पी> रेडिस ग्राहकों के बीच गेम स्थिति सिंक्रोनाइज़ेशन को प्रबंधित करने के लिए पब/सब।
चरण 1:अपना विकास परिवेश स्थापित करना
Node.js इंस्टॉल करना
<पी> सुनिश्चित करें कि आपके सिस्टम पर Node.js स्थापित है: node -v
<पी> यदि आपने इसे इंस्टॉल नहीं किया है, तो इसे Node.js. से डाउनलोड करें रेडिस स्थापित कर रहा है
<पी> आप Redis को स्थानीय रूप से इंस्टॉल कर सकते हैं या इसे डॉकर कंटेनर में चला सकते हैं। macOS (होमब्रू का उपयोग करके)
<पी> सबसे पहले, सुनिश्चित करें कि नीचे दिए गए कमांड चलाने से पहले आपने अपने सिस्टम पर Homebrew इंस्टॉल कर लिया है: brew install redis
brew services start redis
<पी> सत्यापित करें कि रेडिस कंटेनर निम्नलिखित कमांड के साथ चल रहा है: redis-cli ping
<पी> आपको देखना चाहिए: PONG
रेडिस चलाने के लिए डॉकर का उपयोग करना
docker run --name redis-server -p 6379:6379 -d redis
<पी> जांचें कि क्या Redis इसका उपयोग करके चल रहा है: docker exec -it redis-server redis-cli ping
चरण 2:प्रोजेक्ट स्थापित करना
1. प्रोजेक्ट निर्देशिका बनाएं
mkdir tic-tac-toe
cd tic-tac-toe
npm init -y
2. निर्भरताएँ स्थापित करें
npm install express socket.io redis dotenv
3. पर्यावरण चर बनाएँ
<पी> एक .env बनाएं निम्नलिखित सामग्री के साथ अपने प्रोजेक्ट रूट में फ़ाइल करें: PORT=3000
REDIS_HOST=localhost
REDIS_PORT=6379
चरण 3:रेडिस के साथ वेबसॉकेट सर्वर को कार्यान्वित करना
<पी> इस चरण में, हम एक WebSocket सर्वर स्थापित करेंगे जो Node.js का उपयोग करके वास्तविक समय के गेम इंटरैक्शन को संभालता है। , सॉकेट.आईओ , और रेडिस . यह सर्वर गेम की स्थिति का प्रबंधन करेगा, खिलाड़ियों की चाल को संभालेगा, और रेडिस पब/सब का उपयोग करके कई क्लाइंट्स के बीच सिंक्रनाइज़ेशन सुनिश्चित करेगा। <पी> हम कोड के प्रत्येक अनुभाग को तोड़ देंगे ताकि आप समझ सकें कि सब कुछ एक साथ कैसे फिट बैठता है।सर्वर कोड स्पष्टीकरण पी> <पी> server.js नाम की एक फ़ाइल बनाएं और निम्नलिखित कोड जोड़ें: import dotenv from 'dotenv';
import express from 'express';
import http from 'http';
import { Server } from 'socket.io';
import { createClient } from 'redis';
dotenv.config(); // Load environment variables from .env file
const app = express();
const server = http.createServer(app);
const io = new Server(server, {
cors: {
origin: "http://localhost:5173",
methods: ["GET", "POST"],
}
});
- <पी> dotenv :
.env से पर्यावरण चर लोड करता है पोर्ट और चाबियों जैसी संवेदनशील जानकारी को सुरक्षित रखने के लिए फ़ाइल।
- <पी> व्यक्त करना :HTTP अनुरोधों को संभालने के लिए एक बुनियादी एक्सप्रेस सर्वर सेट करता है।
- <पी> http :हम नोड के अंतर्निहित
http का उपयोग करके एक HTTP सर्वर बनाते हैं मॉड्यूल, जिसका उपयोग हम Socket.IO के साथ करेंगे वेबसॉकेट संचार के लिए।
- <पी> सॉकेट.आईओ :यह लाइब्रेरी सर्वर और क्लाइंट के बीच वास्तविक समय, द्विदिशात्मक संचार को सक्षम बनाती है।
- <पी> CORS कॉन्फ़िगरेशन :
localhost:5173 पर चलने वाले हमारे फ्रंटएंड से क्रॉस-ओरिजिन अनुरोधों की अनुमति देता है .
<पी> फिर, रेडिस प्रकाशक और ग्राहक ग्राहक बनाने के लिए, हम निम्नलिखित कोड को server.js में जोड़ेंगे। : // Initialize Redis clients
const pubClient = createClient();
const subClient = createClient();
await pubClient.connect();
await subClient.connect();
<पी> हम रेडिस का उपयोग करते हैं कनेक्टेड क्लाइंट के बीच वास्तविक समय डेटा सिंक्रनाइज़ेशन को संभालने के लिए। - <पी> पबक्लाइंट :संदेश प्रकाशित करने के लिए उपयोग किया जाता है (जैसे गेम स्थिति अपडेट)।
- <पी> उपग्राहक :संदेशों की सदस्यता लेता है (अपडेट के लिए सुनता है)।
- कनेक्ट() :रेडिस सर्वर से कनेक्शन स्थापित करता है।
<पी> इस प्रतिमान में, एक क्लाइंट का उपयोग अपडेट प्रकाशित करने के लिए किया जाता है, और दूसरा अपडेट की सदस्यता लेता है। इससे अवरुद्ध व्यवहार से बचने में मदद मिलती है, क्योंकि Redis के ग्राहक सदस्यता लेते हैं मोड केवल संदेश प्राप्त कर सकता है। <पी> गेम अपडेट के लिए रेडिस चैनलों की सदस्यता लेने के लिए, हम निम्नलिखित कोड को server.js में जोड़ेंगे : // Subscribe to the Redis channel for game updates
await subClient.subscribe('game-moves', (message) => {
gameState = JSON.parse(message);
io.emit('gameState', gameState);
});
- <पी> subClient.subscribe :
game-moves पर संदेशों को सुनता है चैनल.
- <पी> जब भी किसी खिलाड़ी द्वारा कोई नया कदम उठाया जाता है, तो गेम की स्थिति रेडिस में अपडेट हो जाती है, और सभी जुड़े हुए ग्राहकों को नई स्थिति के बारे में सूचित किया जाता है।
- <पी>
message पैरामीटर में गेम स्थिति को एक स्ट्रिंग के रूप में शामिल किया गया है। हम इसे एक जावास्क्रिप्ट ऑब्जेक्ट में पार्स करते हैं और Socket.IO का उपयोग करके अद्यतन स्थिति को प्रसारित करते हैं .
<पी> इसके बाद, गेम की स्थिति और फ़ंक्शन को परिभाषित करने के लिए, हम server.js में निम्नलिखित कोड जोड़ेंगे : // Define initial game state
let gameState = {
board: Array(9).fill(null),
xIsNext: true,
};
// Function to reset the game
function resetGame() {
gameState = {
board: Array(9).fill(null),
xIsNext: true,
};
}
- <पी> गेमस्टेट :बोर्ड की वर्तमान स्थिति और किसकी बारी है (
xIsNext) पर नज़र रखता है ). - <पी> बोर्ड को 9 कोशिकाओं की एक सरणी के रूप में दर्शाया गया है (प्रत्येक 'X', 'O', या
null हो सकता है) ).
- <पी>
xIsNext ध्वज निर्धारित करता है कि किस खिलाड़ी की बारी है।
- <पी> रीसेटगेम() :बोर्ड और टर्न इंडिकेटर को उनकी प्रारंभिक स्थिति में रीसेट करता है, जिससे एक नया गेम शुरू हो सकता है।
<पी> इसके बाद, WebSocket कनेक्शन को संभालने के लिए, निम्नलिखित कोड को server.js में जोड़ें : io.on('connection', (socket) => {
console.log('New client connected:', socket.id);
// Send the current game state to the newly connected client
socket.emit('gameState', gameState);
- <पी>
io.on('connection') जब कोई नया क्लाइंट कनेक्ट होता है तो ईवेंट ट्रिगर हो जाता है।
- <पी> socket.id :प्रत्येक कनेक्टेड क्लाइंट के लिए एक विशिष्ट पहचानकर्ता।
- <पी> हम तुरंत वर्तमान
gameState भेजते हैं नए ग्राहक के लिए ताकि वे वर्तमान बोर्ड देख सकें।
<पी> खिलाड़ी की गतिविधियों को संभालने के लिए, हम server.js में निम्नलिखित कोड जोड़ेंगे : // Handle player moves
socket.on('makeMove', (index) => {
// Prevent making a move if cell is already taken or game is over
if (gameState.board[index] || calculateWinner(gameState.board)) return;
// Update the board and switch turns
gameState.board[index] = gameState.xIsNext ? 'X' : 'O';
gameState.xIsNext = !gameState.xIsNext;
// Publish the updated game state to Redis
pubClient.publish('game-moves', JSON.stringify(gameState));
io.emit('gameState', gameState);
});
- <पी> स्थानांतरित करें :यह ईवेंट तब ट्रिगर होता है जब कोई खिलाड़ी किसी सेल पर क्लिक करता है।
- <पी> सत्यापन :हम जाँचते हैं कि क्या सेल पहले से ही भरा हुआ है या क्या खेल आगे बढ़ने से पहले ही समाप्त हो गया है।
- <पी> गेम स्थिति अपडेट कर रहा है :यदि चाल वैध है, तो हम बोर्ड और स्विच टर्न को अपडेट करते हैं।
- <पी> अद्यतन गेम स्थिति तब है:
- <पी> रेडिस पर प्रकाशित :यह सुनिश्चित करता है कि सर्वर के सभी इंस्टेंस सिंक में रहें।
- <पी> सभी ग्राहकों के लिए प्रसारित :यह सभी खिलाड़ियों के लिए गेम बोर्ड को तुरंत अपडेट कर देता है।
<पी> गेम पुनरारंभ को संभालने के लिए, हम निम्नलिखित कोड को server.js में जोड़ेंगे : // Handle game restarts
socket.on('restartGame', () => {
resetGame();
io.emit('gameState', gameState);
});
<पी> क्लाइंट डिस्कनेक्शन प्रबंधन को संभालने के लिए, हम निम्नलिखित कोड को server.js में जोड़ देंगे : socket.on('disconnect', () => {
console.log('Client disconnected:', socket.id);
});
});
<पी> अंत में, गेम के तर्क को संसाधित करने के लिए, हम निम्नलिखित फ़ंक्शन को server.js में जोड़ देंगे : // Function to check if there's a winner
function calculateWinner(board) {
const lines = [
[0, 1, 2], [3, 4, 5], [6, 7, 8],
[0, 3, 6], [1, 4, 7], [2, 5, 8],
[0, 4, 8], [2, 4, 6]
];
for (let [a, b, c] of lines) {
if (board[a] && board[a] === board[b] && board[a] === board[c]) {
return board[a];
}
}
return null;
}
function isBoardFull(board) {
return board.every((cell) => cell !== null);
}
- <पी> विजेता की गणना करें() :जाँचता है कि बोर्ड पर कोई विजेता संयोजन है या नहीं।
- <पी> isBoardFull() :जाँचता है कि क्या सभी सेल भरे हुए हैं, जो एक ड्रा का संकेत देता है।
चरण 4:रिएक्ट फ्रंटएंड इंटरफ़ेस लागू करें
<पी> इस चरण में, हम अपने टिक-टैक-टो गेम के लिए एक सरल और इंटरैक्टिव रिएक्ट फ्रंटएंड बनाते हैं। यह फ्रंटएंड खिलाड़ियों को वेबसॉकेट सर्वर से जुड़ने, चाल चलने और वास्तविक समय में गेम बोर्ड अपडेट देखने की अनुमति देता है। <पी> App.jsx में , निम्नलिखित कोड जोड़ें: import React, { useEffect, useState } from 'react';
import io from 'socket.io-client';
const socket = io('http://localhost:3000');
function App() {
const [gameState, setGameState] = useState({
board: Array(9).fill(null),
xIsNext: true,
winner: null
});
useEffect(() => {
socket.on('gameState', (state) => {
setGameState(state);
});
return () => socket.off('gameState');
}, []);
const handleClick = (index) => {
if (gameState.board[index] || gameState.winner) return;
socket.emit('makeMove', index);
};
const renderCell = (index) => (
<button onClick={() => handleClick(index)}>{gameState.board[index]}</button>
);
return (
<div>
<h1>Multiplayer Tic-Tac-Toe</h1>
<div className="board">
{[...Array(9)].map((_, i) => renderCell(i))}
</div>
<button onClick={() => socket.emit('restartGame')}>Restart Game</button>
</div>
);
}
export default App;
<पी> यहां इसका सारांश दिया गया है कि रिएक्ट ऐप कैसे टूटा है: - <पी> वेबसॉकेट कनेक्शन :
- फ्रंटएंड
socket.io-client का उपयोग करके सर्वर से कनेक्शन स्थापित करता है .
- <पी> राज्य प्रबंधन :
- <पी> खेल की स्थिति (
gameState ) को रिएक्ट के useState से प्रबंधित किया जाता है और इसमें शामिल हैं: - <पी> बोर्ड (9 सेल).
- <पी> ध्वज xIsNext वर्तमान खिलाड़ी की बारी बताने के लिए।
- <पी> विविजेता स्थिति.
- <पी> वास्तविक समय अपडेट :
- <पी>
useEffect हुक: - <पी>
gameState के लिए सुनता है सर्वर से अपडेट.
- <पी> परिवर्तन का पता चलने पर स्थानीय गेम स्थिति को अपडेट करता है।
- <पी> घटक अनमाउंट होने पर वेबसॉकेट श्रोता को साफ़ करता है।
- <पी> खिलाड़ी की गतिविधियों को संभालना :
- <पी>
handleClick फ़ंक्शन: - <पी> किसी चाल की अनुमति देने से पहले जाँचता है कि क्या कोई सेल पहले से ही भरा हुआ है या गेम में कोई विजेता है या नहीं।
- <पी> एक
makeMove भेजता है क्लिक किए गए सेल इंडेक्स के साथ सर्वर पर ईवेंट।
- <पी> गेम बोर्ड रेंडरिंग :
- <पी>
renderCell फ़ंक्शन बोर्ड पर प्रत्येक सेल के लिए एक बटन बनाता है।
- <पी> बोर्ड को 3x3 ग्रिड का उपयोग करके प्रदर्शित किया जाता है।
- <पी> गेम पुनः प्रारंभ करें :
- "रीस्टार्ट गेम" बटन एक
restartGame उत्सर्जित करता है सभी खिलाड़ियों के लिए गेम बोर्ड को रीसेट करने का इवेंट।
- <पी> उपयोगकर्ता इंटरफ़ेस :
- एक सरल और इंटरैक्टिव लेआउट जो खिलाड़ियों को बारी-बारी से वास्तविक समय में अपडेट देखने की अनुमति देता है।
चरण 5:एप्लिकेशन चलाना
बैकएंड प्रारंभ करना
<पी> बैकएंड सर्वर शुरू करने के लिए, एक नई टर्मिनल विंडो खोलें और निम्नलिखित कमांड चलाएँ: cd tic-tac-toe
npm start
फ्रंटएंड शुरू करना
<पी> रिएक्ट फ्रंटएंड सर्वर शुरू करने के लिए, एक नया टर्मिनल विंडो खोलें और नीचे दिए गए कमांड चलाएं (उसी का उपयोग न करें जिस पर बैकएंड सर्वर चल रहा है, क्योंकि गेम चलाने के लिए आपको दोनों को एक साथ चलाने की आवश्यकता है)। cd tic-tac-toe-client
npm run dev
गेम तक पहुंच
<पी> अपना ब्राउज़र खोलें और यहां नेविगेट करें: http://localhost:5173
चरण 6:रेडिस संदेशों को वास्तविक समय में देखना
<पी> जब गेम चल रहा हो, तो आप रीयल-टाइम गेम स्थिति अपडेट देखने के लिए रेडिस संदेशों को देख सकते हैं। <पी> एक टर्मिनल खोलें और चलाएँ: redis-cli
SUBSCRIBE game-moves
<पी> यह गेम अपडेट प्रदर्शित करेगा: 1) "message"
2) "game-moves"
3) "{\"board\":[\"X\",null,\"O\",null,\"X\",null,null,null,null],\"xIsNext\":false}"
<पी> हर बार जब कोई कदम उठाया जाता है या गेम की स्थिति बदलती है, तो सर्वर अद्यतन गेम स्थिति को game-moves पर प्रकाशित करता है। चैनल. redis-cli का उपयोग करना , जैसे ही गेम खेला जा रहा हो, आप वास्तविक समय में इन अपडेट की निगरानी कर सकते हैं। डेमो
<पी> इस डेमो में, आप टिक टैक टो गेम को स्थानीय रूप से चलते हुए देखेंगे, जो खिलाड़ियों के बारी-बारी से वास्तविक समय के अपडेट प्रदर्शित करेगा। <पी> गेमप्ले में टर्न स्विचिंग, बोर्ड अपडेट और गेम स्टेट घोषणाएं (विजेता या ड्रा) जैसी सुविधाएं प्रदर्शित होती हैं। यह इस बात पर प्रकाश डालता है कि कैसे गेम एक सहज, इंटरैक्टिव अनुभव प्रदान करने के लिए वेबसॉकेट संचार का लाभ उठाता है। <पी> पी> निष्कर्ष
<पी> बधाई हो, आपने Node.js, Socket.IO और Redis का उपयोग करके एक वास्तविक समय मल्टीप्लेयर टिक-टैक-टो गेम सफलतापूर्वक बनाया है। आपने जो सीखा है वह यहां दिया गया है: - <पी> Socket.IO का उपयोग करके वास्तविक समय वेबसॉकेट संचार .
- <पी> रेडिस पब/सब का उपयोग करके गेम स्थिति प्रबंधन .
- <पी> प्रतिक्रिया के साथ एक प्रतिक्रियाशील फ्रंट-एंड का निर्माण .
अगले चरण
- <पी> प्लेयर प्रमाणीकरण जोड़ें.
- <पी> एक चैट सुविधा लागू करें.
- <पी> स्केलेबिलिटी के लिए अपने एप्लिकेशन को क्लाउड प्रदाता पर तैनात करें।
<पी> हैप्पी कोडिंग! <पी> मुफ़्त में कोड करना सीखें. फ्रीकोडकैंप के ओपन सोर्स पाठ्यक्रम ने 40,000 से अधिक लोगों को डेवलपर्स के रूप में नौकरी पाने में मदद की है। आरंभ करें