কম্পিউটার টিউটোরিয়াল

Node.js, Socket.IO, এবং Redis-এর সাহায্যে একটি স্কেলেবল রিয়েল-টাইম মাল্টিপ্লেয়ার টিক-ট্যাক-টো গেম তৈরি করুন

Node.js, Socket.IO, এবং Redis-এর সাহায্যে একটি স্কেলেবল রিয়েল-টাইম মাল্টিপ্লেয়ার টিক-ট্যাক-টো গেম তৈরি করুন

এই টিউটোরিয়ালে, আমরা একটি রিয়েল-টাইম মাল্টিপ্লেয়ার টিক-ট্যাক-টো গেম তৈরি করব Node.js ব্যবহার করে , সকেট.IO , এবং Redis . এই গেমটি দুটি খেলোয়াড়কে বিভিন্ন ব্রাউজার ট্যাব থেকে সংযোগ করতে, খেলার পালা নিতে এবং তাদের খেলার সাথে সাথে রিয়েল-টাইম আপডেট দেখতে দেয়। আমরা Redis ব্যবহার করব একাধিক WebSocket সার্ভার জুড়ে গেম স্টেট সিঙ্ক্রোনাইজেশন পরিচালনা করতে, আমাদের অ্যাপ্লিকেশনকে স্কেলযোগ্য করে তোলে।

শেষ পর্যন্ত, আপনার কাছে রিয়েল-টাইম ক্ষমতা সহ একটি সম্পূর্ণ কার্যকরী গেম থাকবে এবং কীভাবে স্কেলযোগ্য রিয়েল-টাইম অ্যাপ্লিকেশন তৈরি করতে WebSockets এবং Redis ব্যবহার করতে হয় সে সম্পর্কে একটি দৃঢ় বোঝাপড়া থাকবে৷

আপনি যা শিখবেন

  • কিভাবে Socket.IO ব্যবহার করবেন রিয়েল-টাইম যোগাযোগের জন্য।

  • কিভাবে Redis Pub/Sub ব্যবহার করবেন একাধিক ক্লায়েন্ট জুড়ে গেম স্টেট সিঙ্ক্রোনাইজ করতে।

  • কিভাবে একটি মাপযোগ্য ওয়েবসকেট সার্ভার আর্কিটেকচার সেট আপ করবেন।

পূর্বশর্ত

আমরা শুরু করার আগে, নিশ্চিত করুন যে আপনি নিম্নলিখিত ইনস্টল করেছেন:

  • Node.js (v16 বা উচ্চতর)

  • রেডিস

  • ডকার (ঐচ্ছিক, একটি পাত্রে রেডিস চালানোর জন্য)

  • JavaScript, Node.js, এবং WebSockets এর প্রাথমিক জ্ঞান।

সূচিপত্র

  • প্রকল্প ওভারভিউ

  • ধাপ 1:আপনার ডেভেলপমেন্ট এনভায়রনমেন্ট সেট আপ করা

  • ধাপ 2:প্রকল্প সেট আপ করা

  • ধাপ 3:রেডিস

    এর সাথে ওয়েবসকেট সার্ভার বাস্তবায়ন করা
  • ধাপ 4:প্রতিক্রিয়া ফ্রন্টএন্ড ইন্টারফেস প্রয়োগ করুন

  • ধাপ 5:অ্যাপ্লিকেশন চালানো

  • ধাপ 6:রিয়েল-টাইমে রিডিস মেসেজ দেখা

  • ডেমো

  • উপসংহার

প্রকল্প ওভারভিউ

আমরা নিম্নলিখিত বৈশিষ্ট্যগুলির সাথে একটি রিয়েল-টাইম টিক-ট্যাক-টো গেম তৈরি করব:

  • দুই খেলোয়াড় সংযোগ করতে এবং একটি গেম খেলতে পারেন৷

  • গেম বোর্ড বিভিন্ন ব্রাউজার ট্যাব জুড়ে রিয়েল-টাইমে আপডেট হয়।

  • বোর্ড পূর্ণ হলে গেমটি বিজয়ী ঘোষণা করে বা ড্র ঘোষণা করে।

আমরা ব্যবহার করব:

  • Node.js Socket.IO এর সাথে WebSocket সংযোগ পরিচালনার জন্য।

  • রিডিস ক্লায়েন্ট জুড়ে গেম স্টেট সিঙ্ক্রোনাইজেশন পরিচালনা করতে পাব/সাব।

ধাপ 1:আপনার ডেভেলপমেন্ট এনভায়রনমেন্ট সেট আপ করা

Node.js ইনস্টল করা হচ্ছে

আপনার সিস্টেমে Node.js ইনস্টল করা আছে তা নিশ্চিত করুন:

node -v

আপনি যদি এটি ইনস্টল না করে থাকেন তবে এটি Node.js থেকে ডাউনলোড করুন।

