TripleX Final Version

This is my final version of the TripleX as per the lecture course. This was implemented with C++ classes, and added additional features as follows:

  • Minor text corrections

  • Application will not end when given invalid input and will simply ask for a valid input. This will repeat until the user exits the program via ctrl+C or gives a valid input

  • In case user types more than 3 inputs, the game will only check for three inputs and ignore anything else afterwards. This was done with the combination of std::cin.clear() and std::cin.ignore(std::numeric_limitsstd::streamsize::max(), ‘\n’) which reset std::cin to a working state and dropped everything inside the stream buffer

  • Changed Game Over behavior to restart on the same difficulty instead of doing over (as opposed to my earlier build). This now conforms to the lecture’s original game behavior. User also has the option to quit.

  • Added some text pauses to add some better pacing to the game text

  • RNG algorithm has been changed to “1 + (rand()%(iDifficulty+3))”. The range of values per difficulty are as follows:
    Difficulty 1 = 1 - 5
    Difficulty 2 = 1 - 6
    Difficulty 3 = 1 - 7
    Difficulty 4 = 1 - 8
    Difficulty 5 = 1 - 9

main.cpp

#include"Game.h"

int main()
{
    Game MyGame;
    return 0;
}

Game.h

#include"TextDisplay.h"
#include<ctime>

enum 
{
    DEF_DIFF = 1,
    MAX_DIFF = 5,
    ALLOW_RESTART_ON_SAME_DIFFICULTY = true
};

//handles the game loop
class Game
{
    public:
        Game();
        ~Game();

        //check GAMEDEFAULTS.h for defintions
        int CurDiff = DEF_DIFF;
        int MaxDiff = MAX_DIFF;
        int Code[3] = {0,0,0};
        bool GameLoop = true;
        bool isWon = false;
};


//handles the puzzle part of the game
class PreparePuzzle
{
    public:
        PreparePuzzle(int Difficulty);
        ~PreparePuzzle();

        int GetAnswer(int);
        int GetProd();
        int GetSum();

    private:
        //stores the answer code for the puzzle
        int Answer[3] = {0,0,0};
        int CurDiff = DEF_DIFF;
        
};

class PlayerInput
{
    public:
        PlayerInput();
        ~PlayerInput();

        int GetPlayerInput(int);
        int GetPlayerSum();
        int GetPlayerProd();

    private:
        int Input[3];
};

class CheckAnswer
{
    public:
        CheckAnswer(PreparePuzzle*, PlayerInput*);
        ~CheckAnswer();

        bool isSumEqual();
        bool isProdEqual();

    private:
        bool SumEqual = false;
        bool ProdEqual = false;
};

class CheckRestart
{
    public:
        CheckRestart();
        ~CheckRestart();

        bool isRestart();

    private:
        char Restart;
};

Game.cpp

#include"Game.h"

Game::Game()
{
    //initializes seed
    srand(time(NULL));

    //display opening text
    OpeningText     GameTextStart;

    while((this->GameLoop == true) && (this->isWon == false))
    {
        //Start the puzzle
        PreparePuzzle   GamePuzzle(this->CurDiff);
        //Display clues
        DisplaySum      GameTextSum(GamePuzzle.GetSum());
        DisplayProd     GameTextProd(GamePuzzle.GetProd());

        //display game difficulty
        DisplayDiff     GameTextDiff(CurDiff);

        //Ask for Player input
        DisplayPlayerPrompt GamePlayerPrompt;
        PlayerInput         GamePlayerInput;
        DisplayPlayerInput  GameTextInput(
                                            GamePlayerInput.GetPlayerInput(0),
                                            GamePlayerInput.GetPlayerInput(1),
                                            GamePlayerInput.GetPlayerInput(2)
                                            );
        //Display Player answer for comparison
        DisplayPlayerSum    GameTextPlayerSum(GamePlayerInput.GetPlayerSum());
        DisplayPlayerProd   GameTextPlayerProd(GamePlayerInput.GetPlayerProd());

        //Check answer
        CheckAnswer     GameCheck(&GamePuzzle, &GamePlayerInput);
        DisplayCheck    GammeTextCheck(GameCheck.isSumEqual(), GameCheck.isProdEqual());

        if(!(GameCheck.isSumEqual() && GameCheck.isProdEqual())) //wrong answer
        {
            DisplayGameOver GameOver;
            CheckRestart    GameRestart;

            //if player wants to restart
            if(GameRestart.isRestart() == true)
            {
                if(ALLOW_RESTART_ON_SAME_DIFFICULTY == false) //ALLOW_RESTART_ON_SAME_DIFFICULTY can be changed
                {
                    this->CurDiff = DEF_DIFF;
                }
                DisplayNextLevel GameNextLevel;
            }

            else //breaks the loop and ends the game
            {
                this->GameLoop = false;
                DisplayQuit GameQuit;
            }
        }
        else
        {
            //increments difficulty
            if(this->CurDiff < this->MaxDiff)
            {
                ++this->CurDiff;
                DisplayNextLevel GameNextLevel;
            }
            else //max difficulty reached
            {
                //breaks the loop
                DisplayWin  GameWin;
                DisplayQuit GameQuit;
                this->isWon = true;
            }
        }
    }
}

Game::~Game()
{

}

PreparePuzzle::PreparePuzzle(int iDifficulty)
{
    //prepare the answer
    int i = 0;
    for(i = 0; i < 3; i++)
    {
        this->Answer[i] = 1 + (rand()%(iDifficulty+3));
    }
}

PreparePuzzle::~PreparePuzzle()
{

}

int PreparePuzzle::GetAnswer(int iAnswer)
{
    int iReturn = 0;

    if(iAnswer < 3)
    {
        iReturn = this->Answer[iAnswer];
    }
    return iReturn;
}

int PreparePuzzle::GetProd()
{
    return this->Answer[0] * this->Answer[1] * this->Answer[2];
}

int PreparePuzzle::GetSum()
{
    return this->Answer[0] + this->Answer[1] + this->Answer[2];
}

PlayerInput::PlayerInput()
{
    std::cin.clear();
    std::cin>>this->Input[0]>>this->Input[1]>>this->Input[2];
    while(std::cin.fail())
    {
        std::cin.clear();
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        DisplayPlayerInputError GameDisplayInputError;
        std::cin>>this->Input[0]>>this->Input[1]>>this->Input[2];
    }
}

PlayerInput::~PlayerInput()
{

}

int PlayerInput::GetPlayerInput(int iInput)
{
    int iReturn = 0;
    if(iInput < 3)
    {
        iReturn = this->Input[iInput];
    }
    return iReturn;
}

int PlayerInput::GetPlayerSum()
{
    return this->Input[0] + this->Input[1] + this->Input[2];
}

int PlayerInput::GetPlayerProd()
{
    return this->Input[0] * this->Input[1] * this->Input[2];
}

CheckAnswer::CheckAnswer(PreparePuzzle* ppPuzzle, PlayerInput* piInput)
{
    if(ppPuzzle->GetSum() == piInput->GetPlayerSum())
    {
        this->SumEqual = true;
    }

    if(ppPuzzle->GetProd() == piInput->GetPlayerProd())
    {
        this->ProdEqual = true;
    }
}

CheckAnswer::~CheckAnswer()
{

}

bool CheckAnswer::isSumEqual()
{
    return this->SumEqual;
}

bool CheckAnswer::isProdEqual()
{
    return this->ProdEqual;
}

CheckRestart::CheckRestart()
{
    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    this->Restart = std::cin.get();    
}

CheckRestart::~CheckRestart()
{
    
}

bool CheckRestart::isRestart()
{
    bool willRestart = false;
    if((this->Restart == 'y') || (this->Restart == 'Y'))
    {
        willRestart = true;
    }
    return willRestart;
}

TextDisplay.h

#include<iostream>

//displays opening text
class OpeningText
{
    public:    
        OpeningText();
        ~OpeningText();
        
};

//displays the difficulty, called by Game class
class DisplayDiff
{
    public:
        DisplayDiff(int);
        ~DisplayDiff();
};

//Displays the sum of the codes in PreparePuzzle class
class DisplaySum
{
    public:
        DisplaySum(int);
        ~DisplaySum();
};

//Displays the product of the codes in PreparePuzzle class
class DisplayProd
{
    public:
        DisplayProd(int);
        ~DisplayProd();
};

class DisplayPlayerPrompt
{
    public:
        DisplayPlayerPrompt();
        ~DisplayPlayerPrompt();
};

class DisplayPlayerInput
{
    public:
        DisplayPlayerInput(int,int,int);
        ~DisplayPlayerInput();
};

class DisplayPlayerInputError
{
    public:
        DisplayPlayerInputError();
        ~DisplayPlayerInputError();

};

class DisplayPlayerSum
{
    public:
        DisplayPlayerSum(int);
        ~DisplayPlayerSum();
};

class DisplayPlayerProd
{
    public:
        DisplayPlayerProd(int);
        ~DisplayPlayerProd();
};

class DisplayCheck
{
    public:
        DisplayCheck(bool, bool);
        ~DisplayCheck();
};

class DisplayNextLevel
{
    public:
        DisplayNextLevel();
        ~DisplayNextLevel();
};

class DisplayGameOver
{
    public:
        DisplayGameOver();
        ~DisplayGameOver();
};

class DisplayWin
{
    public:
        DisplayWin();
        ~DisplayWin();
};

class DisplayQuit
{
    public:
        DisplayQuit();
        ~DisplayQuit();

};

TextDisplay.cpp

#include"TextDisplay.h"

void ASCIIArt()
{
    std::cout<<"\n ____________________________________________\n";
    std::cout<<"|____________________________________________|\n";
    std::cout<<"|__||  ||___||  |_|___|___|__|  ||___||  ||__|\n";
    std::cout<<"||__|  |__|__|  |___|___|___||  |__|__|  |__||\n";
    std::cout<<"|__||  ||___||  |_|___|___|__|  ||___||  ||__|\n";
    std::cout<<"||__|  |__|__|  |    || |    |  |__|__|  |__||\n";
    std::cout<<"|__||  ||___||  |    || |    |  ||___||  ||__|\n";
    std::cout<<"||__|  |__|__|  |    || |    |  |__|__|  |__||\n";
    std::cout<<"|__||  ||___||  | ScS|| |    |  ||___||  ||__|\n";
    std::cout<<"||__|  |__|__|  |    || |    |  |__|__|  |__||\n";
    std::cout<<"|__||  ||___||  |   O|| |O   |  ||___||  ||__|\n";
    std::cout<<"||__|  |__|__|  |    || |    |  |__|__|  |__||\n";
    std::cout<<"|__||  ||___||  |    || |    |  ||___||  ||__|\n";
    std::cout<<"||__|  |__|__|__|____||_|____|  |__|__|  |__||\n";
    std::cout<<"|LLL|  |LLLLL|______________||  |LLLLL|  |LLL|\n";
    std::cout<<"|LLL|  |LLL|______________|  |  |LLLLL|  |LLL|\n";
    std::cout<<"|LLL|__|L|______________|____|__|LLLLL|__|LLL|\n\n\n";
}

OpeningText::OpeningText()
{
    ASCIIArt();
    std::cout<<"You are an agent of the Coalition. \n"; 
    std::cout<<"You need to break into a high-security vault and get the important documents inside. \n";
    std::cout<<"The vault stands before you, protected by an electronic lock. \n\n"; 
    std::cout<<"You need to enter the access codes to continue. \n";
    std::cout<<"Your multitool tells you that the code is composed of three numbers \n\n";
}

OpeningText::~OpeningText()
{

}

DisplayDiff::DisplayDiff(int iDiff)
{
    std::cout<<"The current mission difficulty is "<<iDiff<<". \n\n";
}

DisplayDiff::~DisplayDiff()
{

}

DisplaySum::DisplaySum(int iSum)
{
    std::cout<<"The sum of those three access codes is "<<iSum<<". \n";
}

DisplaySum::~DisplaySum()
{

}

DisplayProd::DisplayProd(int iProd)
{
    std::cout<<"The product of those three access codes is "<<iProd<<". \n";
}

DisplayProd::~DisplayProd()
{

}

DisplayPlayerPrompt::DisplayPlayerPrompt()
{
    std::cout<<std::endl<<"Please enter the access codes. The three numbers should be seperated by a space \n";
}

