mirror of
https://github.com/TheAlgorithms/C-Plus-Plus.git
synced 2026-05-08 15:14:01 +08:00
clang-format and clang-tidy fixes for 8cd0a772
This commit is contained in:
@@ -1,23 +1,26 @@
|
||||
/**
|
||||
* @file
|
||||
* @file
|
||||
* @brief A simple [Memory Game](https://en.wikipedia.org/wiki/Matching_game)
|
||||
* with **3 different sizes** and multiple letters.
|
||||
* @details
|
||||
* 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.
|
||||
* 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**.
|
||||
* 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](https://github.com/Panquesito7)
|
||||
*/
|
||||
|
||||
#include <iostream> /// for IO operations
|
||||
#include <ctime> /// for std::time()
|
||||
#include <cstdlib> /// for std::srand()
|
||||
#include <vector> /// for std::vector
|
||||
#include <algorithm> /// for std::shuffle()
|
||||
#include <random> /// for std::mt19937
|
||||
#include <algorithm> /// for std::shuffle()
|
||||
#include <cstdlib> /// for std::srand()
|
||||
#include <ctime> /// for std::time()
|
||||
#include <iostream> /// for IO operations
|
||||
#include <random>
|
||||
#include <random> /// for std::mt19937
|
||||
#include <vector> /// for std::vector
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h> /// for sleep
|
||||
@@ -32,7 +35,8 @@
|
||||
namespace games {
|
||||
/**
|
||||
* @namespace
|
||||
* @brief Functions for the [Memory Game](https://en.wikipedia.org/wiki/Matching_game) implementation
|
||||
* @brief Functions for the [Memory
|
||||
* Game](https://en.wikipedia.org/wiki/Matching_game) implementation
|
||||
*/
|
||||
namespace memory_game {
|
||||
/**
|
||||
@@ -41,14 +45,15 @@ namespace memory_game {
|
||||
* @tparam T The type of the input
|
||||
* @param input The input to check.
|
||||
* @returns false if the input IS empty or if it contains a non-digit character
|
||||
* @returns true if the input is NOT empty and if it contains only digit characters
|
||||
* @returns true if the input is NOT empty and if it contains only digit
|
||||
* characters
|
||||
*/
|
||||
template <typename T>
|
||||
bool is_number(const T& input) {
|
||||
bool is_number(const T &input) {
|
||||
if (std::cin.fail()) {
|
||||
std::cin.clear();
|
||||
std::cin.ignore(256, '\n');
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -66,14 +71,12 @@ void init(std::vector<T> *table) {
|
||||
std::vector<char> letters(7);
|
||||
|
||||
// Decrease / increase the number of letters depending on the size.
|
||||
if ((*table).size() == 10) { // 5x2
|
||||
letters = { 'A', 'E', 'Z', 'P', 'D' };
|
||||
}
|
||||
else if ((*table).size() == 8) { // 4x2
|
||||
letters = { 'A', 'E', 'Z', 'D' };
|
||||
}
|
||||
else if ((*table).size() == 14) { // 7x2
|
||||
letters = { 'A', 'E', 'Z', 'P', 'D', 'B', 'M' };
|
||||
if ((*table).size() == 10) { // 5x2
|
||||
letters = {'A', 'E', 'Z', 'P', 'D'};
|
||||
} else if ((*table).size() == 8) { // 4x2
|
||||
letters = {'A', 'E', 'Z', 'D'};
|
||||
} else if ((*table).size() == 14) { // 7x2
|
||||
letters = {'A', 'E', 'Z', 'P', 'D', 'B', 'M'};
|
||||
}
|
||||
|
||||
std::vector<char> pairs;
|
||||
@@ -82,7 +85,8 @@ void init(std::vector<T> *table) {
|
||||
pairs.push_back(letter);
|
||||
}
|
||||
|
||||
std::random_shuffle(pairs.begin(), pairs.end());
|
||||
std::shuffle(pairs.begin(), pairs.end(),
|
||||
std::mt19937(std::random_device()()));
|
||||
|
||||
for (int i = 0; i < (*table).size(); i++) {
|
||||
(*table)[i] = pairs[i];
|
||||
@@ -93,8 +97,7 @@ void init(std::vector<T> *table) {
|
||||
for (int i = 0; i < letters.size(); i++) {
|
||||
if (i == letters.size() - 1) {
|
||||
std::cout << "and " << letters[i] << ".\n\n";
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
std::cout << letters[i] << ", ";
|
||||
}
|
||||
}
|
||||
@@ -121,16 +124,17 @@ void print_table(const std::vector<T> &table) {
|
||||
|
||||
for (int i = 0; i < table.size(); i++) {
|
||||
if (i % 5 == 0 && i != 0) {
|
||||
std::cout << "\n| ";
|
||||
}
|
||||
std::cout << "\n| ";
|
||||
}
|
||||
|
||||
std::cout << table_print[i] << " | ";
|
||||
}
|
||||
std::cout << table_print[i] << " | ";
|
||||
}
|
||||
}
|
||||
|
||||
// Prototype function. This is needed as `ask_data` calls `reset_data`, and `reset_data` calls `ask_data`.
|
||||
// Prototype function. This is needed as `ask_data` calls `reset_data`, and
|
||||
// `reset_data` calls `ask_data`.
|
||||
template <typename T>
|
||||
void reset_data(const std::vector<T> &, int*, int*, int*);
|
||||
void reset_data(const std::vector<T> &, int *, int *, int *);
|
||||
|
||||
/**
|
||||
* @brief Function that asks the user for their
|
||||
@@ -139,11 +143,13 @@ void reset_data(const std::vector<T> &, int*, int*, int*);
|
||||
* @param table The table that's used to get the user's input and data.
|
||||
* @param answer The user's answer.
|
||||
* @param old_answer The user's previous answer.
|
||||
* @param memory_count A counter to check if the user has already answered two values.
|
||||
* @param memory_count A counter to check if the user has already answered two
|
||||
* values.
|
||||
* @returns void
|
||||
*/
|
||||
template <typename T>
|
||||
void ask_data(const std::vector<T> &table, int* answer, int* old_answer, int* memory_count) {
|
||||
void ask_data(const std::vector<T> &table, int *answer, int *old_answer,
|
||||
int *memory_count) {
|
||||
(*old_answer) = (*answer);
|
||||
print_table(table);
|
||||
|
||||
@@ -151,41 +157,49 @@ void ask_data(const std::vector<T> &table, int* answer, int* old_answer, int* me
|
||||
std::cin >> (*answer);
|
||||
|
||||
if (!is_number((*answer))) {
|
||||
std::cout << "\nYou must enter a valid number.\n\n";
|
||||
reset_data(table, answer, old_answer, memory_count);
|
||||
}
|
||||
std::cout << "\nYou must enter a valid number.\n\n";
|
||||
reset_data(table, answer, old_answer, memory_count);
|
||||
}
|
||||
|
||||
// Increase the memory count, which will be later on used for checking if the user has already answered two values.
|
||||
// Increase the memory count, which will be later on used for checking if
|
||||
// the user has already answered two values.
|
||||
(*memory_count)++;
|
||||
|
||||
if (((*answer) > table.size()) || ((*answer) < 1)) {
|
||||
std::cout << "\nYou can't check a value that doesn't exist (or an invalid number).\n\n";
|
||||
std::cout << "\nYou can't check a value that doesn't exist (or an "
|
||||
"invalid number).\n\n";
|
||||
reset_data(table, answer, old_answer, memory_count);
|
||||
}
|
||||
}
|
||||
|
||||
if ((*old_answer) == (*answer)) {
|
||||
std::cout << "\nYou can't check the same value twice.\n\n";
|
||||
reset_data(table, answer, old_answer, memory_count);
|
||||
}
|
||||
|
||||
// If two matches are answered already, but the user checkes a non-answered and an answered value, the program will mark it as no match, however, we must not allow the user to check the same value twice.
|
||||
if ((table[(*answer) - 1] != 0) && ((table[(*old_answer)] == 0) || (table[(*old_answer)] != 0))) {
|
||||
std::cout << "\nYou can't check the same value twice.\n\n";
|
||||
reset_data(table, answer, old_answer, memory_count);
|
||||
// If two matches are answered already, but the user checkes a non-answered
|
||||
// and an answered value, the program will mark it as no match, however, we
|
||||
// must not allow the user to check the same value twice.
|
||||
if ((table[(*answer) - 1] != 0) &&
|
||||
((table[(*old_answer)] == 0) || (table[(*old_answer)] != 0))) {
|
||||
std::cout << "\nYou can't check the same value twice.\n\n";
|
||||
reset_data(table, answer, old_answer, memory_count);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Utility function that resets the data if the user enters an invalid value.
|
||||
* @brief Utility function that resets the data if the user enters an invalid
|
||||
* value.
|
||||
* @tparam T The type of the table.
|
||||
* @param table The table that will be used to call `ask_data()`.
|
||||
* @param answer The user's answer.
|
||||
* @param old_answer The user's previous answer.
|
||||
* @param memory_count A counter to check if the user has already answered two values.
|
||||
* @param memory_count A counter to check if the user has already answered two
|
||||
* values.
|
||||
* @returns void
|
||||
*/
|
||||
template <typename T>
|
||||
void reset_data(const std::vector<T>& table, int* answer, int *old_answer, int* memory_count) {
|
||||
void reset_data(const std::vector<T> &table, int *answer, int *old_answer,
|
||||
int *memory_count) {
|
||||
(*answer) = (*old_answer);
|
||||
(*memory_count)--;
|
||||
|
||||
@@ -195,22 +209,28 @@ void reset_data(const std::vector<T>& table, int* answer, int *old_answer, int*
|
||||
/**
|
||||
* @brief Checks if the two values given by the user match.
|
||||
* @tparam T The type of the table.
|
||||
* @param table_empty The table with no values, slowly assigned from `table` depending on the user's input.
|
||||
* @param table_empty The table with no values, slowly assigned from `table`
|
||||
* depending on the user's input.
|
||||
* @param table The table with the original values.
|
||||
* @param answer The user's answer.
|
||||
* @param first_time A boolean to check if the user has already answered a value.
|
||||
* @param first_time A boolean to check if the user has already answered a
|
||||
* value.
|
||||
* @param old_answer The user's previous answer.
|
||||
* @param memory_count A counter to check if the user has already answered two values.
|
||||
* @param memory_count A counter to check if the user has already answered two
|
||||
* values.
|
||||
* @returns true IF the values given by the user match
|
||||
* @returns false if the values given by the user do NOT match
|
||||
*/
|
||||
template <typename T>
|
||||
bool match(const std::vector<T> &table, std::vector<T> *table_empty, const int &answer, bool *first_time, int *old_answer, int *memory_count) {
|
||||
bool match(const std::vector<T> &table, std::vector<T> *table_empty,
|
||||
const int &answer, bool *first_time, int *old_answer,
|
||||
int *memory_count) {
|
||||
if ((*first_time) == true) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Search across the whole table and if the two values match, keep results, otherwise, hide 'em up.
|
||||
// Search across the whole table and if the two values match, keep results,
|
||||
// otherwise, hide 'em up.
|
||||
for (int i = 0; i < table.size() + 1; i++) {
|
||||
if (i == answer) {
|
||||
if (table[i - 1] == table[(*old_answer) - 1]) {
|
||||
@@ -218,10 +238,10 @@ bool match(const std::vector<T> &table, std::vector<T> *table_empty, const int &
|
||||
(*memory_count) = 0;
|
||||
|
||||
(*old_answer) = 0;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
std::cout << "\nNo match (value was " << table[i - 1] << ", index is " << i << ").\n\n";
|
||||
return true;
|
||||
} else {
|
||||
std::cout << "\nNo match (value was " << table[i - 1]
|
||||
<< ", index is " << i << ").\n\n";
|
||||
|
||||
(*table_empty)[(*old_answer) - 1] = 0;
|
||||
(*table_empty)[answer - 1] = 0;
|
||||
@@ -230,10 +250,10 @@ bool match(const std::vector<T> &table, std::vector<T> *table_empty, const int &
|
||||
(*memory_count) = 0;
|
||||
|
||||
(*old_answer) = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -244,26 +264,33 @@ bool match(const std::vector<T> &table, std::vector<T> *table_empty, const int &
|
||||
* Also checkes if the user has answered all the values already, as well as
|
||||
* verify if the user made a match or not.
|
||||
* @tparam T The type of the tables.
|
||||
* @param table_empty The table with no values, slowly assigned from `table` depending on the user's input.
|
||||
* @param table_empty The table with no values, slowly assigned from `table`
|
||||
* depending on the user's input.
|
||||
* @param table The table with the original values.
|
||||
* @param answer The user's answer.
|
||||
* @param first_time A boolean to check if the user has already answered a value.
|
||||
* @param first_time A boolean to check if the user has already answered a
|
||||
* value.
|
||||
* @param old_answer The user's previous answer.
|
||||
* @param memory_count A counter to check if the user has already answered two values.
|
||||
* @param memory_count A counter to check if the user has already answered two
|
||||
* values.
|
||||
* @returns void
|
||||
*/
|
||||
template <typename T>
|
||||
void assign_results(std::vector<T> *table_empty, std::vector<T> *table, int* answer, bool *first_time, int *old_answer, int *memory_count) {
|
||||
// Search through the entire table and if the answer matches the index, show the value.
|
||||
// If it doesn't match, hide both the values. Don't forget to keep older values already answered.
|
||||
void assign_results(std::vector<T> *table_empty, std::vector<T> *table,
|
||||
int *answer, bool *first_time, int *old_answer,
|
||||
int *memory_count) {
|
||||
// Search through the entire table and if the answer matches the index, show
|
||||
// the value. If it doesn't match, hide both the values. Don't forget to
|
||||
// keep older values already answered.
|
||||
for (int i = 0; i < (*table).size() + 1; i++) {
|
||||
if (i == (*answer)) {
|
||||
if (match((*table), table_empty, (*answer), first_time, old_answer, memory_count) == true) {
|
||||
if (match((*table), table_empty, (*answer), first_time, old_answer,
|
||||
memory_count) == true) {
|
||||
(*table_empty)[i - 1] = (*table)[i - 1];
|
||||
(*first_time) = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
(*first_time) = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((*memory_count) == 1) {
|
||||
(*first_time) = false;
|
||||
@@ -272,43 +299,46 @@ void assign_results(std::vector<T> *table_empty, std::vector<T> *table, int* ans
|
||||
|
||||
char try_again = 'n';
|
||||
|
||||
// Has the user finished the game? Use a `for` loop, and if the table is full, ask the user if he wants to play again.
|
||||
// Has the user finished the game? Use a `for` loop, and if the table is
|
||||
// full, ask the user if he wants to play again.
|
||||
for (int i = 0; i < (*table).size() + 1; i++) {
|
||||
if ((*table_empty)[i] == 0) {
|
||||
break;
|
||||
}
|
||||
else if (i == (*table).size() - 1) {
|
||||
break;
|
||||
} else if (i == (*table).size() - 1) {
|
||||
print_table((*table));
|
||||
|
||||
std::cout << "\n\nYou won. Congratulations! Do you want to play again? (y/n)\n";
|
||||
std::cout << "Size " << (*table).size() << " will be used. This can be changed by re-running the game.";
|
||||
std::cin >> try_again;
|
||||
std::cout << "\n\nYou won. Congratulations! Do you want to play "
|
||||
"again? (y/n)\n";
|
||||
std::cout
|
||||
<< "Size " << (*table).size()
|
||||
<< " will be used. This can be changed by re-running the game.";
|
||||
std::cin >> try_again;
|
||||
if (try_again == 'y') {
|
||||
// This is needed when checking if the user has two matches already.
|
||||
// This is needed when checking if the user has two matches
|
||||
// already.
|
||||
for (int i = 0; i < (*table_empty).size(); i++) {
|
||||
(*table_empty)[i] = 0;
|
||||
}
|
||||
|
||||
init(table);
|
||||
}
|
||||
else if (try_again == 'n') {
|
||||
std::cout << "\nThanks for playing the game!\n";
|
||||
sleep(3);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
else {
|
||||
std::cout << "\nInvalid input (exitting...).\n";
|
||||
init(table);
|
||||
} else if (try_again == 'n') {
|
||||
std::cout << "\nThanks for playing the game!\n";
|
||||
sleep(3);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
std::cout << "\nInvalid input (exitting...).\n";
|
||||
sleep(3);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ask data again.
|
||||
ask_data((*table_empty), answer, old_answer, memory_count);
|
||||
assign_results(table_empty, table, answer, first_time, old_answer, memory_count);
|
||||
assign_results(table_empty, table, answer, first_time, old_answer,
|
||||
memory_count);
|
||||
}
|
||||
} // namespace memory_game
|
||||
} // namespace games
|
||||
@@ -321,14 +351,16 @@ int main() {
|
||||
// Start randomizer. This changes the values every time.
|
||||
std::srand(std::time(nullptr));
|
||||
|
||||
int size = 0; ///< Size of the table.
|
||||
int selection = 0; ///< Selection of the size (4x2, 5x2, 7x2).
|
||||
int size = 0; ///< Size of the table.
|
||||
int selection = 0; ///< Selection of the size (4x2, 5x2, 7x2).
|
||||
|
||||
int response = 0; ///< The answer (number index) that the user chose.
|
||||
int old_answer = 0; ///< Previous answer (number index).
|
||||
int response = 0; ///< The answer (number index) that the user chose.
|
||||
int old_answer = 0; ///< Previous answer (number index).
|
||||
|
||||
int memory_count = 0; ///< Counter to check if the user has already answered two values.
|
||||
bool first_time = true; ///< Whether the user has answered 1 value or not (previous answered values do not count).
|
||||
int memory_count =
|
||||
0; ///< Counter to check if the user has already answered two values.
|
||||
bool first_time = true; ///< Whether the user has answered 1 value or not
|
||||
///< (previous answered values do not count).
|
||||
|
||||
std::cout << "\tMEMORY GAME\n";
|
||||
|
||||
@@ -339,13 +371,22 @@ int main() {
|
||||
|
||||
std::cout << "\nChoose table size: ";
|
||||
std::cin >> selection;
|
||||
} while ((selection < 1 || selection > 3) && (!games::memory_game::is_number(selection)));
|
||||
} while ((selection < 1 || selection > 3) &&
|
||||
(!games::memory_game::is_number(selection)));
|
||||
|
||||
switch(selection) {
|
||||
case 1: size = 8; break;
|
||||
case 2: size = 10; break;
|
||||
case 3: size = 14; break;
|
||||
default: size = 10; break;
|
||||
switch (selection) {
|
||||
case 1:
|
||||
size = 8;
|
||||
break;
|
||||
case 2:
|
||||
size = 10;
|
||||
break;
|
||||
case 3:
|
||||
size = 14;
|
||||
break;
|
||||
default:
|
||||
size = 10;
|
||||
break;
|
||||
}
|
||||
|
||||
std::vector<char> table(size);
|
||||
@@ -354,8 +395,10 @@ int main() {
|
||||
std::cout << "\n";
|
||||
|
||||
games::memory_game::init(&table);
|
||||
games::memory_game::ask_data(table_empty, &response, &old_answer, &memory_count);
|
||||
games::memory_game::assign_results(&table_empty, &table, &response, &first_time, &old_answer, &memory_count);
|
||||
games::memory_game::ask_data(table_empty, &response, &old_answer,
|
||||
&memory_count);
|
||||
games::memory_game::assign_results(&table_empty, &table, &response,
|
||||
&first_time, &old_answer, &memory_count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user