A Step-by-Step Tutorial: Building a “Guess the Number” Game with Next.js

Guess the number game tutorial

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

  1. Setting Up Your Environment
  2. Understanding the Code Structure
  3. Breaking Down the Components
    • State Management with useState
    • Handling User Input
    • Displaying Feedback and Tracking Attempts
  4. Restarting the Game
  5. Create the UI
  6. Styling the Game
  7. Deploying the Game for Production
  8. 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:

  1. State Management: We’ll use useState to manage the various states of the game.
  2. Game Logic: The game generates a random number, tracks attempts, and provides feedback on whether the guess is correct.
  3. 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:

  1. Go to Vercel.
  2. Create a new project and connect your GitHub repository.
  3. 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",
  },
};



Posted

in

by

Post’s tag:

Advertisement