Mystery Number In C++

Introduction to the Mystery Number Game

The Mystery Number Game is a simple and fun programming project where the player has to guess the number which is randomly picked within a certain range. In this game, the program provides feedback to the player, such as whether the guess is higher than or lower than the number so that the player gets an idea of where to look for the number. This continues until the player guesses the correct number successfully.

Beginners Programming Project Applications

The Mystery Number Game is a terrific project for beginners, because it incorporates many of the building blocks of programming in a very interesting and interactive fashion. Here are some of those applications and core learnings:

1. Basic Programming Constructs in Learning

  • Variables: to store the mystery number, user guesses, and attempts.
  • Input/output: entails using std::cin for user input and std::cout to display messages.
  • Conditional Statements: Logic implementation through if-else to give feedback about the guesses.
  • 2. Mastered Loops

  • With while or do-while loop, you can keep the game running until you guessed it right.
  • 3. Introduction to Random Numbers

  • Seeding and learning the experience of how to generate random numbers with rand and srand.
  • 4. Error Handling

  • Verifying that the user input would be appropriate within the range.
  • Invalid input includes non-numeric entries.
  • 5. Encouragement for Solving Problems

  • Logical reasoning is needed to get the best guess possible.
  • Programmers will set the game up in such a way that it gives proper feedback intuitively.
  • 6. Flexibility and Creativity

  • There is flexibility and creativity attached to introducing some or all of the scoring, hints, levels of difficulty, and graphical interface.
  • 7. Be Confident

  • The game's simplicity means quick wins to build confidence in coding.
  • Interactive gameplay rewards students by instantly providing feedback.
  • Random Number Generation in C++

Randomly generating numbers becomes an important aspect of programming in games and simulation, among other algorithmic uses. There are two major ways of generating random numbers using C++ , namely, the old way, which uses the functions rand and srand, and the new way, which has been introduced in C++11 by using the <random> library.

How to use rand and srand for generating random numbers

Rand is a member of C's standard libraries, particularly the cstdlib, and it generates pseudo-random numbers.

Basic Features of rand:

  • Range: Generates numbers between 0 and RAND_MAX (a large constant defined in <cstdlib>).
  • Repeatability: Without seeding, the sequence of numbers will be the same each time the program runs.
  • How to Seed with srand:

To make the sequence unpredictable, use srand to seed the random number generator.

Example

#include <iostream>
#include <cstdlib> // for rand() and srand()
#include <ctime>   // for time()

int main() {
    // Seed the random number generator with the current time
    srand(static_cast<unsigned>(time(0)));

    // Generate random numbers
    int randomNum = rand();              // Between 0 and RAND_MAX
    int randomInRange = rand() % 100;    // Between 0 and 99
    int randomCustomRange = rand() % 50 + 1; // Between 1 and 50

    std::cout << "Random number: " << randomNum << std::endl;
    std::cout << "Random number (0-99): " << randomInRange << std::endl;
    std::cout << "Random number (1-50): " << randomCustomRange << std::endl;

    return 0;
}

Output:

Output

Random number: 308392635
Random number (0-99): 19
Random number (1-50): 31

Disadvantages of rand:

  • There is some weak randomness and non-thread-safe behavior, and there is no fine control of the distribution of numbers created by rand.
  • Introduction to <random> for better randomization (C++11 and later)

Instead, it will go for the <random> header with C++11 for a better understanding of how the random-number generation is supposed to work. It improves the control given for different mongoose and distribution over dealing with randomness.

Key components in <random>:

  • Engines: The engines create sequences of pseudo-randomly generated numbers (e.g., std::mt19937).
  • Distributions: The distributions control the series of numbers and the types of random numbers (e.g., std::uniformintdistribution).
  • Basic Example with <random>:

    Example
    
    #include <iostream>
    #include <random> // for <random>
    
    int main() {
        // Random number generator engine (Mersenne Twister)
        std::random_device rd;               // Random seed
        std::mt19937 generator(rd());        // Pseudo-random number engine
        
        // Uniform distribution in range [1, 100]
        std::uniform_int_distribution<int> dist(1, 100);
    
        // Generate random numbers
        int randomNum = dist(generator);
    
        std::cout << "Random number (1-100): " << randomNum << std::endl;
    
        return 0;
    }
    

