Sunday, November 26, 2017

Programming Challenge 13.19 - Trivia Game

Example Files: TriviaGame.7z

Question.h


#ifndef QUESTION_H_
#define QUESTION_H_

#include <string>
using std::string;

#include <array>
using std::array;

#include <vector>
using std::vector;

class Questions
{
    private:   
        vector<string> questions;
        vector<string> answers;

        bool isCorrect;

    public:
        Questions()
        {
        }

        void setQuestions(string qTemp)
        { questions.push_back(qTemp); }

        void setAnswers(vector<string> aTemp)
        { answers = aTemp; }

        void displayQuestion(int);
        void displayAnswers();
        void evaluateAnswer(int, int);

        bool getCorrect() const
        { return isCorrect; }
};

#endif

Question.cpp


#include "Question.h"

#include <iostream>
using std::cout;

/* **********************************************************
            Questions::displayQuestion() : int
    This function accepts an integer as argument. The question
    to be output is determined by the integer value passed to
    it as index.
    ********************************************************** */

void Questions::displayQuestion(int qNum)
{
    cout << "Question: " << questions[qNum] << "\n\n";
}

/* **********************************************************
            Questions::displayAnswers()
    This function outputs the trivia answers.
    ********************************************************** */

void Questions::displayAnswers()
{
    int cntA = 1;

    for (auto answer : answers)
    {
        cout << "Answer " << (cntA++) << ": " << answer << "\n";
    }
}

/* **********************************************************
            Questions::evaluateAnswers() : int, int
    This function accepts two integer values as argument. It
    evaluates the answer, held by the uAnswer variable, and
    compares these to the vector holding the correct answers.
    ********************************************************** */

void Questions::evaluateAnswer(int uAnswer, int qNum)
{
    const vector<int> correctAnswers{ 0, 3, 1, 2, 1, 2, 2, 0, 1, 2 };

    if (uAnswer-1 == correctAnswers[qNum])
    {
        isCorrect = true;
        cout << "\nCORRECT!\n\n\n";
    }
    else
    {
        cout << "\nWRONG!\n";
        cout << "The correct answer is " << (correctAnswers[qNum] + 1) << ": "
              << (answers[correctAnswers[qNum]]) << "\n\n\n";
    }   
}

Player.h


#ifndef PLAYER_H_
#define PLAYER_H_

#include <string>
using std::string;

class Player
{
    private:
        string playerName;        // Holds a players name
        int     score;                // Holds a players score

    public:   
        Player() : playerName(""), score(0)
        {}

        void setPlayerName();
        bool isPlayerName(string, int);

        void setScore()
        { ++score; }

        string getPlayerName() const
        { return playerName; }

        int getScore() const
        { return score; }
};

#endif

Player.cpp


#include "Player.h"

#include <iostream>
using std::cin;
using std::cout;

/* **********************************************************
            Player::setPlayerName()
    This function asks the player to enter his or her name.
    The input is validated.
    ********************************************************** */

void Player::setPlayerName()
{
    static int playerNum = 1;
    string      tempName = "";
   
    cout << "Please enter your name, Player " << playerNum << ": ";
    getline(cin, tempName);

    while (isPlayerName(tempName, playerNum) == false)
    {
        getline(cin, tempName);
    }

    ++playerNum;
}

/* **********************************************************
            Player::isPlayerName()
    This function validates the players input.
    ********************************************************** */

bool Player::isPlayerName(string tempName, int playerNum)
{
    if (tempName.empty() || tempName.at(0) == ' ')
    {
        cout << "Please enter your name Player " << (playerNum) << ": ";
        return false;
    }
    else
    {
        playerName = tempName;
        return true;
    }
}

Game.h


#ifndef GAME_H_
#define GAME_H_

#include "Player.h"
#include "Question.h"

#include <vector>
using std::vector;

class Game
{
    private:
        static constexpr int NUM_QUESTIONS = 10;
        static constexpr int NUM_PLAYERS = 2;

        int numCorrect;
        int playerNum;

        vector<Questions> trivia;
        vector<Player> player;

    public:
        Game() : trivia(NUM_QUESTIONS), player(NUM_PLAYERS)
        {
            loadQuestions();
            loadAnswers();
        }

        void setupPlayers();
        void loadQuestions();
        void loadAnswers();
        void play();
        void switchPlayers(int);
        bool isValidInput(int);
        void displayScore();
        void announceWinner();
       
        int getPlayerNum() const
        { return playerNum; }
};

#endif

Game.cpp


#include "Game.h"

#include <iomanip>
using std::left;
using std::right;
using std::setw;

#include <iostream>
using std::cin;
using std::cout;

#include <limits>
using std::numeric_limits;
using std::streamsize;

#include <fstream>
using std::fstream;
using std::ios;

/* **********************************************************
            Game::loadQuestions()
    This function reads the trivia questions from a text file
    into a temporary string object. The contents is passed to
    a function of the Question class.
    ********************************************************** */

void Game::loadQuestions()
{
    string tempQ = "";

    fstream readQuestions("triviaQ.txt", ios::in);

    if (readQuestions.fail() == false)
    {
        while (getline(readQuestions, tempQ))
        {
            for (int i = 0; i < trivia.size(); ++i)
            {
                trivia[i].setQuestions(tempQ);
            }
        }
        readQuestions.close();
    }
    else
    {
        cout << "File processing error ... Please close the program and try again.\n";
    }
}

