Algorithms_in_C++ 1.0.0
Set of algorithms implemented in C++.
Loading...
Searching...
No Matches
memory_game.cpp File Reference

A simple Memory Game with 3 different sizes and multiple letters. More...

#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <random>
#include <vector>
#include <unistd.h>
Include dependency graph for memory_game.cpp:

Functions

template<typename T >
constexpr T SLEEP (T seconds)
 for sleep()
 
template<typename T >
bool games::memory_game::is_number (const T &input)
 Utility function to verify if the given input is a number or not. This is very useful to prevent the program being stuck in a loop.
 
template<typename T >
void games::memory_game::init (std::vector< T > *table)
 Initializes the table with the letters.
 
template<typename T >
void games::memory_game::print_table (const std::vector< T > &table)
 Utility function to print the table.
 
template<typename T >
void games::memory_game::reset_data (const std::vector< T > &table, int *answer, int *old_answer, int *memory_count)
 Utility function that resets the data if the user enters an invalid value.
 
template<typename T >
void games::memory_game::ask_data (const std::vector< T > &table, int *answer, int *old_answer, int *memory_count)
 Function that asks the user for their input in the table they previously chose.
 
template<typename T >
bool games::memory_game::match (const std::vector< T > &table, std::vector< T > *table_empty, const int &answer, bool *first_time, int *old_answer, int *memory_count)
 Checks if the two values given by the user match.
 
template<typename T >
void games::memory_game::assign_results (std::vector< T > *table_empty, std::vector< T > *table, int *answer, bool *first_time, int *old_answer, int *memory_count)
 Function to assign the results to the table.
 
int main ()
 Main function.
 

Detailed Description

A simple Memory Game with 3 different sizes and multiple letters.

The game consists on finding the pair of all the given letters depending on the table size. Once all of the instances are all found, the game will end and will ask you if you'd like to play again or not.

It provides 3 different sizes available that the user can choose (4x2, 5x2, 7x2). 7x2 being the biggest table size and hardest mode. The bigger the size, the more letters are available.

Author
David Leal

Function Documentation

◆ ask_data()

template<typename T >
void games::memory_game::ask_data ( const std::vector< T > & table,
int * answer,
int * old_answer,
int * memory_count )

Function that asks the user for their input in the table they previously chose.

Template Parameters
TThe type of the table.
Parameters
tableThe table that's used to get the user's input and data.
answerThe user's answer.
old_answerThe user's previous answer.
memory_countA counter to check if the user has already answered two values.
Returns
void
162 {
163 (*old_answer) = (*answer);
164 print_table(table);
165
166 std::cout << "\n\nType your response here (number index):\n";
167 std::cin >> (*answer);
168
169 if (!is_number((*answer))) {
170 std::cout << "\nYou must enter a valid number.\n\n";
171 reset_data(table, answer, old_answer, memory_count);
172 }
173
174 // Increase the memory count, which will be later on used for checking if
175 // the user has already answered two values.
176 (*memory_count)++;
177
178 if (((*answer) > table.size()) || ((*answer) < 1)) {
179 std::cout << "\nYou can't check a value that doesn't exist (or an "
180 "invalid number).\n\n";
181 reset_data(table, answer, old_answer, memory_count);
182 }
183
184 if ((*old_answer) == (*answer)) {
185 std::cout << "\nYou can't check the same value twice.\n\n";
186 reset_data(table, answer, old_answer, memory_count);
187 }
188
189 // If two matches are answered already, but the user checkes a non-answered
190 // and an answered value, the program will mark it as no match, however, we
191 // must not allow the user to check the same value twice.
192 if ((table[(*answer) - 1] != 0) &&
193 ((table[(*old_answer)] == 0) || (table[(*old_answer)] != 0))) {
194 std::cout << "\nYou can't check the same value twice.\n\n";
195 reset_data(table, answer, old_answer, memory_count);
196 }
197}
bool is_number(const T &input)
Utility function to verify if the given input is a number or not. This is very useful to prevent the ...
Definition memory_game.cpp:62
void print_table(const std::vector< T > &table)
Utility function to print the table.
Definition memory_game.cpp:123
void reset_data(const std::vector< T > &, int *, int *, int *)
Utility function that resets the data if the user enters an invalid value.
Definition memory_game.cpp:211
Here is the call graph for this function:

◆ assign_results()

template<typename T >
void games::memory_game::assign_results ( std::vector< T > * table_empty,
std::vector< T > * table,
int * answer,
bool * first_time,
int * old_answer,
int * memory_count )

Function to assign the results to the table.

Also checkes if the user has answered all the values already, as well as verify if the user made a match or not.

Template Parameters
TThe type of the tables.
Parameters
table_emptyThe table with no values, slowly assigned from table depending on the user's input.
tableThe table with the original values.
answerThe user's answer.
first_timeA boolean to check if the user has already answered a value.
old_answerThe user's previous answer.
memory_countA counter to check if the user has already answered two values.
Returns
void
291 {
292 // Search through the entire table and if the answer matches the index, show
293 // the value. If it doesn't match, hide both the values. Don't forget to
294 // keep older values already answered.
295 for (int i = 0; i < (*table).size() + 1; i++) {
296 if (i == (*answer)) {
297 if (match((*table), table_empty, (*answer), first_time, old_answer,
298 memory_count) == true) {
299 (*table_empty)[i - 1] = (*table)[i - 1];
300 (*first_time) = true;
301 }
302 }
303 }
304
305 if ((*memory_count) == 1) {
306 (*first_time) = false;
307 (*memory_count) = 0;
308 }
309
310 char try_again = 'n';
311
312 // Has the user finished the game? Use a `for` loop, and if the table is
313 // full, ask the user if he wants to play again.
314 for (int i = 0; i < (*table).size() + 1; i++) {
315 if ((*table_empty)[i] == 0) {
316 break;
317 } else if (i == (*table).size() - 1) {
318 print_table((*table));
319
320 std::cout << "\n\nYou won. Congratulations! Do you want to play "
321 "again? (y/n)\n";
323 << "Size " << (*table).size()
324 << " will be used. This can be changed by re-running the game.";
325 std::cin >> try_again;
326 if (try_again == 'y') {
327 // This is needed when checking if the user has two matches
328 // already.
329 for (int i = 0; i < (*table_empty).size(); i++) {
330 (*table_empty)[i] = 0;
331 }
332
333 init(table);
334 } else if (try_again == 'n') {
335 std::cout << "\nThanks for playing the game!\n";
336 SLEEP(3);
337
338 exit(0);
339 } else {
340 std::cout << "\nInvalid input (exitting...).\n";
341 SLEEP(3);
342
343 exit(0);
344 }
345 }
346 }
347
348 // Ask data again.
349 ask_data((*table_empty), answer, old_answer, memory_count);
350 assign_results(table_empty, table, answer, first_time, old_answer,
351 memory_count);
352}
T exit(T... args)
bool match(const std::vector< T > &table, std::vector< T > *table_empty, const int &answer, bool *first_time, int *old_answer, int *memory_count)
Checks if the two values given by the user match.
Definition memory_game.cpp:235
void assign_results(std::vector< T > *table_empty, std::vector< T > *table, int *answer, bool *first_time, int *old_answer, int *memory_count)
Function to assign the results to the table.
Definition memory_game.cpp:289
void ask_data(const std::vector< T > &table, int *answer, int *old_answer, int *memory_count)
Function that asks the user for their input in the table they previously chose.
Definition memory_game.cpp:161
constexpr T SLEEP(T seconds)
for sleep()
Definition memory_game.cpp:36
void init(std::vector< T > *table)
Initializes the table with the letters.
Definition memory_game.cpp:80
Here is the call graph for this function:

◆ init()

template<typename T >
void games::memory_game::init ( std::vector< T > * table)

Initializes the table with the letters.

Template Parameters
TThe type of the table.
Parameters
tableThe table to initialize.
Returns
void
80 {
81 std::vector<char> letters(7);
82
83 // Decrease / increase the number of letters depending on the size.
84 if ((*table).size() == 10) { // 5x2
85 letters = {'A', 'E', 'Z', 'P', 'D'};
86 } else if ((*table).size() == 8) { // 4x2
87 letters = {'A', 'E', 'Z', 'D'};
88 } else if ((*table).size() == 14) { // 7x2
89 letters = {'A', 'E', 'Z', 'P', 'D', 'B', 'M'};
90 }
91
93 for (char letter : letters) {
94 pairs.push_back(letter);
95 pairs.push_back(letter);
96 }
97
98 std::shuffle(pairs.begin(), pairs.end(),
100
101 for (int i = 0; i < (*table).size(); i++) {
102 (*table)[i] = pairs[i];
103 }
104
105 std::cout << "All available types are: ";
106
107 for (int i = 0; i < letters.size(); i++) {
108 if (i == letters.size() - 1) {
109 std::cout << "and " << letters[i] << ".\n\n";
110 } else {
111 std::cout << letters[i] << ", ";
112 }
113 }
114}
T begin(T... args)
T end(T... args)
T push_back(T... args)
T shuffle(T... args)
Here is the call graph for this function:

◆ is_number()

template<typename T >
bool games::memory_game::is_number ( const T & input)

Utility function to verify if the given input is a number or not. This is very useful to prevent the program being stuck in a loop.

Template Parameters
TThe type of the input
Parameters
inputThe input to check.
Returns
false if the input IS empty or if it contains a non-digit character
true if the input is NOT empty and if it contains only digit characters
62 {
63 if (std::cin.fail()) {
64 std::cin.clear();
65 std::cin.ignore(256, '\n');
66
67 return false;
68 }
69
70 return true;
71}
Here is the call graph for this function:

◆ main()

int main ( void )

Main function.

Returns
0 on exit

< Size of the table.

< Selection of the size (4x2, 5x2, 7x2).

< The answer (number index) that the user chose.

< Previous answer (number index).

< Counter to check if the user has already answered two values.

< Whether the user has answered 1 value or not (previous answered values do not count).

360 {
361 // Start randomizer. This changes the values every time.
362 std::srand(std::time(nullptr));
363
364 int size = 0; ///< Size of the table.
365 int selection = 0; ///< Selection of the size (4x2, 5x2, 7x2).
366
367 int response = 0; ///< The answer (number index) that the user chose.
368 int old_answer = 0; ///< Previous answer (number index).
369
370 int memory_count =
371 0; ///< Counter to check if the user has already answered two values.
372 bool first_time = true; ///< Whether the user has answered 1 value or not
373 ///< (previous answered values do not count).
374
375 std::cout << "\tMEMORY GAME\n";
376
377 do {
378 std::cout << "\n1. 4x2 (1)";
379 std::cout << "\n2. 5x2 (2)";
380 std::cout << "\n3. 7x2 (3)\n";
381
382 std::cout << "\nChoose table size: ";
383 std::cin >> selection;
384 } while ((selection < 1 || selection > 3) &&
385 (!games::memory_game::is_number(selection)));
386
387 switch (selection) {
388 case 1:
389 size = 8;
390 break;
391 case 2:
392 size = 10;
393 break;
394 case 3:
395 size = 14;
396 break;
397 default:
398 size = 10;
399 break;
400 }
401
402 std::vector<char> table(size);
403 std::vector<char> table_empty(size);
404
405 std::cout << "\n";
406
408 games::memory_game::ask_data(table_empty, &response, &old_answer,
409 &memory_count);
410 games::memory_game::assign_results(&table_empty, &table, &response,
411 &first_time, &old_answer, &memory_count);
412
413 return 0;
414}
T srand(T... args)
T time(T... args)
Here is the call graph for this function:

◆ match()

template<typename T >
bool games::memory_game::match ( const std::vector< T > & table,
std::vector< T > * table_empty,
const int & answer,
bool * first_time,
int * old_answer,
int * memory_count )

Checks if the two values given by the user match.

Template Parameters
TThe type of the table.
Parameters
table_emptyThe table with no values, slowly assigned from table depending on the user's input.
tableThe table with the original values.
answerThe user's answer.
first_timeA boolean to check if the user has already answered a value.
old_answerThe user's previous answer.
memory_countA counter to check if the user has already answered two values.
Returns
true IF the values given by the user match
false if the values given by the user do NOT match
237 {
238 if ((*first_time) == true) {
239 return true;
240 }
241
242 // Search across the whole table and if the two values match, keep results,
243 // otherwise, hide 'em up.
244 for (int i = 0; i < table.size() + 1; i++) {
245 if (i == answer) {
246 if (table[i - 1] == table[(*old_answer) - 1]) {
247 (*first_time) = true;
248 (*memory_count) = 0;
249
250 (*old_answer) = 0;
251 return true;
252 } else {
253 std::cout << "\nNo match (value was " << table[i - 1]
254 << ", index is " << i << ").\n\n";
255
256 (*table_empty)[(*old_answer) - 1] = 0;
257 (*table_empty)[answer - 1] = 0;
258
259 (*first_time) = true;
260 (*memory_count) = 0;
261
262 (*old_answer) = 0;
263 return false;
264 }
265 }
266 }
267
268 return false;
269}
Here is the call graph for this function:

◆ print_table()

template<typename T >
void games::memory_game::print_table ( const std::vector< T > & table)

Utility function to print the table.

Template Parameters
TThe type of the table.
Parameters
tableThe table to print.
Returns
void
123 {
124 std::cout << "| ";
125 std::vector<T> table_print(table.size());
126
127 for (int i = 0; i < table.size(); i++) {
128 table_print[i] = ' ';
129
130 if (table[i] != 0) {
131 table_print[i] = table[i];
132 }
133 }
134
135 for (int i = 0; i < table.size(); i++) {
136 if (i % 5 == 0 && i != 0) {
137 std::cout << "\n| ";
138 }
139
140 std::cout << table_print[i] << " | ";
141 }
142}
Here is the call graph for this function:

◆ reset_data()

template<typename T >
void games::memory_game::reset_data ( const std::vector< T > & table,
int * answer,
int * old_answer,
int * memory_count )

Utility function that resets the data if the user enters an invalid value.

Template Parameters
TThe type of the table.
Parameters
tableThe table that will be used to call ask_data().
answerThe user's answer.
old_answerThe user's previous answer.
memory_countA counter to check if the user has already answered two values.
Returns
void
212 {
213 (*answer) = (*old_answer);
214 (*memory_count)--;
215
216 ask_data(table, answer, old_answer, memory_count);
217}
Here is the call graph for this function:

◆ SLEEP()

template<typename T >
constexpr T SLEEP ( T seconds)
constexpr

for sleep()

for std::shuffle() for std::srand() for std::time() for IO operations for std::mt19937 for std::vector

36 {
37 return sleep(seconds);
38}