|

Proyek Robotik #12: Game Tebak Angka

Proyek ini adalah permainan tebak angka interaktif berbasis web yang berjalan secara lokal di ESP32. Pengguna terhubung ke hotspot WiFi yang dibuat oleh ESP32 dan mengakses permainan melalui browser. Setiap kali pengguna menebak angka, ESP32 akan memberikan umpan balik melalui web, serta indikator fisik seperti LED dan buzzer:

  • LED Hijau & buzzer panjang saat jawaban benar
  • LED Merah & buzzer pendek saat jawaban salah

Cara Kerja:

  1. ESP32 bertindak sebagai Access Point (hotspot WiFi) dengan SSID Game-Angka dan password 12345678.
  2. Pengguna menyambungkan HP atau laptop ke WiFi tersebut, lalu membuka browser dan mengakses alamat IP default (biasanya 192.168.4.1).
  3. Halaman permainan akan tampil:
    • Pengguna klik “Mulai Game Baru”.
    • ESP32 memilih angka acak antara 1–100.
  4. Pengguna memasukkan tebakan:
    • Jika benar:
      • Menampilkan pesan sukses.
      • Menyalakan LED hijau dan buzzer selama 3 detik.
      • Permainan selesai (harus mulai ulang).
    • Jika salah:
      • Menampilkan petunjuk “lebih besar/ kecil”.
      • Menyalakan LED merah dan buzzer selama 1 detik.
      • Permainan tetap berlangsung.
  5. Jumlah percobaan akan ditampilkan dan terus diperbarui.

Komponen yang Digunakan:

  • 1 × ESP32
  • 1 x LED Hijau
  • 1 x LED Merah
  • 2 x Resistor 220Ω (untuk masing-masing LED)
  • 1 x Buzzer (aktif)
  • Kabel jumper
  • Breadboard
  • 1 x Kabel USB (untuk upload dan power)

Skema:

KomponenKoneksi ke ESP32
LED Hijau (+)GPIO 2 (via resistor 220Ω)
LED Hijau (–)GND
LED Merah (+)GPIO 4 (via resistor 220Ω)
LED Merah (–)GND
Buzzer (+)GPIO 5
Buzzer (–)GND

Kode:

#include <WiFi.h>
#include <WebServer.h>
#include <stdlib.h> // Untuk fungsi random()

// Konfigurasi WiFi
const char* ssid = "Game-Angka";
const char* password = "12345678";

WebServer server(80);

// Pin LED dan buzzer
const int greenLed = 2; // LED hijau
const int redLed = 4;   // LED merah
const int buzzer = 5;   // Buzzer

int targetNumber = 0;  // Angka yang harus ditebak
bool gameActive = false;
int attemptCount = 0;  // Jumlah percobaan

// Halaman web
String generateWebPage() {
  return R"=====(
<!DOCTYPE html>
<html>
<head>
  <title>Game Tebak Angka</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <style>
    body {
      font-family: Arial, sans-serif;
      text-align: center;
      margin: 0;
      padding: 0;
      background-color: #f4f4f9;
    }
    h1 {
      color: #333;
      font-size: 2rem;
      margin-top: 20px;
    }
    p {
      font-size: 1.5rem;
      color: #555;
    }
    input[type="number"] {
      font-size: 1.5rem;
      padding: 10px;
      width: 100px;
      margin: 10px;
      border: 1px solid #ccc;
      border-radius: 5px;
    }
    button {
      font-size: 1.5rem;
      padding: 10px 20px;
      margin: 10px;
      background-color: #007bff;
      color: white;
      border: none;
      border-radius: 5px;
      cursor: pointer;
    }
    button:hover {
      background-color: #0056b3;
    }
    .result {
      font-size: 1.5rem;
      margin-top: 20px;
    }
  </style>
</head>
<body>
  <h1>Game Tebak Angka</h1>
  <p>Masukkan angka antara 1 - 100</p>
  <input id="guess" type="number" min="1" max="100">
  <button onclick="submitGuess()">Tebak</button>
  <p id="result" class="result"></p>
  <p id="attempts" class="result"></p>
  <button onclick="startGame()">Mulai Game Baru</button>
  <script>
    function submitGuess() {
        const inputElement = document.getElementById('guess');
        const guess = inputElement.value;
        fetch('/guess?number=' + guess)
          .then(response => response.text())
          .then(data => {
            document.getElementById('result').innerHTML = data;
            updateAttempts();
            inputElement.value = ""; // Kosongkan input
          });
    }

    function startGame() {
        fetch('/start')
          .then(response => response.text())
          .then(data => {
            document.getElementById('result').innerHTML = data;
            document.getElementById('attempts').innerHTML = "";
            document.getElementById('guess').value = ""; // Kosongkan input
          });
    }

    function updateAttempts() {
        fetch('/attempts')
          .then(response => response.text())
          .then(data => {
            document.getElementById('attempts').innerHTML = "Jumlah Percobaan: " + data;
          });
    }
  </script>
</body>
</html>
)=====";
}