Output:

Output

Random number (1-100): 46

Advantages of <random>:

  • Better Randomness: Randomness produced by the engines is of greater quality.
  • Different Types of Engines: For example, select one among std::mt19937 (Mersenne Twister) or std::defaultrandomengine.
  • Flexible Distributions: std::uniformintdistribution: Uniform distribution for integers. std::uniformrealdistribution: Uniform distribution for floating-point numbers. Other distributions (e.g., normal, binomial).
  • std::uniformintdistribution: Uniform distribution for integers.
  • std::uniformrealdistribution: Uniform distribution for floating-point numbers.
  • Other distributions (e.g., normal, binomial).
  • User Input Handling

The way to receive the responses from any interactive program is the same way a user enters input. For user input in C++, this will be here has std::cin. As every input has dealing with validating and sanitizing, it guarantees that all unexpected or invalid syntaxes are handled reliably by the program through old-school programming.

Using std::cin for capturing user input

Capture standard input from a keyboard using std::cin, which belongs to the <iostream> library. Basic Example:

Example

#include <iostream>
int main() {
    int age;

    std::cout << "Enter your age: ";
    std::cin >> age;

    std::cout << "You entered: " << age << std::endl;
    return 0;
}

Output:

Output

Enter your age: 45
You entered: 45

Common Problems with std::cin

  • Mismatched Types: Entering a non-numeric value when the program expects a number. When the std::cin enters a fail state, it skips the rest of the inputs.
  • Additional Input: It also happened with some characters associated with spaces or new-line characters that are left in the input buffer since it can disturb the coming shots.
  • Entering a non-numeric value when the program expects a number.
  • When the std::cin enters a fail state, it skips the rest of the inputs.
  • It also happened with some characters associated with spaces or new-line characters that are left in the input buffer since it can disturb the coming shots.
  • Validating and sanitizing user input in an interactive program

Input validation ensures that valid data is handed over to the program, while sanitization takes place by deleting or correcting invalid input. Those are:

1. Checking Input Validity

Use the std::cin.fail method to detect invalid input.

Example

#include <iostream>
#include <limits> // For std::numeric_limits

int main() {
    int number;

    std::cout << "Enter an integer: ";
    std::cin >> number;

    if (std::cin.fail()) {
        std::cout << "Invalid input. Please enter a valid integer." << std::endl;
    } else {
        std::cout << "You entered: " << number << std::endl;
    }

    return 0;
}

Output 1:

Output

Enter an integer: 10
You entered: 10

Output:

Output

Enter an integer: 1088888888888888888888
Invalid input. Please enter a valid integer.

2. Clearing the Input Buffer

Clear the error state and unwanted characters from the input buffer using std::cin.clear and std::cin.ignore.

Example

#include <iostream>
#include <limits> // For std::numeric_limits

int main() {
    int number;

    while (true) {
        std::cout << "Enter an integer: ";
        std::cin >> number;

        if (std::cin.fail()) {
            std::cin.clear(); // Clear the error flag
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // Discard invalid input
            std::cout << "Invalid input. Please try again." << std::endl;
        } else {
            break;
        }
    }

    std::cout << "You entered: " << number << std::endl;
    return 0;
}

Output:

Output

Enter an integer: 8976564376
Invalid input. Please try again.
Enter an integer: 896756
You entered: 896756

3. Ensuring Input Falls Within a Valid Range

Use loops to check the validity of the range of inputs.

Example

#include <iostream>
#include<limit>
int main() {
    int number;

    while (true) {
        std::cout << "Enter a number between 1 and 100: ";
        std::cin >> number;

        if (std::cin.fail() || number < 1 || number > 100) {
            std::cin.clear(); // Clear the error flag
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // Discard invalid input
            std::cout << "Invalid input. Please enter a number between 1 and 100." << std::endl;
        } else {
            break;
        }
    }

    std::cout << "You entered: " << number << std::endl;
    return 0;
}