Redis ইনস্টল করা হচ্ছে

আপনি স্থানীয়ভাবে Redis ইনস্টল করতে পারেন বা এটি একটি ডকার কন্টেইনারে চালাতে পারেন।

macOS (হোমব্রু ব্যবহার করে)

প্রথমে, নিচের কমান্ডগুলি চালানোর আগে নিশ্চিত করুন যে আপনার সিস্টেমে হোমব্রু ইনস্টল করা আছে:

brew install redis
brew services start redis

যাচাই করুন যে Redis কন্টেইনারটি নিম্নলিখিত কমান্ডের সাথে চলছে:

redis-cli ping

আপনার দেখতে হবে:

PONG

Redis চালানোর জন্য ডকার ব্যবহার করা

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:Redis এর সাথে WebSocket সার্ভার বাস্তবায়ন করা

এই ধাপে, আমরা একটি WebSocket সার্ভার সেট আপ করব যা Node.js ব্যবহার করে রিয়েল-টাইম গেম ইন্টারঅ্যাকশন পরিচালনা করে , সকেট.IO , এবং Redis . এই সার্ভারটি গেমের অবস্থা পরিচালনা করবে, প্লেয়ারের মুভ পরিচালনা করবে এবং Redis Pub/Sub ব্যবহার করে একাধিক ক্লায়েন্ট জুড়ে সিঙ্ক্রোনাইজেশন নিশ্চিত করবে।

আমরা কোডের প্রতিটি বিভাগ ভেঙে দেব যাতে আপনি বুঝতে পারেন কিভাবে সবকিছু একসাথে ফিট করে।সার্ভার কোড ব্যাখ্যা

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 এর সাথে ব্যবহার করব WebSocket যোগাযোগের জন্য।

  • সকেট.IO :এই লাইব্রেরিটি সার্ভার এবং ক্লায়েন্টদের মধ্যে রিয়েল-টাইম, দ্বিমুখী যোগাযোগ সক্ষম করে৷

  • CORS কনফিগারেশন :localhost:5173 এ চলমান আমাদের ফ্রন্টএন্ড থেকে ক্রস-অরিজিন অনুরোধের অনুমতি দেয় .

তারপর, Redis প্রকাশক এবং গ্রাহক ক্লায়েন্ট তৈরি করতে, আমরা server.js-এ নিম্নলিখিত কোড যোগ করব :

// Initialize Redis clients
const pubClient = createClient();
const subClient = createClient();
await pubClient.connect();
await subClient.connect();

আমরা Redis ব্যবহার করি সংযুক্ত ক্লায়েন্টদের মধ্যে রিয়েল-টাইম ডেটা সিঙ্ক্রোনাইজেশন পরিচালনা করতে।

  • pubClient :বার্তা প্রকাশ করতে ব্যবহৃত হয় (যেমন গেম স্টেট আপডেট)।

  • সাবক্লায়েন্ট :বার্তাগুলিতে সদস্যতা নেয় (আপডেটগুলির জন্য শোনে)৷

  • সংযুক্ত() :Redis সার্ভারের সাথে একটি সংযোগ স্থাপন করে।

এই দৃষ্টান্তে, একটি ক্লায়েন্ট আপডেট প্রকাশ করতে ব্যবহৃত হয়, এবং অন্যটি আপডেটগুলিতে সাবস্ক্রাইব করে। এটি ব্লকিং আচরণ এড়াতে সাহায্য করে, যেহেতু Redis ক্লায়েন্টরা সাবস্ক্রাইব করুন মোড শুধুমাত্র বার্তা গ্রহণ করতে পারে।

গেম আপডেটের জন্য 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-এ বার্তা শোনে চ্যানেল।

  • যখনই একজন খেলোয়াড়ের দ্বারা একটি নতুন পদক্ষেপ নেওয়া হয়, গেমের অবস্থা Redis-এ আপডেট করা হয় এবং সমস্ত সংযুক্ত ক্লায়েন্টদের নতুন অবস্থা সম্পর্কে অবহিত করা হয়৷

  • message প্যারামিটারে একটি স্ট্রিং হিসাবে গেমের অবস্থা রয়েছে। আমরা এটিকে একটি JavaScript অবজেক্টে পার্স করি এবং 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);
 });
  • makeMove :যখন একজন খেলোয়াড় একটি কক্ষে ক্লিক করে তখন এই ইভেন্টটি ট্রিগার হয়৷

    • বৈধতা :আমরা চেক করি যে সেলটি ইতিমধ্যেই দখল করা আছে কিনা বা সরানোর আগে গেমটি শেষ হয়েছে কিনা৷

    • গেমের অবস্থা আপডেট করা হচ্ছে :যদি পদক্ষেপটি বৈধ হয়, আমরা বোর্ড আপডেট করি এবং মোড় পরিবর্তন করি।

  • আপডেট করা গেমের অবস্থা হল:

    1. Redis-এ প্রকাশিত :এটি নিশ্চিত করে যে সার্ভারের সমস্ত দৃষ্টান্ত সিঙ্কে থাকে৷

    2. সমস্ত ক্লায়েন্টের কাছে সম্প্রচারিত :এটি অবিলম্বে সমস্ত খেলোয়াড়দের জন্য গেম বোর্ড আপডেট করে৷

