1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
|
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <ctime>
#include <cstdlib>
#include <cctype>
#include <boost/thread.hpp>
#include <boost/serialization/list.hpp>
//needed to conduct serialization
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
//needed to open and close files
using namespace std;
int points;
void question(const std::string& fname)
//this clears these values to 0 to ensure that the cypher is not disrupted
{
vector<string> lines;
ifstream file(fname);
//this inputs the file "fname" from which the text files holding the football teams, characters and countries will be loaded, as i had trouble loading files individually
if (!file) {
cout << "Cannot open file " << fname << '\n';
return;
//if the any of the files are not present in the folder then this is printed to show the user that something is wrong, and gives them an idea of how it can be fixed
}
for (string line; getline(file, line); lines.push_back(line));
const auto random_number{ rand() % lines.size() };
const auto word{ lines[random_number] };
const auto codes{ new int[word.length()] {} };
//these lines find and identify the lines within a text file so that the entire word is selected instead of just the first letter and the word can be mixed upand then changed into numbers at the next code block
for (size_t i = 0; i < word.length(); ++i)
if (isalpha(static_cast<unsigned char>(word[i]))) {
codes[i] = std::tolower(static_cast<unsigned char>(word[i])) - 'a' + 1;
cout << codes[i] << ' ';
//these lines change the identifed lines with the text file to the substitution cypher, changing each letter into the corresponding number in the alphabet
}
string answer;
cout << "\nPlease input your answer (no capitals, no spaces): ";
cin >> answer;
cout << word;
//this allows the user to input an answer, and after they have inputted an answer it will also show them the correct answer to see how far off they were(either completly wrong, or perhaps the wrong format)
if (answer == word) {
cout << "\nCorrect!\n\n";
points++;
//if the user gets the answer correct they are told as such and a point is added to their score
}
else cout << "\nIncorrect :(\n\n";
//if the answer is incorrect they are told and are able to continue and do not gain any points
}
struct Quiz {
string fname;
string title;
string catnum;
/**i used a struct to created the actual quiz part of the game, as this was simpler than using public and private classes
*the string fname is the text file containing the names
*the title file is the name of the category in the quiz, for the game to output and for it to not contain underscores
*the catnum is the number of the category, so that the game can tell the user what level they are on before it begins
*/
};
class scores {
int past, total;
public:
scores() {}
scores(int p, int t) :past(p), total(t) {}
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive& ar, const unsigned int version)
{
ar& past;
ar& total;
}
int getpoints() { return past; }
int gettotal() { return total; }
};
/** serialization used to contain the players best score and the total amount of points they have gathered
* code adapted from Mike Morgan (2017)
* the class of scores is used with the integer parameters best and total
* it uses a default constructor (L67)
* it also uses a bespoke constructor which indicates that the ints of "b" and "t" are the same as "best" and "total"
* L69 allows the values of best and total to be accessed through boost serialization
* the use of & on L73 and L74 allows the input and output of these integers instead of one way with << or >>
*/
int main()
{
std::list<int> data;
try
{
std::ifstream in("newcategory.txt");
boost::archive::text_iarchive ar(in);
ar >> data;
}
catch (std::exception& ex)
{
std::cerr << ex.what();
}
{
std::ofstream out("newcategory.txt");
boost::archive::text_oarchive ar(out);
ar << data;
}
/**
*a simple serialization output to the file for the new category
*it outputs to the file that is being created "newcategory.txt"
*/
const Quiz qz[]{ {"Premier_League_Teams.txt", "\nPremier League Football Teams!\n","first"},
{"Premier_League_Teams.txt", "\nPremier League Football Teams!\n", "second"},
{"Hobbit_Characters.txt", "\nHobbit Characters\n", "third"},
{"Hobbit_Characters.txt", "\nHobbit Characters\n", "fourth"},
{"South_American_Countries.txt", "\nSouth American Countries\n", "final"} };
//these lines of code identify the text files from the stored folder, and also output the name of the round, as well as its position in the queue using the strings above
srand(static_cast<unsigned int>(time(nullptr)));
//seeds the random number generator and ensures it is not affected by previous launching of the code
cout << "Richard Osman's house of Games: This round is in code.\n\n\n";
cout << "The objective of this round is to unscramble the coded word.\n";
cout << "You will be given the category as the clue\n";
cout << "and you have to type out what you believe the answer to be, with a capital letter\n\n";
//introductory text for the user to read
string Name;
cout << "But First, Enter your first name: ";
getline(cin, Name);
//this will allow the quiz to be personal to each player, displaying their name at key points and also their name next to their score.
cout << "\nWelcome contestant " << Name << ". Are you ready to begin the quiz?\n";
cout << "Please type yes to continue (case sensitive): ";
string respond;
cin >> respond;
if (respond != "yes") {
cout << "Maybe next time!\n";
return 0;
//this adds a degree of playability to the game, offering a quit game button, to increase immersion and the user experience
}
cout << "Good luck!\n";
for (const auto& quiz : qz) {
cout << "The " << quiz.catnum << " category is...\n" << quiz.title << '\n';
//this tells the user the number of the category we are on, and what the category is
question(quiz.fname);
//this loads the question from the quiz data structure
cout << Name << ", your score is " << points << " out of 5!\n";
//after each answer is submitted the user is told their current score out of the total amount of questions
std::list<scores> data;
try
{
std::ifstream in("scores.txt");
boost::archive::text_iarchive arch(in);
arch >> data;
}
catch (std::exception* ex)
{
std::cerr << ex->what();
}
for (auto i : data)
{
std::cout << i.getpoints() << " previous " << i.gettotal() << " total " << std::endl;
}
data.push_back(scores(45454, 454));
data.push_back(scores(1, 3));
{
std::ofstream out("scores.txt");
boost::archive::text_oarchive arch(out);
arch << data;
}
}
}
|