DisplayPlayerPrompt::~DisplayPlayerPrompt()
{

}

DisplayPlayerInput::DisplayPlayerInput(int iInput1, int iInput2, int iInput3)
{
    std::cout<<std::endl<<"You have entered "<<iInput1<<" "<<iInput2<<" "<<iInput3<<std::endl;
}

DisplayPlayerInput::~DisplayPlayerInput()
{

}

DisplayPlayerInputError::DisplayPlayerInputError()
{
    std::cout<<"\nYou have entered an invalid value! Please try again.\n";
    std::cout<<"Please enter the access codes. The three numbers should be seperated by a space \n";
}

DisplayPlayerInputError::~DisplayPlayerInputError()
{

}

DisplayPlayerSum::DisplayPlayerSum(int iSum)
{
    std::cout<<std::endl<<"The sum of your input is "<<iSum;
}

DisplayPlayerSum::~DisplayPlayerSum()
{

}

DisplayPlayerProd::DisplayPlayerProd(int iProd)
{
    std::cout<<std::endl<<"The product of your input is "<<iProd;
}

DisplayPlayerProd::~DisplayPlayerProd()
{

}

DisplayCheck::DisplayCheck(bool isSumEqual, bool isProdEqual)
{
    if(isSumEqual == true)
    {
        std::cout<<std::endl<<"Your input matches the sum of the access codes.";
    }
    else
    {
        std::cout<<std::endl<<"Your input does not match the sum of the access codes.";
    }

    if(isProdEqual == true)
    {
        std::cout<<std::endl<<"Your input matches the product of the access codes.";
    }
    else
    {
        std::cout<<std::endl<<"Your input does not match the product as the access codes.";
    }

    if(isProdEqual && isSumEqual)
    {
        std::cout<<std::endl<<std::endl<<"The vault opens and you quickly make off with the documents. This is sure to get you a promotion! \n";
    }
    else
    {
        std::cout<<std::endl<<std::endl<<"Sorry, but you lose! The alarms were triggered! \n";
        std::cout<<"You quickly made a swift exit before the security outfit spots you. \n";
        std::cout<<"You arrive at your headquarters and was sternly reprimanded by your superior. \n";
        std::cout<<"I guess that promotion is out of reach now. \n";
    }
}

DisplayCheck::~DisplayCheck()
{

}

DisplayNextLevel::DisplayNextLevel()
{
    std::cout<<std::endl<<"Upon arriving back at your headquarters a new assignment is waiting for you. ";
    std::cout<<"I guess you have another chance at that promotion.\n\n";
    std::cout<<"Press any key and then enter to continue.\n\n";

    //pauses the text
    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    std::cin.get();
    std::cout<<"You need to break into another high-security vault and get the important documents inside. ";
    std::cout<<"You rush to your next assignment and see another vault standing before you, protected by an electronic lock. \n\n"; 
    std::cout<<"You need to enter the access codes to continue. \n";
    std::cout<<"Your multitool tells you that the code is composed of three numbers \n\n";
}

DisplayNextLevel::~DisplayNextLevel()
{

}

DisplayWin::DisplayWin()
{
    std::cout<<"\n\nYour superior hears of your incredible exploits and decides to finally give you that promotion!\n";
    std::cout<<"He congratulates you with a smile, and hopes to see more success from you in the future.\n";
}

DisplayWin::~DisplayWin()
{

}

DisplayGameOver::DisplayGameOver()
{
    std::cout<<"\n\nWould you like to restart? Press Y to restart and any other key to quit.\n\n";
}

DisplayGameOver::~DisplayGameOver()
{

}

DisplayQuit::DisplayQuit()
{
    std::cout<<"\n\"Well that was a tough day's work\", you say to yourself.\n";
    std::cout<<"\nYou decide you've done enough and hang your coat and hat and retire for the day.\n\n";
}

DisplayQuit::~DisplayQuit()
{

}


As I have mentioned in my prior posts, this code was done in conjunction with other lesson materials and there are concepts implemented here that is out of scope of the lecture.

For future reference (lest I forget), my build script is as follows

@echo off
del /Q *.obj
del /Q .*exe
cl /O2 /EHsc main.cpp game.cpp TextDisplay.cpp 

Privacy & Terms