গেম রিস্টার্ট পরিচালনা করতে, আমরা 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:প্রতিক্রিয়া ফ্রন্টএন্ড ইন্টারফেস প্রয়োগ করুন

এই ধাপে, আমরা আমাদের টিক-ট্যাক-টো গেমের জন্য একটি সহজ এবং ইন্টারেক্টিভ প্রতিক্রিয়া ফ্রন্টএন্ড তৈরি করি। এই ফ্রন্টএন্ড খেলোয়াড়দের WebSocket সার্ভারের সাথে সংযোগ করতে, নড়াচড়া করতে এবং রিয়েল-টাইমে গেম বোর্ড আপডেট দেখতে দেয়।

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 ) React এর useState দিয়ে পরিচালিত হয় এবং অন্তর্ভুক্ত:

      • বোর্ড (9 কোষ)।

      • পতাকা xIsNext বর্তমান খেলোয়াড়ের পালা নির্দেশ করতে।

      • বিজয়ী অবস্থা।

  • রিয়েল-টাইম আপডেট :

    • useEffect হুক:

      • gameState এর জন্য শোনে সার্ভার থেকে আপডেট।

      • পরিবর্তন সনাক্ত করা হলে স্থানীয় গেমের অবস্থা আপডেট করে।

      • কম্পোনেন্ট আনমাউন্ট করা হলে WebSocket লিসেনারকে পরিষ্কার করে।

  • প্লেয়ার মুভ হ্যান্ডলিং :

    • 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 বার্তাগুলি দেখতে পারেন৷

একটি টার্মিনাল খুলুন এবং চালান:

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 ব্যবহার করা হচ্ছে , আপনি রিয়েল-টাইমে এই আপডেটগুলি নিরীক্ষণ করতে পারেন, যেহেতু গেমটি খেলা হচ্ছে৷

ডেমো

এই ডেমোতে, আপনি টিক ট্যাক টো গেমটি স্থানীয়ভাবে চলমান দেখতে পাবেন, খেলোয়াড়রা যখন পালা করে তখন রিয়েল-টাইম আপডেটগুলি প্রদর্শন করে৷

গেমপ্লে টার্ন স্যুইচিং, বোর্ড আপডেট এবং গেম স্টেট ঘোষণা (বিজয়ী বা ড্র) এর মতো বৈশিষ্ট্যগুলি প্রদর্শন করে। এটি হাইলাইট করে যে গেমটি কীভাবে একটি মসৃণ, ইন্টারেক্টিভ অভিজ্ঞতা প্রদান করতে WebSocket যোগাযোগের সুবিধা দেয়৷

উপসংহার

অভিনন্দন, আপনি Node.js, Socket.IO, এবং Redis ব্যবহার করে সফলভাবে একটি রিয়েল-টাইম মাল্টিপ্লেয়ার টিক-ট্যাক-টো গেম তৈরি করেছেন। আপনি যা শিখেছেন তা এখানে:

  • Socket.IO ব্যবহার করে রিয়েল-টাইম ওয়েবসকেট যোগাযোগ .

  • Redis Pub/Sub ব্যবহার করে গেম স্টেট ম্যানেজমেন্ট .

  • প্রতিক্রিয়া দিয়ে একটি প্রতিক্রিয়াশীল ফ্রন্ট-এন্ড তৈরি করা .

পরবর্তী ধাপগুলি

  • প্লেয়ার প্রমাণীকরণ যোগ করুন।

  • একটি চ্যাট বৈশিষ্ট্য প্রয়োগ করুন৷

  • পরিমাপযোগ্যতার জন্য একটি ক্লাউড প্রদানকারীর কাছে আপনার অ্যাপ্লিকেশন স্থাপন করুন৷

শুভ কোডিং!

বিনামূল্যে কোড শিখুন. freeCodeCamp-এর ওপেন সোর্স পাঠ্যক্রম 40,000-এরও বেশি লোককে ডেভেলপার হিসেবে চাকরি পেতে সাহায্য করেছে। শুরু করুন


  1. জাভাস্ক্রিপ্টে ডি-স্ট্রাকচারিং অ্যাসাইনমেন্ট।

  2. জাভাস্ক্রিপ্টে ঐচ্ছিক ক্যাচ বাইন্ডিং ব্যাখ্যা করুন।

  3. আমি কিভাবে আমার iOS অ্যাপ্লিকেশনের জন্য একটি আইকন সেট করতে পারি?

  4. HTML DOM বোল্ড অবজেক্ট