General observations
=======
To be honest, your code is extremely clear and readable to me. I wouldn't guess that you were a beginner from reading your code. You have eliminated the use of magic numbers, and use global constants instead which is good!
----------
[Anonymous namespaces][1]
=======
The keyword `static` in this context means that it has [internal linkage][2]. An [anonymous namespace][1] also does the same thing, but they are considered to be somewhat [superior][3] to the `static` keyword in C++.
The link I cited has some great answers.<br> But mainly,
- `static` will only work for functions and objects, an anonymous namespace on the other hand can let you have your own type definitions, classes, structs (almost everything)...
```c++
// Globals.h
namespace
{
// constants
}
```
Prefer using `constexpr`
=======
[**constexpr in C++**][4]
> The keyword `constexpr` was introduced in C++11 and improved in C++14.
> It means constant expression. Like `const`, it can be applied to
> variables: A compiler error is raised when any code attempts to modify
> the value. Unlike `const`, `constexpr` can also be applied to functions
> and class constructors. constexpr indicates that the value, or return
> value, is constant and, where possible, is computed at compile time.
Use `constexpr` when you can, it tells the compiler that it's literally just a constant. <br> It forces the compiler to calculate the value of something at compile-time. Moreover, you can pass it as a template argument too
```c++
namespace
{
constexpr char COMPUTER_GUESSER { 'c' };
}
```
----------
Use an `enum`
=======
This point can depend according to your style, but I think that an [enum][5] is called for here.
I am talking about these variables
```c++
COMPUTER_GUESSER = 'c';
PLAYER_GUESSER = 'p';
QUIT = 'q';
ANSWER_IS_YES = 'y';
ANSWER_IS_NO = 'n';
```
I believe that having an `enum` here makes sense because you can group these variables as they all are related to the user's **choice**, this is what it would look like
```c++
enum Choice : char
{
COMPUTER_GUESSER = 'c',
PLAYER_GUESSER = 'p',
QUIT = 'q',
ANSWER_IS_YES = 'y',
ANSWER_IS_NO = 'n',
};
```
```c++
if (input == Choice::QUIT) //...
else if (input == Choice::ANSWER_YES) //...
```
----------
Generating a random `int`
=======
C++ has [`std::uniform_int_distribution`][6] which is better than C's `rand()`.
----------
Consider [`inlining`][7] smaller functions
=======
```c++
int randomNumGenerator(const int max, const int min)
{
return rand() % max + min;
}
int rangeNumToGuess(const int max, const int min)
{
return ((max - min) / 2) + min;
}
int rangeNum(const int max, const int min)
{
return max - min;
}
```
Inlining these functions can improve the performance a lot, but you need to place the definition of these functions in the **header file**, you can specify `inline` but it's likely that the compiler will inline them itself.
> instead of executing the function call CPU instruction to transfer
> control to the function body, a copy of the function body is executed
> without generating the call.
----------
Always handle invalid input
=======
```c++
std::cout << "Enter your guess number: ";
while (std::cin >> userGuess)
{
//...
}
```
Here, `std::cin` is expecting an integer, if the user accidentally enters something else, `std::cin` will **fail**, leading to strange behavior in your
There are a few ways, [this][8] article is worth reading.
A small bug
=======
In your `restart()` function
```c++
bool restart()
{
char userChoice{};
std::cout << "Play again? (y/n): ";
std::cin >> userChoice;
char lowerUserChoice = tolower(userChoice);
if (lowerUserChoice == ANSWER_IS_YES)
{
startGame();
}
else if (lowerUserChoice == ANSWER_IS_NO)
{
computerOrPlayer(QUIT);
}
else
{
std::cout << "Please choose the available option\n";
restart();
}
return true;
}
```
Since you recursively call `restart()` on invalid input, you should `return` the value you get. Otherwise, the function won't return anything
```c++
else
{
std::cout << "Please choose a valid option!\n";
return restart();
}
```
[1]: https://stackoverflow.com/questions/357404/why-are-unnamed-namespaces-used-and-what-are-their-benefits
[2]: https://www.learncpp.com/cpp-tutorial/internal-linkage/
[3]: https://stackoverflow.com/questions/4422507/superiority-of-unnamed-namespace-over-static
[4]: https://docs.microsoft.com/en-us/cpp/cpp/constexpr-cpp?view=vs-2019#:~:text=The%20keyword%20constexpr%20was%20introduced,to%20functions%20and%20class%20constructors.
[5]: https://en.cppreference.com/w/cpp/language/enum
[6]: https://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution
[7]: https://en.cppreference.com/w/cpp/language/inline#:~:text=The%20inline%20specifier%2C%20when%20used,is%20implicitly%20an%20inline%20function.
[8]: https://www.learncpp.com/cpp-tutorial/5-10-stdcin-extraction-and-dealing-with-invalid-text-input/