Sign in to follow this  
lightningblah

My Guess the Number Code for criticism

Recommended Posts

lightningblah    110
edit: I uploaded the program of the game for anyone to see how it works and handles everything easily. The program will automatically create a "highscores.txt" file in whatever directory you run it in.

The program can be found here: http://www.mediafire.com/?t41zeb9azb4pa56
---------------

I made Guess the Number.. the age old game where you guess a number between 1 and 100 and the computer tells you if it's too high or too low. The features I added to the game are:

-High score list. It's in a text file so it's easy for anyone to modify it, but the game checks if there's any extra lines or letters or numbers where they're not supposed to be and reloads a default high score file if needed.
-Protection against any incorrect input. If you try to put letters or spaces where numbers are supposed to go, or numbers where letters should the game doesn't let you.
-Easy, navigable menu.

The game compiles and runs well without any bugs or errors (as far as I can tell :X) but I know there's still a lot to work on internally. I tried to use classes in this game but structuring it well with them is hard for me to grasp. I also put them all into a game class to make it so I didn't need any global variables, but I feel like I still have them they're just hidden in my game class. I also think there might be better ways for me to handle checking for errors.

Any criticism and suggestions or bashing is welcomed by all, and thank you in advance. I know there's a lot of code here and if there's a better way to share it I'll modify my post right away.

game.h
 
#ifndef game_h
#define game_h

#include "randomNumber.h"
#include "stringManipulator.h"
#include "textFile.h"
#include <string>
using std::string;

class game
{
public:
void start();
void newGame();
void newGameHeader();
void checkScoreFile();
void howToPlay();
void viewTopScores();
void resetTopScores();
void displayMenu();
void quitGame();
void checkTopScores();
void setTopScores(int i);
void showCredits();
void topScoreHeader();

game();
~game() {}
private:
randomNumber gameRandomNumber;
stringManipulator gameStringManipulator;
textFile gameHighscores;

bool mainGame; // bools to keep game loops going
bool inNewGame;
bool inMenu;
bool inTopScores;

string stringMenuChoice;
int intMenuChoice;

int intHighscores[10];
string strHighscores[10];

int intGuess;
string stringGuess;

string strInitials;

int numberOfTurns;

int error;
int quit;
};

#endif











game.cpp

#include "game.h"
#include "randomNumber.h"
#include "stringManipulator.h"
#include "textFile.h"
#include <iostream>
#include <string>

using namespace std;


game::game()
{
intGuess = -1; // intGuess is set to -1 to show it's the start of the game
error = -1;
quit = -2;

mainGame = true;
inMenu = true;
inNewGame = false;
inTopScores = false;

gameRandomNumber.seed();

numberOfTurns = 0;
}

void game::start()
{
system("cls");

checkScoreFile(); // make sure high score table is in a valid format

displayMenu();

while (mainGame == true)
{
while (inMenu == true)
{
cout << endl << ": ";

getline(cin, stringMenuChoice);

intMenuChoice = gameStringManipulator.getTitleScreenInput(stringMenuChoice);

if (intMenuChoice == error)
{
system("cls");
displayMenu();
cout << endl << "Invalid input!" << endl;
}
else
{
inMenu = false;
}
}

switch (intMenuChoice)
{
case 1:
newGame();
displayMenu();
break;
case 2:
system("cls");
howToPlay();
displayMenu();
break;
case 3:
system("cls");
viewTopScores();
displayMenu();
break;
case 4:
system("cls");
resetTopScores();
displayMenu();
break;
case 5:
system("cls");
showCredits();
displayMenu();
break;
case 6:
quitGame();
mainGame = false;
break;
default:
displayMenu();
cout << "Error.";
mainGame = false;
break;
}
}
}

void game::quitGame()
{
system("cls");
}

void game::newGame()
{
inNewGame = true;
gameRandomNumber.generateNewNumber();

newGameHeader();

while (inNewGame == true)
{

cout << ": ";
getline(cin, stringGuess);
intGuess = gameStringManipulator.convertToInt(stringGuess);

if (intGuess == quit)
{
inNewGame = false;
intGuess = -1;
numberOfTurns = 0;
system("cls");
break;
}

if (intGuess == error || intGuess < 1 || intGuess > 100)
{
newGameHeader();
cout << "Invalid input!" << endl << endl;
}
else if (intGuess < gameRandomNumber.getNumber())
{
numberOfTurns++;
newGameHeader();
cout << "Higher!" << endl << endl;
}
else if (intGuess > gameRandomNumber.getNumber())
{
numberOfTurns++;
newGameHeader();
cout << "Lower!" << endl << endl;
}
else if (intGuess == gameRandomNumber.getNumber())
{
system("cls");
cout << "You win!" << endl;
numberOfTurns++;
cout << endl << "The correct number was " <<

gameRandomNumber.getNumber() << "." << " It took you " << numberOfTurns << "

tries to win! Congratulations." << endl << endl;
checkTopScores(); //check if the player made the top scores
numberOfTurns = 0;
intGuess = -1;
inNewGame = false;
}
}

inMenu = true;

}

void game::displayMenu()
{
cout << "***Guess the Number***" << endl;
cout << "(1) New game" << endl;
cout << "(2) How to play" << endl;
cout << "(3) Top scores" << endl;
cout << "(4) Reset top scores" << endl;
cout << "(5) Credits" << endl;
cout << "(6) Quit" << endl;
}

void game::newGameHeader()
{
system("cls");
cout << "The computer picked a number between 1 and 100, try to guess

it in as few turns as possible!" << endl << "Enter q to quit at any time." <<

endl << endl << "So far you have taken " << numberOfTurns << " tries to guess

the number." << endl;
if (intGuess == -1) // if it's before the player has made a guess
{
cout << "You haven't guessed a number yet." << endl << endl;
}
else
{
cout << "The last number you guessed was " << intGuess << "." << endl << endl;
}
}

void game::checkTopScores()
{
if (gameHighscores.readNamesAndScores("highscores.txt", strHighscores, intHighscores) == false)
{
cout << "Error!";
}

for (int i = 9; i >= 0; i--) // from the bottom of the file count up
{
if (i == 0) //if you're on the top of the file, and the player did better
{
if (numberOfTurns < intHighscores[i])
{
setTopScores(i);
break;
}
}
if (numberOfTurns == intHighscores[i]) // if the player matches a preview top score, replace it
{
setTopScores(i);
break;
}
else if (numberOfTurns < intHighscores[i] && numberOfTurns >

intHighscores[i - 1]) //if the player did better than one score, but not

better than the next, replace the first score
{
setTopScores(i);
break;
}
}
}

void game::howToPlay()
{
system("cls");

cout << "The object of the game is to guess the randomly generated

number between" << endl << "1 and 100 using as few turns as possible. The

computer will tell you if" << endl << "you guessed too high, too low, or the

correct number each guess you make." << endl << endl;

inMenu = true;

}

void game::checkScoreFile()
{
if (gameHighscores.checkFile("highscores.txt") == false)
{
cout << "Highscore file is corrupt.. loading default." << endl << endl;
if (gameHighscores.loadDefault("highscores.txt") == false)
{
cout << "Error!";
}
}
}

void game::viewTopScores()
{
system("cls");

if (gameHighscores.readNamesAndScores("highscores.txt", strHighscores, intHighscores) == false)
{
cout << "Error!";
}

for (int i = 0; i < 10; i++)
{
cout << strHighscores[i] << " " << intHighscores[i] << endl;
}
cout << endl;
inMenu = true;
}

void game::topScoreHeader()
{
system("cls");
cout << "You made it on the top score list! Please enter your three

initials." << endl << "(Symbols allowed..)" << endl << endl;
}

void game::setTopScores(int i)
{
inTopScores = true;

cout << "You made it on the top score list! Please enter your three

initials." << endl << "(Symbols allowed..)" << endl << endl;
while (inTopScores == true)
{
cout << ":";
getline(cin, strInitials);
if (gameStringManipulator.isInitials(strInitials) == false)
{
topScoreHeader();
cout << endl << "Please enter only three letters or
symbols for your initials." << endl << endl;
}
else
inTopScores = false;
}
intHighscores[i] = numberOfTurns;
strHighscores[i] = strInitials;
if (gameHighscores.writeToFile("highscores.txt", intHighscores, strHighscores) == false)
{
cout << "Error!";
}
system("cls");
}

void game::showCredits()
{
system("cls");
cout << "This game was programmed by Jonathan Whitaker in C++. &

Jonathan Whitaker was motivated by Catherine Alvarez." << endl << endl;

inMenu = true;
}

void game::resetTopScores()
{
system("cls");
cout << "Reseting highscore file to it's default values..." << endl << endl;
if (gameHighscores.loadDefault("highscores.txt") == false)
{
cout << "Error!";
}

inMenu = true;
}











stringManipulator.h

#ifndef stringManipulator_h
#define stringManipulator_h

#include <string>
using std::string;

class stringManipulator
{
public:
stringManipulator();
~stringManipulator() {}
int convertToInt(string newString); // convert a string to an int
int getTitleScreenInput(string newString); // only returns ints needed for the title screen
bool isInitials(string newString); // makes sure just 3 letters or symbols were entered
private:
int error; // error return values
int quit;
};

#endif











stringManipulator.cpp

#include "stringManipulator.h"
#include <sstream>
#include <string>
using std::istringstream;
using std::string;

stringManipulator::stringManipulator()
{
error = -1; //error values
quit = -2;
}

int stringManipulator::getTitleScreenInput(string newString)
{
int convertedNumber = error;

if (newString.size() > 1) // if more than one number is entered back to back, ex. "33"
{
return error;
}

for (unsigned int i = 0; i < newString.size(); i++) // test if player entered just numbers
{
if (newString[i] == ' ') // no spaces
{
return error;
}

if (newString[i] < '1' || newString[i] > '6') // only numbers 1 to 6 are used for the menu
{
return error;
}

}

// convert the string to an int
convertedNumber = convertToInt(newString);
return convertedNumber;
}

int stringManipulator::convertToInt(string newString)
{
int convertedNumber = error; //if user only presses enter through std::cin

for (unsigned int i = 0; i < newString.size(); i++) // test if player entered just numbers
{
if ((newString[i] == 'q' && newString.size() == 1) ||
(newString[i] == 'Q' && newString.size() == 1))
{
return quit;
}
if (newString[i] < '0' || newString[i] > '9' || newString[i] == ' ')
{
return error; //not a number entered
}

}

istringstream ss(newString); // convert the string guess into an int
ss >> convertedNumber;
return convertedNumber;

}

bool stringManipulator::isInitials(string newString)
{
if (newString.size() == 3) // if the string is 3 letters long
{
for (unsigned int i = 0; i < newString.size(); i++)
{
if (newString[i] >= '0' && newString[i] <= '9' || newString[i] == ' ') // if the string has numbers or a space
{
return false;
}
}
}
else // string is not 3 letters long
{
return false;
}
return true;
}











textFile.h

#ifndef textFile_h
#define textFile_h

#include <string>
#include <fstream>
#include "stringManipulator.h"

using std::string;
using std::ifstream;
using std::ofstream;

class textFile
{
public:
bool loadDefault(string fileName); // load the default high score file
bool checkFile(string fileName); // make sure the high score file is formatted correctly
bool writeToFile(string fileName, int newHighscores[], string newNames[]);
bool readNamesAndScores(string fileName, string newNames[], int newScores[]);
private:
ifstream outputHighscoreFile;
ofstream inputHighscoreFile;
stringManipulator textStringManipulator; // for converting strings to integers
};

#endif











textFile.cpp