Output 1:

Output

Enter a number between 1 and 100: 54
You entered: 54

Output 2:

Output

Enter a number between 1 and 100: 945
Invalid input. Please enter a number between 1 and 100.
Enter a number between 1 and 100: 67
You entered: 67

Conditional Statements

Conditional statements allow a program to make decisions based on specific conditions. For a number-guessing game, conditional logic helps evaluate user guesses and provides them with appropriate feedback.

Use of if-else statements to evaluate user guesses

In Mystery Number Game program, if-else statements are used to compare the input from the user as guesses against the mystery number and give feedback based on that.

Basic Example:

Example

#include <iostream>
int main() {
    int mysteryNumber = 42; // Predefined mystery number for simplicity
    int userGuess;

    std::cout << "Guess the mystery number (1-100): ";
    std::cin >> userGuess;

    if (userGuess > mysteryNumber) {
        std::cout << "Too high! Try again." << std::endl;
    } else if (userGuess < mysteryNumber) {
        std::cout << "Too low! Try again." << std::endl;
    } else {
        std::cout << "Congratulations! You guessed the number!" << std::endl;
    }

    return 0;
}

Output 1:

Output

Guess the mystery number (1-100): 45
Too high! Try again.

Output 2:

Output

Guess the mystery number (1-100): 9
Too low! Try again.

Edge Cases and Invalid Input

When input does not match the expected behavior in general, that is an edge case. Non-numeric characters and out-of-bounds guesses are examples of invalid input.

1. Edge Case: Input out of Range

Check that the user's guess falls within the acceptable range.

Example

#include <iostream>
int main() {
    int mysteryNumber = 42;
    int userGuess;

    while (true) {
        std::cout << "Guess the mystery number (1-100): ";
        std::cin >> userGuess;

        if (userGuess < 1 || userGuess > 100) {
            std::cout << "Invalid guess. Please enter a number between 1 and 100." << std::endl;
            break;
        } else if (userGuess > mysteryNumber) {
            std::cout << "Too high! Try again." << std::endl;
            break;
        } else if (userGuess < mysteryNumber) {
            std::cout << "Too low! Try again." << std::endl;
            break;
        } else {
            std::cout << "Congratulations! You guessed the number!" << std::endl;
            break;
        }
    }

    return 0;
}

Output 1:

Output

Guess the mystery number (1-100):10 
Too low! Try again.

Output 2:

Output

Guess the mystery number (1-100):59
Too high! Try again.

Output 3:

Output

Guess the mystery number (1-100):42
Congratulations! You guessed the number!

2. Edge Case: Input is Non-Numeric

Validate input to account for non-numeric types and clear input buffer.

Example

#include <iostream>
#include <limits>

int main() {
    int mysteryNumber = 42;
    int userGuess;

    while (true) {
        std::cout << "Guess the mystery number (1-100): ";
        std::cin >> userGuess;

        if (std::cin.fail()) {
            std::cin.clear(); // Clear the error flag
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // Discard invalid input
            std::cout << "Invalid input. Please enter a numeric value." << std::endl;
        } else if (userGuess < 1 || userGuess > 100) {
            std::cout << "Invalid guess. Please enter a number between 1 and 100." << std::endl;
        } else if (userGuess > mysteryNumber) {
            std::cout << "Too high! Try again." << std::endl;
        } else if (userGuess < mysteryNumber) {
            std::cout << "Too low! Try again." << std::endl;
        } else {
            std::cout << "Congratulations! You guessed the number!" << std::endl;
            break;
        }
    }

    return 0;
}

Output:

Output

Guess the mystery number (1-100): 67
Too high! Try again.
Guess the mystery number (1-100): 30
Too low! Try again.
Guess the mystery number (1-100): 45
Too high! Try again.
Guess the mystery number (1-100): 40
Too low! Try again.
Guess the mystery number (1-100): 41
Too low! Try again.
Guess the mystery number (1-100): 42
Congratulations! You guessed the number!

