Free source code of Whack-a-Mole game built with HTML, CSS and JavaScript. Learn how to create, customize and run a responsive browser arcade game.
Some games are fun because they are easy to understand but surprisingly difficult to master. Whack-a-Mole is a perfect example. You watch the holes, wait for a mole to appear, and tap it before it disappears or moves somewhere else.
What Is Whack-a-Mole Code?
In this tutorial, we will build a simple Whack-a-Mole game using HTML, CSS, and JavaScript. The game includes a score counter, a countdown timer, and a nine-hole playing area. You can play it in your browser on a computer or a mobile phone.
You do not need a game engine or any external JavaScript library. Everything is included in one HTML file, so you can test the game and customize its design without a complicated setup.
Whack-a-Mole is a classic arcade game in which moles pop up from holes for a short time. The player’s job is to hit as many moles as possible before the time runs out.
The idea is simple, but the game tests your reaction speed and attention. Every successful hit increases your score, and you try to beat your previous result in the next round.
A browser version is also a useful project for beginners who want to learn how JavaScript handles clicks, timers, random numbers, and changes to a webpage.
Features of This Whack-a-Mole Game
This version includes the main features needed for a small arcade game:
- A 3 × 3 grid with nine mole holes.
- A randomly selected active mole.
- A 30-second countdown timer.
- A score counter that updates after successful hits.
- A start and restart button.
- Mouse, touch, and keyboard-friendly controls.
- A final score message when time runs out.
- Responsive styling for mobile and desktop screens.
- No external libraries or image files required.
The moles are created using CSS and emoji, so you can run the game immediately. Later, you can replace the emoji with your own mole illustrations or animated images.
Free Whack-a-Mole Game Source Code HTML JavaScript
The following code contains the complete game. Copy it into a file called index.html, save the file, and open it in a modern web browser.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Whack-a-Mole Game</title>
<style>
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 24px 14px;
min-height: 100vh;
background: #f0fdf4;
color: #173b2a;
font-family: Arial, sans-serif;
text-align: center;
}
.game {
width: 100%;
max-width: 480px;
margin: 0 auto;
}
h1 {
margin: 0 0 8px;
color: #15803d;
font-size: clamp(32px, 8vw, 46px);
}
.intro {
margin: 0 auto 20px;
max-width: 420px;
color: #4b6657;
line-height: 1.6;
}
.stats {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 12px;
margin-bottom: 18px;
}
.stat {
padding: 14px 10px;
border-radius: 10px;
background: #ffffff;
box-shadow: 0 3px 12px rgba(22, 101, 52, 0.08);
}
.stat span {
display: block;
margin-bottom: 5px;
color: #64748b;
font-size: 13px;
font-weight: bold;
text-transform: uppercase;
}
.stat strong {
color: #15803d;
font-size: 28px;
}
.board {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 12px;
padding: 14px;
border: 4px solid #166534;
border-radius: 18px;
background: #86b86b;
box-shadow: 0 8px 0 #14532d;
}
.hole {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
aspect-ratio: 1;
padding: 0;
border: 4px solid #5b3a25;
border-radius: 50%;
background: #49301f;
box-shadow: inset 0 7px 0 rgba(0, 0, 0, 0.2);
cursor: pointer;
overflow: hidden;
font-size: clamp(34px, 10vw, 52px);
-webkit-tap-highlight-color: transparent;
touch-action: manipulation;
}
.hole:focus-visible {
outline: 3px solid #facc15;
outline-offset: 3px;
}
.hole.active {
background: #70472c;
border-color: #3f291c;
}
.hole:disabled {
cursor: default;
}
.mole {
display: inline-block;
animation: pop 0.13s ease-out;
user-select: none;
pointer-events: none;
}
@keyframes pop {
from {
transform: translateY(14px) scale(0.75);
}
to {
transform: translateY(0) scale(1);
}
}
.controls {
margin-top: 24px;
}
.start-button {
width: 100%;
padding: 14px 20px;
border: none;
border-radius: 9px;
background: #15803d;
color: white;
font-size: 17px;
font-weight: bold;
cursor: pointer;
transition: background 0.2s;
}
.start-button:hover {
background: #166534;
}
.start-button:focus-visible {
outline: 3px solid #facc15;
outline-offset: 3px;
}
.message {
min-height: 28px;
margin: 16px 0 0;
color: #166534;
font-size: 15px;
font-weight: bold;
line-height: 1.5;
}
.instructions {
margin-top: 24px;
padding: 16px;
border-radius: 10px;
background: #dcfce7;
color: #365844;
text-align: left;
line-height: 1.7;
font-size: 14px;
}
.instructions h2 {
margin: 0 0 8px;
color: #166534;
font-size: 19px;
}
.instructions p {
margin: 0;
}
@media (max-width: 360px) {
.board {
gap: 7px;
padding: 9px;
}
.hole {
border-width: 3px;
}
}
</style>
</head>
<body>
<main class="game">
<h1>Whack-a-Mole!</h1>
<p class="intro">
Ready to test your reaction speed?
Hit as many moles as you can before the timer reaches zero.
</p>
<div class="stats">
<div class="stat">
<span>Score</span>
<strong id="score">0</strong>
</div>
<div class="stat">
<span>Time Left</span>
<strong><span id="timer" style="display:inline;font-size:inherit;color:inherit">30</span>s</strong>
</div>
</div>
<div
class="board"
id="board"
aria-label="Whack-a-Mole game board"
></div>
<div class="controls">
<button class="start-button" id="startButton">
Start Game
</button>
<p class="message" id="message" aria-live="polite">
Press Start Game when you're ready!
</p>
</div>
<section class="instructions">
<h2>How to Play</h2>
<p>
Press Start Game to begin. A mole will appear in one of the
nine holes. Tap or click the mole to earn a point. Keep your
eyes on the board and try to get the highest score before the
30-second timer ends.
</p>
</section>
</main>
<script>
const board = document.getElementById("board");
const scoreDisplay = document.getElementById("score");
const timerDisplay = document.getElementById("timer");
const message = document.getElementById("message");
const startButton = document.getElementById("startButton");
const GAME_LENGTH = 30;
const MOLE_CHANGE_DELAY = 750;
let holes = [];
let score = 0;
let timeLeft = GAME_LENGTH;
let activeHole = -1;
let playing = false;
let timerInterval = null;
let moleTimeout = null;
function createBoard() {
board.innerHTML = "";
holes = [];
for (let i = 0; i < 9; i++) {
const hole = document.createElement("button");
hole.type = "button";
hole.className = "hole";
hole.disabled = true;
hole.setAttribute("aria-label", `Hole ${i + 1}`);
hole.addEventListener("click", function() {
hitMole(i);
});
holes.push(hole);
board.appendChild(hole);
}
drawHoles();
}
function drawHoles() {
holes.forEach((hole, index) => {
hole.innerHTML = "";
hole.classList.remove("active");
if (playing) {
hole.disabled = false;
} else {
hole.disabled = true;
}
if (playing && index === activeHole) {
hole.classList.add("active");
hole.innerHTML = '<span class="mole" aria-hidden="true">🐹</span>';
hole.setAttribute(
"aria-label",
`Mole in hole ${index + 1}`
);
} else {
hole.setAttribute("aria-label", `Hole ${index + 1}`);
}
});
}
function showRandomMole() {
if (!playing) return;
let nextHole = Math.floor(Math.random() * holes.length);
if (holes.length > 1 && nextHole === activeHole) {
nextHole = (nextHole + 1) % holes.length;
}
activeHole = nextHole;
drawHoles();
moleTimeout = setTimeout(() => {
if (!playing) return;
activeHole = -1;
drawHoles();
moleTimeout = setTimeout(
showRandomMole,
120
);
}, MOLE_CHANGE_DELAY);
}
function hitMole(index) {
if (!playing || index !== activeHole) {
return;
}
score++;
scoreDisplay.textContent = score;
clearTimeout(moleTimeout);
activeHole = -1;
drawHoles();
moleTimeout = setTimeout(showRandomMole, 100);
}
function startGame() {
clearInterval(timerInterval);
clearTimeout(moleTimeout);
score = 0;
timeLeft = GAME_LENGTH;
activeHole = -1;
playing = true;
scoreDisplay.textContent = score;
timerDisplay.textContent = timeLeft;
message.textContent = "Go! Catch those moles!";
startButton.textContent = "Restart Game";
drawHoles();
showRandomMole();
timerInterval = setInterval(() => {
timeLeft--;
timerDisplay.textContent = timeLeft;
if (timeLeft <= 0) {
endGame();
}
}, 1000);
}
function endGame() {
playing = false;
clearInterval(timerInterval);
clearTimeout(moleTimeout);
activeHole = -1;
drawHoles();
message.textContent =
`Time's up! Your final score is ${score}. Play again to beat it!`;
startButton.textContent = "Play Again";
}
startButton.addEventListener("click", startGame);
createBoard();
</script>
</body>
</html>
How to Run the Game
You can test this game without installing any special software.
- Copy the complete source code above.
- Open Notepad, Visual Studio Code, or another text editor.
- Create a new file named
index.html. - Paste the code into the file and save it.
- Open the saved file in Chrome, Firefox, Edge, or another modern browser.
- Press Start Game and tap or click the mole whenever it appears.
The game runs locally in your browser, so you do not need an internet connection to play it after saving the file.
How Does the Game Work?
Although the game looks simple, several JavaScript functions work together to keep it running.
1. Creating the Playing Board
The createBoard() function creates nine buttons and places them inside the game board. Each button represents one hole where a mole can appear.
Using buttons also makes the game easier to interact with using a mouse, touchscreen, or keyboard.
2. Showing a Random Mole
The showRandomMole() function selects a random hole and displays the mole. After a short delay, the mole disappears and the game selects another position.
This gives the player a limited time to react.
3. Increasing the Score
When the player clicks or taps the active mole, the hitMole() function checks whether the selected hole is correct.
If it is, the score increases by one. Clicking an empty hole does not add points.
4. Managing the Timer
The game starts with 30 seconds on the clock. JavaScript updates the countdown once every second.
When the timer reaches zero, the game stops, the mole disappears, and the final score is displayed.
5. Restarting the Game
The Start Game button changes to Restart Game while a round is running. Pressing it begins a fresh round with the score and timer reset.
The previous timer and mole timeout are cleared before the next round begins, preventing old game events from interfering with the new round.
How to Customize the Game
One advantage of building games with HTML, CSS, and JavaScript is that you can change the appearance without rewriting the entire project.
Change the Game Duration
Find this line in the JavaScript:
const GAME_LENGTH = 30;
Change 30 to 60 if you want players to have one minute to catch as many moles as possible.
Make the Moles Move Faster
Find this line:
const MOLE_CHANGE_DELAY = 750;
The value is measured in milliseconds. A smaller value makes the mole disappear more quickly, while a larger value gives players more time to react.
This setting is a useful way to adjust the difficulty.
Change the Background Colour
Find the body rule in the CSS:
body {
background: #f0fdf4;
}
Replace the colour value with your preferred background colour. You can also adjust the board’s green colours to match your website’s design.
Change the Mole Character
The game currently uses a hamster emoji as a simple placeholder. Find this line:
hole.innerHTML =
'<span class="mole" aria-hidden="true">🐹</span>';
You can replace the emoji with a different character or use an image you have permission to use. For a custom image, make sure it fits inside the hole and looks good on small screens.
Add a Best Score Feature
You could save the highest score using the browser’s localStorage feature. This would allow returning players to compare their current score with a previous result.
Remember that browser storage can be cleared, and scores saved this way are stored on the player’s device rather than in a central database.
Can You Add This Game to WordPress?
Yes. You can publish the game on a WordPress website using a method that supports its HTML, CSS, and JavaScript.
For example, you could:
- Create a dedicated game page.
- Upload the game files to your hosting account.
- Use a custom page template or a suitable game-embedding method.
- Add a short introduction and instructions around the game.
- Test the page on both mobile and desktop devices.
If you use WordPress, avoid pasting the entire HTML document into a normal Paragraph block. Some WordPress setups also restrict JavaScript in the Custom HTML block.
For a growing collection of browser games, keeping the game code separate from your article content can make updates and maintenance easier.
Is Whack-a-Mole a Good Beginner Project?
Yes. This project introduces several useful JavaScript concepts without requiring complicated game physics.
You can practise working with random numbers, event listeners, timers, variables, conditional statements, and DOM updates. These concepts also appear in quizzes, reaction games, clicker games, and other small browser projects.
Once the basic version works, try adding a sound effect, a difficulty setting, or a best-score display. Small improvements can help you understand how interactive games are built.
Most important Points
1. Is this Whack-a-Mole game source code free?
Yes. You can copy and modify the code in this tutorial for learning and your own projects. If you add third-party graphics, sounds, or code, check their licences before distributing your version.
2. Does the game require an internet connection?
No. The game uses built-in HTML, CSS, and JavaScript and can run locally in a modern browser.
3. Can I play the game on a mobile phone?
Yes. The layout adjusts to smaller screens, and the holes use touch-friendly buttons. You can tap the active mole to increase your score.
4. Can I change the timer?
Yes. Change the GAME_LENGTH value in the JavaScript to set a different round duration.
5. Can I add real mole images?
Yes. Replace the emoji with your own images or properly licensed graphics. You may need to adjust the CSS so the images fit neatly inside the circular holes.
6. Can I publish the game on my website?
Yes. You can host it as a standalone HTML page or integrate it through a suitable website template. If you use WordPress, choose a method that permits the JavaScript required by the game.
Final Guidelines for You
A Whack-a-Mole game is a fun way to practise front-end development. The rules are easy to understand, but the project still gives you experience with timers, random positions, click events, and updating a score in real time.
Start with the source code in this tutorial and test it in your browser. Once everything works as expected, experiment with the speed, colours, characters, and scoring system to create your own version.
Explore more free HTML5 game source code and tutorials on our website to discover your next project.
Here is Free Snake Game HTML Source Code
