##My version
int readInteger(const char *prompt) { std::cout << prompt << std::flush; int n; if (std::cin >> n) return n; // else, clean up and ask again std::cin.clear(); return readInteger(prompt); }
int readInteger(const char *prompt)
{
std::cout << prompt << std::flush;
int n;
if (std::cin >> n)
return n;
// else, clean up and ask again
std::cin.clear();
return readInteger(prompt);
}
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <string>
int readInteger(const char *prompt)
{
std::cout << prompt << std::flush;
int n;
if (std::cin >> n)
return n;
// else, clean up and ask again
std::cin.clear();
std::string line;
std::getline(std::cin, line);
return readInteger(prompt);
}
void playComputersChoice()
{
const int computersNumber = (rand()) % 100 + 1;
std::cout << "Welcome. Try to guess my number.\n";
for (int tries = 0; ; ++tries) {
int playersNumber = readInteger("Your guess: ");
if (playersNumber > computersNumber) {
std::cout << "Too bad. Your guess was too high.\n";
} else if (playersNumber < computersNumber) {
std::cout << "Too bad. Your guess was too low.\n";
} else {
std::cout << "You did it. You guessed my number.\n"
<< "It only took you " << tries << " tries.\n";
return;
}
}
}
void playPlayersChoice()
{
int playersNumber;
do {
playersNumber = readInteger("Pick a number: ");
} while (playersNumber < 1 || playersNumber > 100);
int tooLow = 0;
int tooHigh = 101;
for (int tries = 0; ; ++tries) {
int computersNumber = tooLow + 1 + rand() % (tooHigh-tooLow-1);
std::cout << "Is it " << computersNumber << "?\n";
std::cout << "This was my " << tries << " try.\n";
if (computersNumber < playersNumber) {
tooLow = computersNumber;
} else if (computersNumber > playersNumber) {
tooHigh = computersNumber;
} else {
// found it
std::cout << "Well then it has to be " << computersNumber << "\n";
std::cout << "Only took me " << ++tries << " goes!\n\n";
return;
}
}
}
enum playMode { playerVersusCpu = 1, cpuVersusPlayer, exitMenu};
playMode selectPlayMode()
{
std::cout << playerVersusCpu << " - Player Versus Computer\n";
std::cout << cpuVersusPlayer << " - Computer Versus Player\n";
std::cout << exitMenu << " - Exit\n";
return playMode(readInteger("Select a game mode: "));
}
int main()
{
std::srand(static_cast<unsigned int>(std::time(nullptr)));
playMode playModeSelect;
do {
playModeSelect = selectPlayMode();
switch (playModeSelect) {
case playerVersusCpu:
playComputersChoice();
break;
case cpuVersusPlayer:
playPlayersChoice();
break;
case exitMenu:
// do nothing here
break;
}
} while (playModeSelect != exitMenu);
}
int readInteger(const char *prompt) { std::cout << prompt << std::flush; int n; if (std::cin >> n) return n; // else, clean up and ask again std::cin.clear(); return readInteger(prompt); }
#include <iostream>
#include <ctime>
#include <cstdlib>
int readInteger(const char *prompt)
{
std::cout << prompt << std::flush;
int n;
if (std::cin >> n)
return n;
// else, clean up and ask again
std::cin.clear();
std::string line;
std::getline(std::cin, line);
return readInteger(prompt);
}
void playComputersChoice()
{
const int computersNumber = (rand()) % 100 + 1;
std::cout << "Welcome. Try to guess my number.\n";
for (int tries = 0; ; ++tries) {
int playersNumber = readInteger("Your guess: ");
if (playersNumber > computersNumber) {
std::cout << "Too bad. Your guess was too high.\n";
} else if (playersNumber < computersNumber) {
std::cout << "Too bad. Your guess was too low.\n";
} else {
std::cout << "You did it. You guessed my number.\n"
<< "It only took you " << tries << " tries.\n";
return;
}
}
}
void playPlayersChoice()
{
int playersNumber;
do {
playersNumber = readInteger("Pick a number: ");
} while (playersNumber < 1 || playersNumber > 100);
int tooLow = 0;
int tooHigh = 101;
for (int tries = 0; ; ++tries) {
int computersNumber = tooLow + 1 + rand() % (tooHigh-tooLow-1);
std::cout << "Is it " << computersNumber << "?\n";
std::cout << "This was my " << tries << " try.\n";
if (computersNumber < playersNumber) {
tooLow = computersNumber;
} else if (computersNumber > playersNumber) {
tooHigh = computersNumber;
} else {
// found it
std::cout << "Well then it has to be " << computersNumber << "\n";
std::cout << "Only took me " << ++tries << " goes!\n\n";
return;
}
}
}
enum playMode { playerVersusCpu = 1, cpuVersusPlayer, exitMenu};
playMode selectPlayMode()
{
std::cout << playerVersusCpu << " - Player Versus Computer\n";
std::cout << cpuVersusPlayer << " - Computer Versus Player\n";
std::cout << exitMenu << " - Exit\n";
return playMode(readInteger("Select a game mode: "));
}
int main()
{
std::srand(static_cast<unsigned int>(std::time(nullptr)));
playMode playModeSelect;
do {
playModeSelect = selectPlayMode();
switch (playModeSelect) {
case playerVersusCpu:
playComputersChoice();
break;
case cpuVersusPlayer:
playPlayersChoice();
break;
case exitMenu:
// do nothing here
break;
}
} while (playModeSelect != exitMenu);
}
int readInteger(const char *prompt)
{
std::cout << prompt << std::flush;
int n;
if (std::cin >> n)
return n;
// else, clean up and ask again
std::cin.clear();
return readInteger(prompt);
}
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <string>
int readInteger(const char *prompt)
{
std::cout << prompt << std::flush;
int n;
if (std::cin >> n)
return n;
// else, clean up and ask again
std::cin.clear();
std::string line;
std::getline(std::cin, line);
return readInteger(prompt);
}
void playComputersChoice()
{
const int computersNumber = (rand()) % 100 + 1;
std::cout << "Welcome. Try to guess my number.\n";
for (int tries = 0; ; ++tries) {
int playersNumber = readInteger("Your guess: ");
if (playersNumber > computersNumber) {
std::cout << "Too bad. Your guess was too high.\n";
} else if (playersNumber < computersNumber) {
std::cout << "Too bad. Your guess was too low.\n";
} else {
std::cout << "You did it. You guessed my number.\n"
<< "It only took you " << tries << " tries.\n";
return;
}
}
}
void playPlayersChoice()
{
int playersNumber;
do {
playersNumber = readInteger("Pick a number: ");
} while (playersNumber < 1 || playersNumber > 100);
int tooLow = 0;
int tooHigh = 101;
for (int tries = 0; ; ++tries) {
int computersNumber = tooLow + 1 + rand() % (tooHigh-tooLow-1);
std::cout << "Is it " << computersNumber << "?\n";
std::cout << "This was my " << tries << " try.\n";
if (computersNumber < playersNumber) {
tooLow = computersNumber;
} else if (computersNumber > playersNumber) {
tooHigh = computersNumber;
} else {
// found it
std::cout << "Well then it has to be " << computersNumber << "\n";
std::cout << "Only took me " << ++tries << " goes!\n\n";
return;
}
}
}
enum playMode { playerVersusCpu = 1, cpuVersusPlayer, exitMenu};
playMode selectPlayMode()
{
std::cout << playerVersusCpu << " - Player Versus Computer\n";
std::cout << cpuVersusPlayer << " - Computer Versus Player\n";
std::cout << exitMenu << " - Exit\n";
return playMode(readInteger("Select a game mode: "));
}
int main()
{
std::srand(static_cast<unsigned int>(std::time(nullptr)));
playMode playModeSelect;
do {
playModeSelect = selectPlayMode();
switch (playModeSelect) {
case playerVersusCpu:
playComputersChoice();
break;
case cpuVersusPlayer:
playPlayersChoice();
break;
case exitMenu:
// do nothing here
break;
}
} while (playModeSelect != exitMenu);
}
Starting with a few simple things:
using namespace std;
It's a poor idea to import the whole of std
namespace into your program. Instead, I suggest you selectively take just those names you intend to use.
system("pause");
When using system()
, you should always check its return value; in this particular case, it will always fail unless there's a pause
program on the user's PATH. I have no such thing, and it doesn't seem to be in any common Linux distribution I've ever seen - it appears to be this anti-pattern.
Two variables are declared but never used: playAgain
and roundOver
.
On to the structure. The code looks like One Big Main(). It really helps to identify self-contained chunks of functionality and, especially, any re-usable parts of the program. So I'd write something more like:
int main()
{
playMode playModeSelect;
do {
playModeSelect = selectPlayMode();
switch (playModeSelect) {
case playerVersusCpu:
playComputersChoice();
break;
case cpuVersusPlayer:
playPlayersChoice();
break;
case exitMenu:
// do nothing here
break;
}
} while (playModeSelect != exitMenu);
}
Having done that, we can implement the functions selectPlayMode()
, playComputersChoice()
and playPlayersChoice()
. Let's start with selectPlayMode()
. A function version of your code looks like:
playMode selectPlayMode()
{
using std::cout;
using std::cin;
cout << "1 - Player Versus Computer\n";
cout << "2 - Computer Versus Player\n";
cout << "3 - Exit\n";
cout << "Select a game mode: ";
int playModeSelect;
cin >> playModeSelect;
return playMode(playModeSelect);
}
We can be more rigorous about ensuring that the displayed numbers match how we interpret them:
cout << playerVersusCpu << " - Player Versus Computer\n";
cout << cpuVersusPlayer << " - Computer Versus Player\n";
cout << exitMenu << " - Exit\n";
cout << "Select a game mode: " << std::flush;
Note that I've explicitly flushed the output stream before reading any input. This should happen anyway when switching between cout
and cin
, but it's good to be clear that this is what we want.
Now let's move on to playComputersChoice()
. If we extract this into a function, we have:
void playComputersChoice()
{
int computersNumber = (rand()) % 100 + 1;
int tries = 0;
std::cout << "Welcome. Try to guess my number: " << std::flush;
int playersNumber;
do {
std::cin >> playersNumber;
if (playersNumber > computersNumber)
{
std::cout << "Too bad. Your guess was too high.\n";
std::cout << "Try again: " << std::flush;
++tries;
}
else if (playersNumber < computersNumber)
{
std::cout << "Too bad. Your guess was too low.\n";
std::cout << "Try again: " << std::flush;
++tries;
}
else if (playersNumber = computersNumber)
{
std::cout << "You did it. You guessed my number.\n";
++tries;
std::cout << "It only took you " << tries << " tries.\n";
}
} while (playersNumber != computersNumber);
}
Some things that I see here: in the if/else-if cascade, the last condition will always be true if the first two were false, so we can write a simple else
there. Note also that we increment tries
in each branch of the if, so we can hoist that statement so it's always executed. Finally, the do/while repeats the test of playersNumber
against computersNumber
; instead of that, we could write an infinite loop, and break out of it when the player wins:
void playComputersChoice()
{
const int computersNumber = (rand()) % 100 + 1;
std::cout << "Welcome. Try to guess my number: " << std::flush;
for (int tries = 0; ; ++tries) {
int playersNumber;
std::cin >> playersNumber;
if (playersNumber > computersNumber) {
std::cout << "Too bad. Your guess was too high.\n"
<< "Try again: " << std::flush;
} else if (playersNumber < computersNumber) {
std::cout << "Too bad. Your guess was too low.\n"
<< "Try again: " << std::flush;
} else {
std::cout << "You did it. You guessed my number.\n"
<< "It only took you " << tries << " tries.\n";
return;
}
}
}
You'll see that I made computersNumber
constant, to show that during this game, the computer can't change its secret number - that would be cheating! More seriously, the judicious use of const
can help to avoid misunderstandings and mistakes.
Finally, let's have the computer do the guessing:
void playPlayersChoice()
{
int playersNumber;
std::cout << "Pick a number: " << std::flush;
std::cin >> playersNumber;
int tries = 0;
int tooLow = 0;
int tooHigh = 101;
int computersNumber;
do {
computersNumber = rand() % 100 + 1;
while ((computersNumber != playersNumber) && (computersNumber > tooLow) && (computersNumber < tooHigh)) {
++tries;
std::cout << "Is it " << computersNumber << "?\n";
std::cout << "This was my " << tries << " try.\n";
if ((computersNumber > tooLow) && (computersNumber < playersNumber)) {
tooLow = computersNumber;
} else if ((computersNumber < tooHigh) && (computersNumber > playersNumber)) {
tooHigh = computersNumber;
}
}
} while (computersNumber != playersNumber);
std::cout << "Well then it has to be " << computersNumber << "\n";
std::cout << "Only took me " << ++tries << " goes!\n\n";
}
There's a few changes we can make here. First, we should ensure that the player's number is within the range 1-100, otherwise the computer can never guess it:
int playersNumber;
do {
std::cout << "Pick a number: " << std::flush;
std::cin >> playersNumber;
} while (playersNumber < 1 || playersNumber > 100);
Also, the computer should be able to use its previously determined high and low values when guessing:
computersNumber = tooLow + 1 + rand() % (tooHigh-tooLow-1);
And we can use a similar loop to the player's game:
for (int tries = 0; ; ++tries) {
Now, something that applies throughout. What happens if you don't enter a number when asked? The >>
operator will return false, but we never check it, and never fix up the stream. We definitely need some error handling, and to avoid writing the same code many times, we'll want it as a function:
int readInteger(const char *prompt) { std::cout << prompt << std::flush; int n; if (std::cin >> n) return n; // else, clean up and ask again std::cin.clear(); return readInteger(prompt); }
I don't think you the "Play again (y/n)" question. Given that choice 3 from the menu is "exit", then asking whether to play again is redundant. You could go the other way, and remove the exit option instead.
##My version
#include <iostream>
#include <ctime>
#include <cstdlib>
int readInteger(const char *prompt)
{
std::cout << prompt << std::flush;
int n;
if (std::cin >> n)
return n;
// else, clean up and ask again
std::cin.clear();
std::string line;
std::getline(std::cin, line);
return readInteger(prompt);
}
void playComputersChoice()
{
const int computersNumber = (rand()) % 100 + 1;
std::cout << "Welcome. Try to guess my number.\n";
for (int tries = 0; ; ++tries) {
int playersNumber = readInteger("Your guess: ");
if (playersNumber > computersNumber) {
std::cout << "Too bad. Your guess was too high.\n";
} else if (playersNumber < computersNumber) {
std::cout << "Too bad. Your guess was too low.\n";
} else {
std::cout << "You did it. You guessed my number.\n"
<< "It only took you " << tries << " tries.\n";
return;
}
}
}
void playPlayersChoice()
{
int playersNumber;
do {
playersNumber = readInteger("Pick a number: ");
} while (playersNumber < 1 || playersNumber > 100);
int tooLow = 0;
int tooHigh = 101;
for (int tries = 0; ; ++tries) {
int computersNumber = tooLow + 1 + rand() % (tooHigh-tooLow-1);
std::cout << "Is it " << computersNumber << "?\n";
std::cout << "This was my " << tries << " try.\n";
if (computersNumber < playersNumber) {
tooLow = computersNumber;
} else if (computersNumber > playersNumber) {
tooHigh = computersNumber;
} else {
// found it
std::cout << "Well then it has to be " << computersNumber << "\n";
std::cout << "Only took me " << ++tries << " goes!\n\n";
return;
}
}
}
enum playMode { playerVersusCpu = 1, cpuVersusPlayer, exitMenu};
playMode selectPlayMode()
{
std::cout << playerVersusCpu << " - Player Versus Computer\n";
std::cout << cpuVersusPlayer << " - Computer Versus Player\n";
std::cout << exitMenu << " - Exit\n";
return playMode(readInteger("Select a game mode: "));
}
int main()
{
std::srand(static_cast<unsigned int>(std::time(nullptr)));
playMode playModeSelect;
do {
playModeSelect = selectPlayMode();
switch (playModeSelect) {
case playerVersusCpu:
playComputersChoice();
break;
case cpuVersusPlayer:
playPlayersChoice();
break;
case exitMenu:
// do nothing here
break;
}
} while (playModeSelect != exitMenu);
}