// Fungsi untuk memulai game
void startGame() {
  targetNumber = random(1, 101); // Pilih angka acak antara 1 hingga 100
  gameActive = true;
  attemptCount = 0; // Reset jumlah percobaan
  digitalWrite(greenLed, LOW); // Matikan LED hijau
  digitalWrite(redLed, LOW);  // Matikan LED merah
  digitalWrite(buzzer, LOW);  // Matikan buzzer
  server.send(200, "text/plain", "Game dimulai!<br />Tebak angka antara 1 hingga 100.");
}


// Fungsi untuk memeriksa tebakan
void checkGuess() {
  if (!gameActive) {
    server.send(200, "text/plain", "Game belum dimulai.<br />Klik 'Mulai Game Baru' untuk bermain.");
    return;
  }

  if (!server.hasArg("number")) {
    server.send(400, "text/plain", "Masukkan angka untuk menebak!");
    return;
  }

  int guess = server.arg("number").toInt();

  if (guess == targetNumber) {
    gameActive = false;
    digitalWrite(greenLed, HIGH); // Nyalakan LED hijau
    digitalWrite(buzzer, HIGH);  // Nyalakan buzzer selama 3 detik
    delay(3000);
    digitalWrite(greenLed, LOW); // Matikan LED hijau
    digitalWrite(buzzer, LOW);   // Matikan buzzer
    server.send(200, "text/plain", "Benar! Angkanya adalah " + String(targetNumber) + ".<br />Klik 'Mulai Game Baru' untuk bermain lagi.");
  } else {
    attemptCount++; // Tambahkan jumlah percobaan
    digitalWrite(redLed, HIGH); // Nyalakan LED merah
    digitalWrite(buzzer, HIGH); // Nyalakan buzzer selama 1 detik
    delay(1000);
    digitalWrite(redLed, LOW);  // Matikan LED merah
    digitalWrite(buzzer, LOW);  // Matikan buzzer

    if (guess < targetNumber) {
      server.send(200, "text/plain", "Salah! Angkanya lebih besar dari " + String(guess) + ".");
    } else {
      server.send(200, "text/plain", "Salah! Angkanya lebih kecil dari " + String(guess) + ".");
    }
  }
}

// Fungsi untuk mengirim jumlah percobaan
void sendAttempts() {
  server.send(200, "text/plain", String(attemptCount));
}

void setup() {
  Serial.begin(115200);

  // Inisialisasi pin
  pinMode(greenLed, OUTPUT);
  pinMode(redLed, OUTPUT);
  pinMode(buzzer, OUTPUT);

  digitalWrite(greenLed, LOW);
  digitalWrite(redLed, LOW);
  digitalWrite(buzzer, LOW);

  // Konfigurasi WiFi
  WiFi.softAP(ssid, password);
  Serial.println("WiFi AP dimulai");

  // Rute server
  server.on("/", []() { server.send(200, "text/html", generateWebPage()); });
  server.on("/start", startGame);
  server.on("/guess", checkGuess);
  server.on("/attempts", sendAttempts);

  server.begin();
  Serial.println("Server dimulai");
}

void loop() {
  server.handleClient();
}

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *