Whack-a-Mole Game using HTML CSS and JavaScript
Last Updated :
24 Jul, 2024
Improve
Whack-A-Mole is a classic arcade-style game that combines speed and precision. The game is set in a grid of holes, and the objective is to "whack" or hit the moles that randomly pop up from these holes. In this article, we are going to create Whack-a-Mole using HTML, CSS and JavaScript.
Preview Image:
Prerequisites:
Approach:
- Start by creating the HTML structure for your Whack-A-Mole game. Use semantic tags like
<header>
,<main>
, and include elements for game information (score, timer) and the game container with mole holes. - Style your game using CSS to create an appealing layout and you have to use this mole image.
- Use JavaScript to add interactivity to your Whack-A-Mole game.
- Select DOM elements and initialize game variables.
- Implement core functions for mole appearance (
comeout
) and handling clicks (handleMoleClick
). - Create functions to start the game, initiating intervals, and updating UI elements. Implement the end game function, clearing intervals, and resetting the game state.
- Add event listeners to buttons, ensuring proper states (disabled/enabled).
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="styles.css">
<title>Whac-A-Mole</title>
</head>
<body>
<div class="game-info">
<div id="score">Score: 0</div>
<div id="timer">Time: 60s</div>
</div>
<button id="startButton">Start Game</button>
<button id="endButton" disabled>End Game</button>
<div class="game-container">
<div class="hole" id="hole1"></div>
<div class="hole" id="hole2"></div>
<div class="hole" id="hole3"></div>
<div class="hole" id="hole4"></div>
<div class="hole" id="hole5"></div>
<div class="hole" id="hole6"></div>
<div class="hole" id="hole7"></div>
<div class="hole" id="hole8"></div>
<div class="hole" id="hole9"></div>
</div>
<script src="script.js"></script>
</body>
</html>
body {
background-color: rgb(255, 228, 196);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.game-info {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin: 20px;
}
#startButton {
margin-bottom: 20px;
padding: 10px;
font-size: 16px;
cursor: pointer;
}
#endButton {
margin-bottom: 20px;
padding: 10px;
font-size: 16px;
cursor: pointer;
}
.game-container {
background-color: rgb(1, 254, 64);
display: grid;
grid-template-columns: repeat(3, 160px);
gap: 10px;
border: 2px solid rgb(216, 216, 216);
padding: 20px;
border-radius: 10px;
}
.hole {
height: 150px;
background: rgb(19, 55, 139);
border: 5px solid rgb(30, 30, 30);
cursor: pointer;
border-radius: 100px;
}
.mole {
background-size: 150px;
background-image: url(
"https://media.geeksforgeeks.org/wp-content/uploads/20231130123541/mole.png")
}
@media only screen and (max-width: 600px) {
.game-container {
width: 80%;
gap: 10px;
padding: 5%;
grid-template-columns: repeat(3, 38%);
}
.hole {
height: 50px;
width: 50px;
border-radius: 100px;
}
.mole {
background-size: 50px;
background-image: url(
"https://media.geeksforgeeks.org/wp-content/uploads/20231130123541/mole.png")
}
}
document.addEventListener(
"DOMContentLoaded", function () {
const holes =
document.querySelectorAll(".hole");
const startButton =
document.getElementById("startButton");
const endButton =
document.getElementById("endButton");
const scoreDisplay =
document.getElementById("score");
const timerDisplay =
document.getElementById("timer");
let timer;
let score = 0;
let countdown;
let moleInterval;
// Set the initial state to game over
let gameOver = true;
function comeout() {
holes.forEach(hole => {
hole.classList.remove('mole');
hole.removeEventListener(
'click', handleMoleClick);
});
let random = holes[Math.floor(Math.random() * 9)];
random.classList.add('mole');
random.addEventListener('click', handleMoleClick);
}
function handleMoleClick() {
if (!gameOver) {
score++;
scoreDisplay.textContent = `Score: ${score}`;
}
this.classList.remove('mole');
}
function startGame() {
if (!gameOver) {
// Prevent starting the game
// again if it's already in progress
return;
}
gameOver = false;
score = 0;
scoreDisplay.textContent = `Score: ${score}`;
timer = 60;
timerDisplay.textContent = `Time: ${timer}s`;
startButton.disabled = true;
endButton.disabled = false;
countdown = setInterval(() => {
timer--;
timerDisplay.textContent = `Time: ${timer}s`;
if (timer <= 0) {
clearInterval(countdown);
gameOver = true;
alert(`Game Over!\nYour final score: ${score}`);
startButton.disabled = false;
endButton.disabled = true;
}
}, 1000);
moleInterval = setInterval(() => {
if (!gameOver) comeout();
}, 1000);
console.log("Game started");
}
function endGame() {
clearInterval(countdown);
clearInterval(moleInterval);
gameOver = true;
alert(`Game Ended!\nYour final score: ${score}`);
score = 0;
timer = 60;
scoreDisplay.textContent = `Score: ${score}`;
timerDisplay.textContent = `Time: ${timer}s`;
startButton.disabled = false;
endButton.disabled = true;
}
startButton.addEventListener("click", startGame);
endButton.addEventListener("click", endGame);
});
Output: