⚠️ JavaScript is required for live preview. Here's the code:
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Balap Karung Matematika 2 Player</title>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
background-color: #f0f4f8;
display: flex;
flex-direction: column;
height: 100vh;
overflow: hidden;
}
header {
background-color: #2c3e50;
color: white;
text-align: center;
padding: 10px;
}
/* Container Utama 2 Player */
.game-container {
display: flex;
flex: 1;
width: 100%;
}
/* Interface Masing-Masing Player */
.player-screen {
flex: 1;
display: flex;
flex-direction: column;
padding: 20px;
border-right: 4px solid #2c3e50;
}
.player-screen:last-child {
border-right: none;
}
#p1-screen { background-color: #eef7ff; }
#p2-screen { background-color: #fff0f0; }
.player-title {
font-size: 1.5rem;
font-weight: bold;
margin-bottom: 10px;
text-align: center;
}
/* Area Lintasan Balap */
.track {
height: 120px;
background-color: #d4a373;
border: 3px dashed #8d5b4c;
border-radius: 10px;
position: relative;
margin-bottom: 20px;
overflow: hidden;
}
.finish-line {
position: absolute;
right: 20px;
top: 0;
bottom: 0;
width: 10px;
background: repeating-linear-gradient(
0deg,
#000,
#000 10px,
#fff 10px,
#fff 20px
);
}
/* Karakter Karung */
.racer {
font-size: 2.5rem;
position: absolute;
left: 10px;
bottom: 10px;
transition: left 0.3s ease-in-out;
}
.jump {
animation: hop 0.3s ease;
}
@keyframes hop {
0% { transform: translateY(0); }
50% { transform: translateY(-30px); }
100% { transform: translateY(0); }
}
/* Card Soal Matematika */
.math-card {
background: white;
border-radius: 12px;
padding: 20px;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
display: flex;
flex-direction: column;
align-items: center;
gap: 15px;
}
.question {
font-size: 2rem;
font-weight: bold;
color: #333;
}
.options {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
width: 100%;
}
.btn-opt {
padding: 15px;
font-size: 1.2rem;
font-weight: bold;
border: 2px solid #ccc;
border-radius: 8px;
background-color: #f8f9fa;
cursor: pointer;
transition: background 0.2s;
}
.btn-opt:hover {
background-color: #e2e8f0;
}
.feedback {
height: 25px;
font-weight: bold;
font-size: 1.1rem;
}
/* Modal Pemenang */
.modal {
display: none;
position: fixed;
top: 0; left: 0; right: 0; bottom: 0;
background: rgba(0,0,0,0.7);
justify-content: center;
align-items: center;
z-index: 100;
}
.modal-content {
background: white;
padding: 30px;
border-radius: 15px;
text-align: center;
}
.btn-restart {
margin-top: 15px;
padding: 10px 20px;
font-size: 1rem;
background-color: #27ae60;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
</style>
</head>
<body>
<header>
<h1>🏁 Game Balap Karung Matematika 🏁</h1>
<p>Jawab pertanyaan dengan benar untuk melompat ke garis finish!</p>
</header>
<div class="game-container">
<!-- Interface Player 1 -->
<div class="player-screen" id="p1-screen">
<div class="player-title" style="color: #2980b9;">Player 1 🏃♂️</div>
<div class="track">
<div class="finish-line"></div>
<div class="racer" id="p1-racer">🛍️</div>
</div>
<div class="math-card">
<div class="question" id="p1-question">0 + 0</div>
<div class="options" id="p1-options"></div>
<div class="feedback" id="p1-feedback"></div>
</div>
</div>
<!-- Interface Player 2 -->
<div class="player-screen" id="p2-screen">
<div class="player-title" style="color: #c0392b;">Player 2 🏃♀️</div>
<div class="track">
<div class="finish-line"></div>
<div class="racer" id="p2-racer">🛍️</div>
</div>
<div class="math-card">
<div class="question" id="p2-question">0 + 0</div>
<div class="options" id="p2-options"></div>
<div class="feedback" id="p2-feedback"></div>
</div>
</div>
</div>
<!-- Popup Pemenang -->
<div class="modal" id="winner-modal">
<div class="modal-content">
<h2 id="winner-text">Player X Menang! 🎉</h2>
<button class="btn-restart" onclick="resetGame()">Main Lagi</button>
</div>
</div>
<script>
const TARGET_STEPS = 5; // Jumlah jawaban benar untuk mencapai finish
let p1State = { score: 0, currentAnswer: 0 };
let p2State = { score: 0, currentAnswer: 0 };
let isGameOver = false;
// Fungsi membuat soal matematika acak
function generateQuestion() {
const num1 = Math.floor(Math.random() * 12) + 1;
const num2 = Math.floor(Math.random() * 12) + 1;
const isAddition = Math.random() > 0.5;
const questionText = isAddition ? `${num1} + ${num2}` : `${num1} × ${num2}`;
const correctAnswer = isAddition ? num1 + num2 : num1 * num2;
// Buat 4 pilihan jawaban (1 benar, 3 salah)
let choices = [correctAnswer];
while (choices.length < 4) {
let fakeAns = correctAnswer + (Math.floor(Math.random() * 7) - 3);
if (fakeAns >= 0 && !choices.includes(fakeAns)) {
choices.push(fakeAns);
}
}
// Acak urutan pilihan
choices.sort(() => Math.random() - 0.5);
return { questionText, correctAnswer, choices };
}
// Render soal baru ke player tertentu
function loadQuestion(player) {
if (isGameOver) return;
const qData = generateQuestion();
const isP1 = player === 1;
if (isP1) p1State.currentAnswer = qData.correctAnswer;
else p2State.currentAnswer = qData.correctAnswer;
const qElement = document.getElementById(isP1 ? 'p1-question' : 'p2-question');
const optElement = document.getElementById(isP1 ? 'p1-options' : 'p2-options');
qElement.textContent = qData.questionText;
optElement.innerHTML = '';
qData.choices.forEach(choice => {
const btn = document.createElement('button');
btn.className = 'btn-opt';
btn.textContent = choice;
btn.onclick = () => handleAnswer(player, choice);
optElement.appendChild(btn);
});
}
// Cek Jawaban Player
function handleAnswer(player, selectedChoice) {
if (isGameOver) return;
const isP1 = player === 1;
const state = isP1 ? p1State : p2State;
const feedbackEl = document.getElementById(isP1 ? 'p1-feedback' : 'p2-feedback');
const racerEl = document.getElementById(isP1 ? 'p1-racer' : 'p2-racer');
if (selectedChoice === state.currentAnswer) {
state.score++;
feedbackEl.style.color = '#27ae60';
feedbackEl.textContent = 'Correct! Lompat! 🦘';
// Efek Lompat
racerEl.classList.add('jump');
setTimeout(() => racerEl.classList.remove('jump'), 300);
// Update Posisi Karung (Persentase Pergerakan)
const trackWidth = racerEl.parentElement.offsetWidth - 60;
const newPos = (state.score / TARGET_STEPS) * trackWidth;
racerEl.style.left = `${10 + newPos}px`;
// Cek Kemenangan
if (state.score >= TARGET_STEPS) {
endGame(player);
return;
}
} else {
feedbackEl.style.color = '#e74c3c';
feedbackEl.textContent = 'Salah! Coba lagi!';
}
// Beri delay singkat sebelum ganti soal
setTimeout(() => {
feedbackEl.textContent = '';
loadQuestion(player);
}, 600);
}
// Selesai Game
function endGame(winner) {
isGameOver = true;
document.getElementById('winner-text').textContent = `🏆 Player ${winner} Menang! 🎉`;
document.getElementById('winner-modal').style.display = 'flex';
}
// Reset Game untuk Ulangi
function resetGame() {
p1State = { score: 0, currentAnswer: 0 };
p2State = { score: 0, currentAnswer: 0 };
isGameOver = false;
document.getElementById('p1-racer').style.left = '10px';
document.getElementById('p2-racer').style.left = '10px';
document.getElementById('winner-modal').style.display = 'none';
loadQuestion(1);
loadQuestion(2);
}
// Jalankan game saat pertama kali dimuat
loadQuestion(1);
loadQuestion(2);
</script>
</body>
</html>