In this tutorial, we’ll be building a simple “Guess the Number” game using Next.js. The game generates a random number between 1 and 100, and your task is to guess that number by entering guesses within a specified range. The game gives you feedback on whether your guess is too high or too low, and it tracks the number of attempts.
This guide will walk you through every step, from understanding the code to deploying the game.
Table of Contents
- Setting Up Your Environment
- Understanding the Code Structure
- Breaking Down the Components
- State Management with useState
- Handling User Input
- Displaying Feedback and Tracking Attempts
- Restarting the Game
- Create the UI
- Styling the Game
- Deploying the Game for Production
- Conclusion
1. Setting Up Your Environment
First, you need to have Node.js and npm installed on your machine. If they are not installed, download and install Node.js.
To create a new Next.js project, open your terminal and run:
npx create-next-app@latest guess-the-number-game
cd guess-the-number-game
Then start the development server:
npm run dev
You can open your browser and navigate to http://localhost:3000 to verify that everything is working.
2. Understanding the Code Structure
This tutorial uses a React functional component with React hooks. The structure of the game is relatively simple and divided into different sections.
Here’s an overview of how we are managing the game:
- State Management: We’ll use useState to manage the various states of the game.
- Game Logic: The game generates a random number, tracks attempts, and provides feedback on whether the guess is correct.
- User Interaction: Users input guesses via a form, and the form’s submission triggers logic to validate and respond to the guess.
3. Breaking Down the Components
a. State Management with useState
At the core of the game, we are using useState to handle the following states:
- targetNumber: The number the user needs to guess, generated randomly.
- floorNumber and ceilingNumber: Represent the current guess range.
- guess: The user’s current guess input.
- message: Feedback message based on the user’s guess.
- attempts: The number of guesses made so far.
- gameOver: A boolean indicating whether the game is over.
const minNum = 0;
const maxNum = 100;
const [targetNumber, setTargetNumber] = useState(generateRandomNumber());
const [floorNumber, setFloorNumber] = useState(minNum);
const [ceilingNumber, setCeilingNumber] = useState(maxNum);
const [guess, setGuess] = useState("");
const [message, setMessage] = useState("");
const [attempts, setAttempts] = useState(0);
const [gameOver, setGameOver] = useState(false); // Track if the game is over
b. Generating a Random Number
The generateRandomNumber function generates a random number between 1 and 100. This is the target that the user needs to guess.
// Generate random number between 1 and 100
function generateRandomNumber() {
return Math.floor(Math.random() * 100) + 1;
}
c. Handling User Input
When the user submits a guess, the handleSubmit function is triggered. It prevents the default form behavior, validates the guess, updates the game state, and provides feedback.
// Handle when the user submits their guess
const handleSubmit = (e) => {
console.log(e);
e.preventDefault();
setAttempts(attempts + 1);
const parsedGuess = parseInt(guess, 10);
if (isNaN(parsedGuess)) {
setMessage("Please enter a valid number.");
return;
}
if (parsedGuess === targetNumber) {
setMessage(
`Congratulations! You guessed the number in ${attempts + 1} attempts.`
);
setGameOver(true); // Game Over when the guess is correct
} else if (parsedGuess < targetNumber) {
setMessage("Too low! Try again.");
if (parsedGuess > floorNumber) setFloorNumber(parsedGuess);
} else {
setMessage("Too high! Try again.");
if (parsedGuess < ceilingNumber) setCeilingNumber(parsedGuess);
}
// Clear the guess input
setGuess("");
};
4. Restarting the Game
The game has a “Restart” button, which calls the handleRestart function. This resets all the state values, including the target number, attempts, and game-over flag.
// Restart the game
const handleRestart = () => {
setTargetNumber(generateRandomNumber());
setGuess("");
setAttempts(0);
setMessage("");
setFloorNumber(minNum);
setCeilingNumber(maxNum);
setGameOver(false); // Reset the gameOver state
};
5. Create the UI
return (
<div style={styles.container}>
<h1>Guess the Number Game</h1>
<p>
Guess the number between <strong>{floorNumber}</strong> and{" "}
<strong>{ceilingNumber}</strong>.
</p>
<form onSubmit={handleSubmit} style={styles.form}>
<input
type="number"
value={guess}
onChange={(e) => setGuess(e.target.value)}
style={styles.input}
placeholder="Enter your guess"
/>
<button type="submit" style={styles.button}>
Submit Guess
</button>
</form>
{message && <p style={styles.message}>{message}</p>}
<p>Attempts: {attempts}</p>
{gameOver && (
<button onClick={handleRestart} style={styles.restartButton}>
Restart Game
</button>
)}
</div>
);
6. Styling the Game
The game is styled using a simple inline CSS object. Here’s how we apply styles to various elements:
const styles = {
container: {
display: "flex",
flexDirection: "column",
alignItems: "center",
padding: "20px",
fontFamily: "Arial, sans-serif",
},
form: {
margin: "20px 0",
},
input: {
borderColor: "#cccccc",
borderWidth: "1px",
borderStyle: "solid",
padding: "10px",
fontSize: "16px",
width: "200px",
marginRight: "10px",
},
button: {
backgroundColor: "#FF6347",
color: "#ffffff",
padding: "10px 20px",
fontSize: "16px",
cursor: "pointer",
},
message: {
fontWeight: "bold",
color: "#FF6347",
},
restartButton: {
marginTop: "20px",
padding: "10px 20px",
fontSize: "16px",
backgroundColor: "#28a745",
color: "#fff",
border: "none",
cursor: "pointer",
},
};
7. Deploying the Game for Production
Now that your game is working locally, you can deploy it. If you’re using Vercel (which is highly optimized for Next.js apps), here’s how you can deploy:
- Go to Vercel.
- Create a new project and connect your GitHub repository.
- Vercel will automatically build and deploy your app.
Alternatively, you can use Netlify, Firebase Hosting, or GitHub Pages to deploy your static site.
8. Conclusion
Congratulations! You’ve built a fully functional “Guess the Number” game using React and Next.js. Throughout this tutorial, you’ve learned:
- How to use useState for managing game state.
- How to handle user input and provide feedback.
- How to restart the game and clear inputs.
- Basic styling with inline CSS in React.
- How to deploy your game for public access.
This basic game can be expanded with more features like difficulty levels, sound effects, or animations. Keep experimenting and have fun building!
Complete code:
"use client";
import { useState } from "react";
export default function Home() {
const minNum = 0;
const maxNum = 100;
const [targetNumber, setTargetNumber] = useState(generateRandomNumber());
const [floorNumber, setFloorNumber] = useState(minNum);
const [ceilingNumber, setCeilingNumber] = useState(maxNum);
const [guess, setGuess] = useState("");
const [message, setMessage] = useState("");
const [attempts, setAttempts] = useState(0);
const [gameOver, setGameOver] = useState(false); // Track if the game is over
// Generate random number between 1 and 100
function generateRandomNumber() {
return Math.floor(Math.random() * 100) + 1;
}
// Handle when the user submits their guess
const handleSubmit = (e) => {
console.log(e);
e.preventDefault();
setAttempts(attempts + 1);
const parsedGuess = parseInt(guess, 10);
if (isNaN(parsedGuess)) {
setMessage("Please enter a valid number.");
return;
}
if (parsedGuess === targetNumber) {
setMessage(
`Congratulations! You guessed the number in ${attempts + 1} attempts.`
);
setGameOver(true); // Game Over when the guess is correct
} else if (parsedGuess < targetNumber) {
setMessage("Too low! Try again.");
if (parsedGuess > floorNumber) setFloorNumber(parsedGuess);
} else {
setMessage("Too high! Try again.");
if (parsedGuess < ceilingNumber) setCeilingNumber(parsedGuess);
}
// Clear the guess input
setGuess("");
};
// Restart the game
const handleRestart = () => {
setTargetNumber(generateRandomNumber());
setGuess("");
setAttempts(0);
setMessage("");
setFloorNumber(minNum);
setCeilingNumber(maxNum);
setGameOver(false); // Reset the gameOver state
};
return (
<div style={styles.container}>
<h1>Guess the Number Game</h1>
<p>
Guess the number between <strong>{floorNumber}</strong> and{" "}
<strong>{ceilingNumber}</strong>.
</p>
<form onSubmit={handleSubmit} style={styles.form}>
<input
type="number"
value={guess}
onChange={(e) => setGuess(e.target.value)}
style={styles.input}
placeholder="Enter your guess"
/>
<button type="submit" style={styles.button}>
Submit Guess
</button>
</form>
{message && <p style={styles.message}>{message}</p>}
<p>Attempts: {attempts}</p>
{gameOver && (
<button onClick={handleRestart} style={styles.restartButton}>
Restart Game
</button>
)}
</div>
);
}
const styles = {
container: {
display: "flex",
flexDirection: "column",
alignItems: "center",
padding: "20px",
fontFamily: "Arial, sans-serif",
},
form: {
margin: "20px 0",
},
input: {
borderColor: "#cccccc",
borderWidth: "1px",
borderStyle: "solid",
padding: "10px",
fontSize: "16px",
width: "200px",
marginRight: "10px",
},
button: {
backgroundColor: "#FF6347",
color: "#ffffff",
padding: "10px 20px",
fontSize: "16px",
cursor: "pointer",
},
message: {
fontWeight: "bold",
color: "#FF6347",
},
restartButton: {
marginTop: "20px",
padding: "10px 20px",
fontSize: "16px",
backgroundColor: "#28a745",
color: "#fff",
border: "none",
cursor: "pointer",
},
};