Aplikasi web multiplayer Rock Paper Scissors (Batu Gunting Kertas) yang dibangun menggunakan teknologi modern. Permainan ini memungkinkan 2 pemain untuk bermain secara real-time melalui internet dengan sistem room matching otomatis.
- Framework: Node.js + Express.js
- Real-time Communication: Socket.io
- Port: 3001
- Framework: React.js + Vite
- Styling: CSS3 dengan animasi
- Port: 5173
GP Coba/
โโโ server.js # Server backend utama
โโโ package.json # Dependencies server
โโโ PENJELASAN_PROJECT.md # Dokumentasi project
โโโ GAME_FIX_SUMMARY.md # Summary perbaikan bug
โโโ gp-coba/ # Folder frontend React
โโโ src/
โ โโโ App.jsx # Komponen React utama
โ โโโ App.css # Styling utama
โ โโโ main.jsx # Entry point React
โ โโโ index.css # Base CSS
โ โโโ components/ # Komponen terpisah (kosong)
โ โโโ contexts/ # Context API (kosong)
โ โโโ hooks/ # Custom hooks (kosong)
โโโ public/ # Assets statis (kosong)
โโโ package.json # Dependencies frontend
โโโ index.html # HTML template
โโโ vite.config.js # Konfigurasi Vite
const express = require('express')
const http = require('http')
const socketIo = require('socket.io')
const cors = require('cors')- Menggunakan Express untuk HTTP server
- Socket.io untuk komunikasi real-time
- CORS untuk mengizinkan koneksi dari frontend
let waitingPlayer = null // Menyimpan pemain yang sedang menunggu
let games = new Map() // Menyimpan semua game room aktifgenerateRoomId()
function generateRoomId() {
return Math.random().toString(36).substring(2, 8)
}- Membuat ID room unik 6 karakter acak untuk setiap game
determineWinner(choice1, choice2)
function determineWinner(choice1, choice2) {
if (choice1 === choice2) return 'tie'
const winConditions = {
rock: 'scissors', // Batu mengalahkan gunting
paper: 'rock', // Kertas mengalahkan batu
scissors: 'paper' // Gunting mengalahkan kertas
}
return winConditions[choice1] === choice2 ? 'win' : 'lose'
}- Menentukan pemenang berdasarkan aturan klasik Rock Paper Scissors
Connection Event
- Menangani koneksi baru dari client
- Menampilkan log user yang terhubung
Join Game Event
- Jika ada
waitingPlayer: Membuat room baru dan memulai game - Jika tidak ada: Menunggu di queue sebagai
waitingPlayer
Player Choice Event
- Menerima pilihan dari pemain (rock/paper/scissors)
- Menunggu hingga kedua pemain membuat pilihan
- Menghitung hasil ronde dan update skor
- Mengirim hasil ke kedua pemain
- Mengecek apakah game sudah selesai (7 ronde)
const [socket, setSocket] = useState(null) // Koneksi socket
const [username, setUsername] = useState('') // Nama pemain
const [gameState, setGameState] = useState('login') // login|waiting|playing|finished
const [roomId, setRoomId] = useState('') // ID room game
const [currentRound, setCurrentRound] = useState(1) // Ronde saat ini (1-7)
const [playerChoice, setPlayerChoice] = useState('') // Pilihan pemain
const [opponentChoice, setOpponentChoice] = useState('') // Pilihan lawan
const [scores, setScores] = useState({ player: 0, opponent: 0 }) // Skor
const [gameHistory, setGameHistory] = useState([]) // Riwayat permainan
const [aiRecommendation, setAiRecommendation] = useState('') // Rekomendasi AIuseEffect(() => {
const newSocket = io('https://hck.duniahabbib.site')
newSocket.on('gameJoined', (data) => {
// Bergabung ke room / menunggu lawan
})
newSocket.on('gameStart', (data) => {
// Game dimulai, dapat info lawan
})
newSocket.on('roundResult', (data) => {
// Menerima hasil ronde dari server
})
newSocket.on('gameOver', (data) => {
// Game selesai, tampilkan hasil akhir
})
}, [])const generateAIRecommendation = () => {
if (gameHistory.length < 2) return ''
// Analisis 2 langkah terakhir lawan
const recentMoves = gameHistory.slice(-2).map(h => h.opponentChoice)
const moveCount = { rock: 0, paper: 0, scissors: 0 }
recentMoves.forEach(move => {
moveCount[move]++
})
// Cari pilihan paling sering dan counter-nya
const mostFrequent = Object.keys(moveCount).reduce((a, b) =>
moveCount[a] > moveCount[b] ? a : b
)
const counter = {
rock: 'paper', // Jika lawan sering pilih batu, rekomendasikan kertas
paper: 'scissors', // Jika lawan sering pilih kertas, rekomendasikan gunting
scissors: 'rock' // Jika lawan sering pilih gunting, rekomendasikan batu
}
return counter[mostFrequent]
}Login Screen
- Input username
- Button "Join Game"
Waiting Screen
- Menampilkan "Waiting for opponent..."
- Spinner loading
Game Screen
- Header dengan info ronde (1-7) dan skor
- AI recommendation (muncul mulai ronde 3)
- Tombol pilihan: ๐ชจ Rock, ๐ Paper, โ๏ธ Scissors
- Tampilan hasil ronde
- History permainan
Game Over Screen
- Hasil akhir (menang/kalah/seri)
- Skor final
- Ringkasan statistik
- Button "Main Lagi"
- Background: Gradient ungu-biru yang menarik
- Cards: Glass morphism effect dengan backdrop blur
- Colors: Dominan putih dengan aksen hijau untuk tombol
- Typography: Font Arial yang clean
.app - Container utama dengan centering dan gradient background
.final-round - Styling khusus untuk ronde terakhir
.final-round {
color: #ff6b6b;
font-weight: bold;
animation: pulse 1.5s infinite;
}
@keyframes pulse {
0% { opacity: 1; }
50% { opacity: 0.5; }
100% { opacity: 1; }
}.choice-btn - Tombol pilihan dengan hover effect dan transisi
.ai-recommendation - Box rekomendasi AI dengan border kuning
- User membuka
http://localhost:5173/https://hck.duniahabbib.site - Memasukkan username
- Klik "Join Game"
- Socket terhubung ke server
- Jika belum ada pemain lain โ masuk waiting queue
- Jika sudah ada pemain โ langsung match dan buat room
- Server generate room ID unik
- Kedua pemain masuk room yang sama
Per Ronde (1-7):
- Kedua pemain memilih rock/paper/scissors
- Server tunggu hingga kedua pilihan masuk
- Server hitung pemenang ronde
- Update skor dan kirim hasil ke clients
- Client tampilkan hasil dan tunggu 3 detik
- Lanjut ke ronde berikutnya
AI Recommendation:
- Mulai ronde 3, AI analisis 2 langkah terakhir lawan
- Berikan rekomendasi counter-move
- Tampilkan di UI dengan ikon robot
- Setelah ronde 7 selesai
- Server hitung skor final
- Tentukan pemenang overall
- Kirim
gameOverevent ke clients - Client tampilkan hasil akhir
- Server cleanup room setelah 5 detik
- Node.js (v14+)
- npm atau yarn
-
Clone atau Download Project
-
Install Dependencies Server
cd "GP Coba" npm install
-
Install Dependencies Client
cd gp-coba npm install -
Jalankan Server (Terminal 1)
cd "GP Coba" npm start # atau untuk development: npm run dev
Server akan berjalan di
http://localhost:3001/https://hck.duniahabbib.site -
Jalankan Client (Terminal 2)
cd "GP Coba/gp-coba" npm run dev
Client akan berjalan di
http://localhost:5173 -
Testing Multiplayer
- Buka 2 tab browser
- Masukkan username berbeda di masing-masing tab
- Mulai bermain!
{
"dependencies": {
"cors": "^2.8.5", // Cross-Origin Resource Sharing
"express": "^4.21.2", // Web framework
"socket.io": "^4.7.2" // Real-time communication
},
"devDependencies": {
"nodemon": "^3.1.10" // Auto-restart server saat development
}
}{
"dependencies": {
"react": "^19.1.0", // UI library
"react-dom": "^19.1.0", // React DOM renderer
"socket.io-client": "^4.8.1" // Socket.io client
},
"devDependencies": {
"@vitejs/plugin-react": "^4.4.1", // Vite React plugin
"eslint": "^9.25.0", // Code linting
"vite": "^6.3.5" // Build tool
}
}- Game melanjut ke ronde 8 - Fixed: Game sekarang berhenti tepat di ronde 7
- Race condition cleanup - Fixed: Hapus duplikasi cleanup code
- UI feedback - Added: Indikator "FINAL ROUND" dengan animasi
- Cleanup room otomatis setelah game selesai
- Error handling untuk disconnect
- Visual feedback yang lebih baik
- Code structure yang lebih clean
- Real-time Multiplayer - Permainan sinkron antar pemain
- Auto Matchmaking - Sistem queue otomatis
- AI Recommendation - Saran berbasis analisis pola lawan
- Game History - Rekam jejak setiap ronde
- Responsive Design - Tampilan adaptif di berbagai device
- Visual Effects - Animasi dan transisi yang smooth
- Error Handling - Penanganan disconnect dan error
- Frontend: React.js, CSS3, Socket.io Client
- Backend: Node.js, Express.js, Socket.io
- Build Tool: Vite
- Package Manager: npm
- Real-time: WebSocket (Socket.io)
- Styling: Pure CSS dengan modern effects
Dokumentasi ini dibuat untuk membantu pemahaman struktur dan cara kerja aplikasi Rock Paper Scissors Multiplayer.