#include "textFile.h"
#include <string>
#include <fstream>

using std::string;
using std::ofstream;
using std::ifstream;
using std::endl;

bool textFile::checkFile(string fileName)
{
outputHighscoreFile.open(fileName);

if (!outputHighscoreFile.is_open())
{
return false;
}

string line;
int i = 0;
while (!outputHighscoreFile.eof())
{
std::getline(outputHighscoreFile, line);
if (i % 2 != 0) // if an odd line (which holds the names) make sure it's not more than 3 letters long
{
if (line.size() > 3)
{
outputHighscoreFile.close();
return false;
}
}
if (i % 2 == 0) // if an even line make sure it's only numbers
{
for (unsigned int i = 0; i < line.size(); i++)
{
if (line[i] < '0' || line[i] > '9' || line[i] == ' ')
{
outputHighscoreFile.close();
return false;
}
}
}
else //if it's an odd line make sure it's only letters or symbols
{
for (unsigned int i = 0; i < line.size(); i++)
{
if (line[i] > '0' && line[i] < '9' || line[i] == ' ')
{
outputHighscoreFile.close();
return false;
}
}
}
i++;
}
outputHighscoreFile.close();
if (i == 20) //make sure the file is only 20 lines long
{
return true;
}
else
{
return false;
}

}

bool textFile::readNamesAndScores(string fileName, string newNames[], int newScores[])
{
outputHighscoreFile.open(fileName);

if (!outputHighscoreFile.is_open())
{
return false;
}


string line;
int intLine;
int i = 0;
int j = 0;
int counter = 0;
while (!outputHighscoreFile.eof())
{
std::getline(outputHighscoreFile, line);
if (counter % 2 == 0) //put even lines in the scores list once they're converted, odds in the names list
{
intLine = textStringManipulator.convertToInt(line);
newScores[i] = intLine;
i++;
}
else
{
newNames[j] = line;
j++;
}
counter++;
}
outputHighscoreFile.close();
return true;
}

bool textFile::writeToFile(string fileName, int newHighscores[], string newNames[])
{
inputHighscoreFile.open(fileName);

if (!inputHighscoreFile.is_open())
{
return false;
}

for (int i = 0; i < 10; i++)
{
if (i == 9) // on the last line in the file, don't add an /n
{
inputHighscoreFile << newHighscores[i] << endl << newNames[i];
}
else
{
inputHighscoreFile << newHighscores[i] << endl << newNames[i] << endl;
}
}

inputHighscoreFile.close();
return true;
}

bool textFile::loadDefault(string fileName)
{
inputHighscoreFile.open(fileName);

if (!inputHighscoreFile.is_open())
{
return false;
}

int defaultHighscores[10] = {4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
string defaultNames[10] = {"cat", "jon", "cga", "jtw", "ass", "dam", "lol", "sux", "dik", "dix"};

for (int i = 0; i < 10; i++)
{
if (i == 9) // on the last line in file, don't add an /n
{
inputHighscoreFile << defaultHighscores[i] << endl << defaultNames[i];
}
else
{
inputHighscoreFile << defaultHighscores[i] << endl << defaultNames[i] << endl;
}
}
inputHighscoreFile.close();
return true;
}











randomNumber.h

#ifndef randomNumber_h
#define randomNumber_h

class randomNumber
{
public:
void seed(); //set the seed to base the random numbers on
void generateNewNumber();
int getNumber();

private:
int number;
};

#endif











randomNumber.cpp

#include "randomNumber.h"
#include <ctime>
#include <cstdlib>


void randomNumber::generateNewNumber()
{
number = rand() % 100 + 1; // random number between 1 and 100
}

void randomNumber::seed()
{
srand(time(0));
}

int randomNumber::getNumber()
{
return number;
}











main.cpp

#include "game.h"

int main()
{
game theGame;

theGame.start();

return 0;
}











[Edited by - lightningblah on December 5, 2010 10:34:11 PM]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this