⚠️ 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>Tarik Tambang Matematika Sederhana</title>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: sans-serif;
user-select: none;
}
body {
background: #1e293b;
display: flex;
flex-direction: column;
height: 100vh;
padding: 15px;
overflow: hidden;
}
h1 {
color: #ffffff;
text-align: center;
font-size: 1.5rem;
margin-bottom: 10px;
}
/* AREA LAPANGAN & TALI */
.field {
width: 100%;
max-width: 800px;
height: 60px;
background: #475569;
border: 3px solid #64748b;
border-radius: 10px;
position: relative;
overflow: hidden;
align-self: center;
margin-bottom: 15px;
}
.center-line {
position: absolute;
left: 50%;
top: 0;
width: 4px;
height: 100%;
background: #ef4444;
transform: translateX(-50%);
z-index: 2;
}
.rope-container {
position: absolute;
width: 100%;
height: 12px;
top: 50%;
transform: translateY(-50%);
left: 0;
transition: left 0.15s ease-out;
}
.rope {
width: 300%;
height: 100%;
background: repeating-linear-gradient(45deg, #d97706, #d97706 10px, #b45309 10px, #b45309 20px);
position: absolute;
left: -100%;
}
.flag {
width: 20px;
height: 20px;
background: #facc15;
position: absolute;
left: 50%;
top: -4px;
transform: translateX(-50%) rotate(45deg);
}
/* DUA PANEL INTERAKTIF (KIRI & KANAN) */
.game-layout {
display: flex;
width: 100%;
max-width: 800px;
flex: 1;
gap: 15px;
align-self: center;
}
.player-panel {
flex: 1;
border-radius: 12px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 20px;
}
.panel-p1 { background: #1d4ed8; } /* Biru - Player 1 */
.panel-p2 { background: #047857; } /* Hijau - Player 2 */
.label {
font-size: 1.1rem;
font-weight: bold;
color: #ffffff;
margin-bottom: 10px;
opacity: 0.9;
}
.question {
font-size: 2.8rem;
font-weight: bold;
color: #ffffff;
margin-bottom: 20px;
}
.options-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
width: 100%;
}
.btn-opt {
padding: 18px;
font-size: 1.3rem;
font-weight: bold;
background: rgba(255, 255, 255, 0.15);
color: #ffffff;
border: 2px solid rgba(255, 255, 255, 0.25);
border-radius: 10px;
cursor: pointer;
transition: background 0.1s;
}
.btn-opt:active {
background: rgba(255, 255, 255, 0.4);
}
/* POPUP PEMENANG */
.overlay {
display: none;
position: fixed;
top: 0; left: 0; width: 100%; height: 100%;
background: rgba(15, 23, 42, 0.85);
align-items: center;
justify-content: center;
z-index: 10;
}
.win-box {
background: #334155;
padding: 30px;
border-radius: 15px;
text-align: center;
color: #ffffff;
box-shadow: 0 10px 20px rgba(0,0,0,0.3);
width: 85%;
max-width: 350px;
}
.win-box h2 { font-size: 1.8rem; margin-bottom: 20px; }
.btn-reset {
padding: 12px 25px;
font-size: 1.1rem;
background: #facc15;
color: #1e293b;
border: none;
border-radius: 8px;
cursor: pointer;
font-weight: bold;
}
</style>
</head>
<body>
<h1>Tarik Tambang Matematika</h1>
<!-- LAYAR LAPANGAN -->
<div class="field">
<div class="center-line"></div>
<div class="rope-container" id="rope">
<div class="rope"></div>
<div class="flag"></div>
</div>
</div>
<!-- TATA LETAK PANEL INTERAKTIF -->
<div class="game-layout">
<!-- PANEL PLAYER 1 (KIRI) -->
<div class="player-panel panel-p1">
<div class="label">PLAYER 1</div>
<div class="question" id="q1">-</div>
<div class="options-grid" id="opts1"></div>
</div>
<!-- PANEL PLAYER 2 (KANAN) -->
<div class="player-panel panel-p2">
<div class="label">PLAYER 2</div>
<div class="question" id="q2">-</div>
<div class="options-grid" id="opts2"></div>
</div>
</div>
<!-- NOTIFIKASI PEMENANG -->
<div class="overlay" id="overlay">
<div class="win-box">
<h2 id="winMsg">Menang!</h2>
<button class="btn-reset" onclick="resetGame()">Main Lagi</button>
</div>
</div>
<script>
let ropePos = 0; // Posisi tali: 0 = Tengah, Negatif = Kiri, Positif = Kanan
const winLimit = 5; // Butuh selisih 5 poin untuk menang
const pullDistance = 40; // Pergeseran tali dalam pixel
let ansP1 = 0;
let ansP2 = 0;
// Membuat angka acak sederhana (1 sampai 12)
function rand(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
// Formula pembuat soal matematika acak
function generateData() {
const a = rand(4, 12);
const b = rand(1, 4);
const isPlus = Math.random() > 0.5;
const text = isPlus ? `${a} + ${b}` : `${a} - ${b}`;
const answer = isPlus ? (a + b) : (a - b);
// Membuat 4 pilihan jawaban acak unik
const options = new Set([answer]);
while(options.size < 4) {
const wrong = answer + rand(-3, 3);
if (wrong >= 0) options.add(wrong);
}
return {
text: text,
answer: answer,
opts: Array.from(options).sort(() => Math.random() - 0.5)
};
}
// Perbarui panel soal Player 1
function renderP1() {
const data = generateData();
ansP1 = data.answer;
document.getElementById('q1').innerText = data.text;
const grid = document.getElementById('opts1');
grid.innerHTML = '';
data.opts.forEach(num => {
const btn = document.createElement('button');
btn.className = 'btn-opt';
btn.innerText = num;
btn.onclick = () => verify(1, num);
grid.appendChild(btn);
});
}
// Perbarui panel soal Player 2
function renderP2() {
const data = generateData();
ansP2 = data.answer;
document.getElementById('q2').innerText = data.text;
const grid = document.getElementById('opts2');
grid.innerHTML = '';
data.opts.forEach(num => {
const btn = document.createElement('button');
btn.className = 'btn-opt';
btn.innerText = num;
btn.onclick = () => verify(2, num);
grid.appendChild(btn);
});
}
// Proses verifikasi jawaban tombol
function verify(player, selected) {
if (player === 1) {
if (selected === ansP1) ropePos--; // Jawaban benar P1 menarik ke kiri
renderP1();
} else {
if (selected === ansP2) ropePos++; // Jawaban benar P2 menarik ke kanan
renderP2();
}
// Gerakkan tali secara visual
document.getElementById('rope').style.left = `${ropePos * pullDistance}px`;
// Aturan penentu akhir permainan
if (ropePos <= -winLimit) {
endGame("PLAYER 1 (KIRI) MENANG!");
} else if (ropePos >= winLimit) {
endGame("PLAYER 2 (KANAN) MENANG!");
}
}
function endGame(message) {
document.getElementById('winMsg').innerText = message;
document.getElementById('overlay').style.display = 'flex';
}
function resetGame() {
ropePos = 0;
document.getElementById('rope').style.left = '0px';
document.getElementById('overlay').style.display = 'none';
renderP1();
renderP2();
}
// Jalankan sistem saat aplikasi dimuat pertama kali
resetGame();
</script>
</body>
</html>