3. Combining Multiple Conditions

You can combine conditions to handle specific situations using logical operators (&&, ||).

Example

#include <iostream>
#include <limits> // Required for std::numeric_limits

int main() {
    int userGuess;

    while (true) {
        std::cout << "Enter a number between 1 and 100: ";
        std::cin >> userGuess;

        if (std::cin.fail() || userGuess < 1 || userGuess > 100) {
            std::cin.clear(); // Clear error flags
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // Discard invalid input
            std::cout << "Invalid input. Please enter a number between 1 and 100." << std::endl;
        } else {
            break; // Exit loop if input is valid
        }
    }

    std::cout << "You entered: " << userGuess << std::endl;
    return 0;
}

Output 1:

Output

Enter a number between 1 and 100: 90
You entered: 90

Output:

Output

Enter a number between 1 and 100: 150
Invalid input. Please enter a number between 1 and 100.
Enter a number between 1 and 100: 89
You entered: 89

Game Loop Implementation

Implementing a game loop is crucial for interactive games, like a Mystery Number Game. A game loop repeatedly executes game logic (e.g., taking user input and checking guesses) until a specific condition is met, such as the player guessing the correct number.

Structuring the game logic with loops (while, do-while, or for)

1. Game Loop Using while

A while loop is effective for repeating the guessing logic until the player guesses correctly.

Example

#include <iostream>
#include <cstdlib> // For rand() and srand()
#include <ctime>   // For time()
#include <limits>  // For std::numeric_limits

int main() {
    srand(static_cast<unsigned>(time(0))); // Seed random number generator
    int mysteryNumber = rand() % 100 + 1;  // Random number between 1 and 100
    int userGuess;

    std::cout << "Welcome to the Mystery Number Game!" << std::endl;

    bool guessedCorrectly = false;

    while (!guessedCorrectly) {
        std::cout << "Guess the mystery number (1-100): ";
        std::cin >> userGuess;

        if (std::cin.fail()) {
            std::cin.clear(); // Clear error flag
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // Discard invalid input
            std::cout << "Invalid input. Please enter a number between 1 and 100." << std::endl;
            continue;
        }

        if (userGuess < 1 || userGuess > 100) {
            std::cout << "Out of range! Enter a number between 1 and 100." << std::endl;
        } else if (userGuess > mysteryNumber) {
            std::cout << "Too high! Try again." << std::endl;
        } else if (userGuess < mysteryNumber) {
            std::cout << "Too low! Try again." << std::endl;
        } else {
            std::cout << "Congratulations! You guessed the number!" << std::endl;
            guessedCorrectly = true;
        }
    }

    return 0;
}

Output:

Output

Welcome to the Mystery Number Game!
Guess the mystery number (1-100): 90
Too high! Try again.
Guess the mystery number (1-100): 80
Too high! Try again.
Guess the mystery number (1-100): 70
Too low! Try again.
Guess the mystery number (1-100): 75
Congratulations! You guessed the number!

2. Game Loop Using do-while

A do-while loop guarantees the game logic runs at least once, which is useful for user-driven games.

Example

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <limits> // Include this header for std::numeric_limits

int main() {
    srand(static_cast<unsigned>(time(0))); // Seed random number generator
    int mysteryNumber = rand() % 100 + 1; // Random number between 1 and 100
    int userGuess;

    std::cout << "Welcome to the Mystery Number Game!" << std::endl;

    do {
        std::cout << "Guess the mystery number (1-100): ";
        std::cin >> userGuess;

        if (std::cin.fail()) {
            std::cin.clear(); // Clear the error flag
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // Discard invalid input
            std::cout << "Invalid input. Please try again." << std::endl;
            continue;
        }

        if (userGuess < 1 || userGuess > 100) {
            std::cout << "Out of range! Enter a number between 1 and 100." << std::endl;
        } else if (userGuess > mysteryNumber) {
            std::cout << "Too high! Try again." << std::endl;
        } else if (userGuess < mysteryNumber) {
            std::cout << "Too low! Try again." << std::endl;
        } else {
            std::cout << "Congratulations! You guessed the number!" << std::endl;
            break; // Exit the loop upon correct guess
        }
    } while (true);

    return 0;
}