/* **********************************************************
            Game::loadAnswers()
    This function reads the trivia answers from a text file,
    and passes these to a temporary vector. The contents of
    is then passed to a function of the Question class.
    ********************************************************** */

void Game::loadAnswers()
{
    vector<string> tempA(4);

    fstream readAnswers("triviaA.txt", ios::in);

    if (readAnswers.fail() == false)
    {
        for (int i = 0; i < trivia.size(); ++i)
        {
            for (int j = 0; j < tempA.size(); ++j)
            {
                getline(readAnswers, tempA[j], ',');
            }
            trivia[i].setAnswers(tempA);
        }
        readAnswers.close();
    }
    else
    {
        cout << "File processing error ... Please close the program and try again.\n";
    }
}

/* **********************************************************
            Game::setupPlayers()
    This function makes a call to the Player class, to set the
    player names.
    ********************************************************** */

void Game::setupPlayers()
{
    for (int i = 0; i < NUM_PLAYERS; ++i)
    {
        player[i].setPlayerName();
    }
}

/* **********************************************************
            Game::play()
    This function allows each player in turn to answer five
    trivia questions. I outputs a question and four answers,
    then asks the player to indicate his answer, by entering
    a numeric value in the range of 1-4. If it is correct, the
    players' score counter will increase by a value of 1.
   ********************************************************** */

void Game::play()
{
    int answer = 0;

    for (int i = 0; i < trivia.size(); ++i)
    {
        switchPlayers(i);

        trivia[i].displayQuestion(i);
        trivia[i].displayAnswers();

        cout << "Your answer (1-4): ";
        cin >> answer;

        while (isValidInput(answer) == false)
        {
            cout << "Your answer (1-4): ";
            cin >> answer;
        }

        trivia[i].evaluateAnswer(answer, i);

        if (trivia[i].getCorrect() == true)
        {
            player[getPlayerNum()].setScore();
        }
    }
}

/* **********************************************************
            Game::switchPlayers() : int
    This function accepts an integer value as argument. If the
    value is 0, player ones turn is announced. If the value is
    half the size of available trivia-questions, the players
    are switched, and the next players' turn is announced.
   ********************************************************** */

void Game::switchPlayers(int qNum)
{
    if (qNum == 0)
    {
        cout << "\n\nYour Turn " << player[getPlayerNum()].getPlayerName() << "\n\n";
    }
  
    if (qNum == trivia.size() / 2)
    {
        ++playerNum %= NUM_PLAYERS;
        cout << "\nYour Turn " << player[getPlayerNum()].getPlayerName() << "\n\n";
    }
}

/* **********************************************************
            Game::isvalidInput() : int
    This function accepts an integer as argument. It validates
    the players' input. If it is outside bounds, or of any
    other type than integer, the function returns false, else
    true is returned.
   ********************************************************** */

bool Game::isValidInput(int answer)
{
    if (answer < 1 || answer > 4)
    {
        cin.clear();
        cin.ignore(numeric_limits<streamsize>::max(), '\n');

        return false;
    }
    else
    {
        return true;
    }

    return false;
}

/* **********************************************************
            Game::displayScore()
    This function outputs the players' names and their score.
   ********************************************************** */

void Game::displayScore()
{
    cout << "\nPlayer Name" << setw(25) << "Score\n\n";

    for (int i = 0; i < NUM_PLAYERS; ++i)
    {  
       cout << setw(15) << left << player[i].getPlayerName()
              << setw(19) << right << player[i].getScore() << "\n";
    }

}

/* **********************************************************
            Game::displayScore()
    This function outputs a congratulatory message, declaring
    the player with the highest score the winner. If both
    players have the same score, both are announced winner.
   ********************************************************** */

void Game::announceWinner()
{
    playerNum = 0;

    if (player[getPlayerNum()].getScore() > player[getPlayerNum() + 1].getScore())
    {
        cout << "\nCongratulations, ";
        cout << player[getPlayerNum()].getPlayerName() << "!\n\n";
        cout << "You are the winner of our $10.000 prize!\n\n";
    }
    else if (player[getPlayerNum() + 1].getScore() > player[getPlayerNum()].getScore())
    {
        cout << "\nCongratulations, ";
        cout << player[getPlayerNum() + 1].getPlayerName() << "!\n";
        cout << "You are the winner of $10.000!\n\n";
    }

    if (player[getPlayerNum()].getScore() == player[getPlayerNum() + 1].getScore())
    {
        cout << "\nWe have a tie! Both ";
        cout << player[getPlayerNum()].getPlayerName() << " and "
              << player[getPlayerNum() + 1].getPlayerName() << " win $2.000!\n\n";
    }
}

TriviaGame.cpp


#include "Game.h"

#include <iostream>
using std::cout;

int main()
{
    Game game;

    cout << "WELCOME TO TRIVIA WORLD!\n\n";

    game.setupPlayers();
    game.play();
    game.displayScore();
    game.announceWinner();

    cout << "This concludes todays quiz!\n"
         << "Don't forget to tune in for another round of TRIVIA WORLD!\n\n";

    return 0;
}


Example Output:







No comments:

Post a Comment