Output:

Output

Welcome to the Mystery Number Game!
Guess the mystery number (1-100): 90
Too high! Try again.
Guess the mystery number (1-100): 80
Too high! Try again.
Guess the mystery number (1-100): 70
Too high! Try again.
Guess the mystery number (1-100): 60
Too low! Try again.
Guess the mystery number (1-100): 65
Too high! Try again.
Guess the mystery number (1-100): 63
Congratulations! You guessed the number!

3. Game Loop Using for

A for loop is less common for guessing games but can enforce a maximum number of attempts.

Example

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <limits> // Required for std::numeric_limits

int main() {
    srand(static_cast<unsigned>(time(0))); // Seed random number generator
    int mysteryNumber = rand() % 100 + 1; // Random number between 1 and 100
    int userGuess;

    std::cout << "Welcome to the Mystery Number Game!" << std::endl;

    const int maxAttempts = 5; // Limit the number of attempts

    for (int attempts = 1; attempts <= maxAttempts; ++attempts) {
        std::cout << "Attempt " << attempts << " of " << maxAttempts << ": ";
        std::cin >> userGuess;

        if (std::cin.fail()) {
            std::cin.clear(); // Clear the error flag
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // Discard invalid input
            std::cout << "Invalid input. Please try again." << std::endl;
            --attempts; // Retry the same attempt
            continue;
        }

        if (userGuess < 1 || userGuess > 100) {
            std::cout << "Out of range! Enter a number between 1 and 100." << std::endl;
        } else if (userGuess > mysteryNumber) {
            std::cout << "Too high! Try again." << std::endl;
        } else if (userGuess < mysteryNumber) {
            std::cout << "Too low! Try again." << std::endl;
        } else {
            std::cout << "Congratulations! You guessed the number!" << std::endl;
            break;
        }

        if (attempts == maxAttempts) {
            std::cout << "Game over! The mystery number was " << mysteryNumber << "." << std::endl;
        }
    }

    return 0;
}

Output:

Output

Welcome to the Mystery Number Game!
Attempt 1 of 5: 1
Too low! Try again.
Attempt 2 of 5: 56
Too low! Try again.
Attempt 3 of 5: 200
Out of range! Enter a number between 1 and 100.
Attempt 4 of 5: 45
Too low! Try again.
Attempt 5 of 5: 42
Too low! Try again.
Game over! The mystery number was 84.

Conclusion

The mystery number game is an absolute starter course for anyone wanting to get started in practical and conceptual programming projects. Working on this game involves a number of fundamental skills, such as:

1. Using Variables and Random Number Generators:

To store and manipulate variables such as user guesses and the number they're trying to guess, alongside generating random numbers using rand or <random>, not to mention, explode examples of how to practically apply your initiates.

2. Input/Output Handling:

Catches user input via std::cin and makes meaningful feedback with std::cout-an intro to the core of interaction in the software: user interaction.

3. Game Logic Structure with Conditional Statements and Loops:

Implementation of if-else conditions along with loops (while, do-while, or for) showing how to make structured reusable logic-the core skill in programming.

4. Ensuring Robust Input Validation:

Validation of User Input is done not only to ensure smooth-to-play but also underlines coding with reduced error possibilities through considering edge cases and even invalid entries.

5. Improving Problem-Solving Skills:

This game encourages both players and programmers-the players think the numbers out deductively, while the programmers design experiences that can range from the most intuitive to feature-rich and user-friendly.

6. Exploring Creative Additions:

Ways to stretch the game's image include adding scores, hints, degrees of difficulty, and limits on the number of times a user can retry. These are all areas that could be open to much-needed creativity and learning and would demonstrate how software grows with the expectations of users.

Input Required

This code uses input(). Please provide values below: