diff options
8 files changed, 253 insertions, 22 deletions
diff --git a/Year 1/Object-oriented Programming/07-Practice-05.04.2022/Game.cpp b/Year 1/Object-oriented Programming/07-Practice-05.04.2022/Game.cpp index ae5fcc0..14274f9 100644 --- a/Year 1/Object-oriented Programming/07-Practice-05.04.2022/Game.cpp +++ b/Year 1/Object-oriented Programming/07-Practice-05.04.2022/Game.cpp @@ -1,29 +1,58 @@ #include "Game.h" +/* Helpers */ + +double getRandomBetween(int a, int b) { + if (a > b) { + int temp = b; + b = a; + a = temp; + } + + srand(time(NULL)); + return a + (double(rand()) / RAND_MAX) * (b - a); +} + /* Private */ -void Game::turn(Player& player, double& bet) { +void Game::copyFrom(const Game& other) { + this->caseCount = other.caseCount; + + cases = new GameCase[this->caseCount]; + for (int i = 0; i < this->caseCount; i++) + cases[i] = other.cases[i]; +} + +void Game::free() { + delete[] cases; +} + +TurnResult Game::turn(double& bet) { std::cout << "Enter command: "; char buffer; std::cin >> buffer; bool result = false; - for (int i = 0; i < this->caseCount; i++) { - if (cases[i].get_comm() == buffer) { - result = cases[i].exec(player, bet); - break; - } - } + int caseI = 0; + while (cases[caseI].get_comm() != buffer && caseI < this->caseCount) + caseI++; + + if (caseI < this->caseCount) + result = cases[caseI].exec(bet); + else + std::cout << "Invalid command! "; if (result) { - std::cout << "You win!"; - player.addToBalance("", bet); + std::cout << "You won this turn. Your current bet is " << bet << std::endl << "Do you want to continue? [y/n] "; + std::cin >> buffer; + return (buffer == 'N' || buffer == 'n') ? Win : Continue; } - else { - std::cout << "You lost!"; - player.deductFromBalance("", bet); + else if (bet > 0) { + std::cout << "Do you want to quit? [y/n] "; + std::cin >> buffer; + return (buffer == 'N' || buffer == 'n') ? Continue : Quit; } - std::cout << " Current balance: " << player.get_balance() << std::endl; + return Lost; } /* Public */ @@ -34,4 +63,55 @@ Game::Game(const GameCase* cases, unsigned casesCount) { this->cases[i] = cases[i]; } +Game::Game(const Game& other) { + this->copyFrom(other); +} + +Game& Game::operator=(const Game& other) { + if (this != &other) { + this->free(); + this->copyFrom(other); + } + return *this; +} + +Game::~Game() { + this->free(); +} + +void Game::play(Player& player) { + if (player.get_age() < 18) { + std::cout << "You must be at least 18 years old to play." << std::endl; + return; + } + + std::cout << "Password: "; + char password[2048]; + std::cin >> password; + + std::cout << "Your current balance: " << player.get_balance() << std::endl << "Enter bet: "; + double bet; + std::cin >> bet; + + player.deductFromBalance(password, bet); + TurnResult result = Continue; + while (result == Continue) + result = this->turn(bet); + + switch (result) { + case Win: + std::cout << "You've won! " << bet << " will be added to your account." << std::endl; + player.addToBalance(password, bet); + break; + + case Quit: // If your bet drops to 0, you'll automatically lose, so you'll never quit with bet of 0. + std::cout << "Quitting game. " << bet << " will be added to your account." << std::endl; + player.addToBalance(password, bet); + break; + + default: + std::cout << "You lost! Your balance is " << player.get_balance() << "." << std::endl; + break; + } +} diff --git a/Year 1/Object-oriented Programming/07-Practice-05.04.2022/Game.h b/Year 1/Object-oriented Programming/07-Practice-05.04.2022/Game.h index 96feeaf..8915196 100644 --- a/Year 1/Object-oriented Programming/07-Practice-05.04.2022/Game.h +++ b/Year 1/Object-oriented Programming/07-Practice-05.04.2022/Game.h @@ -1,13 +1,25 @@ #include <iostream> +#include <stdlib.h> // srand, time and rand #include "Player.h" #include "GameCase.h" +double getRandomBetween(int, int); + +enum TurnResult { + Quit, + Continue, + Win, + Lost +}; + class Game { GameCase* cases; unsigned caseCount; - void turn(Player&, double&); + void copyFrom(const Game&); + void free(); + TurnResult turn(double&); public: Game(const GameCase*, unsigned); diff --git a/Year 1/Object-oriented Programming/07-Practice-05.04.2022/GameCase.cpp b/Year 1/Object-oriented Programming/07-Practice-05.04.2022/GameCase.cpp index 713c94c..f16e72b 100644 --- a/Year 1/Object-oriented Programming/07-Practice-05.04.2022/GameCase.cpp +++ b/Year 1/Object-oriented Programming/07-Practice-05.04.2022/GameCase.cpp @@ -3,11 +3,15 @@ GameCase::GameCase() : GameCase('\0', nullptr) {} -GameCase::GameCase(char command, bool func(const Player&, double&)) { +GameCase::GameCase(char command, bool func(double&)) { this->command = command; this->func = func; } -bool GameCase::exec(const Player& player, double& bet) const { - return this->func(player, bet); +char GameCase::get_comm() const { + return this->command; +} + +bool GameCase::exec(double& bet) const { + return this->func(bet); } diff --git a/Year 1/Object-oriented Programming/07-Practice-05.04.2022/GameCase.h b/Year 1/Object-oriented Programming/07-Practice-05.04.2022/GameCase.h index bf5030f..8efd039 100644 --- a/Year 1/Object-oriented Programming/07-Practice-05.04.2022/GameCase.h +++ b/Year 1/Object-oriented Programming/07-Practice-05.04.2022/GameCase.h @@ -2,12 +2,12 @@ class GameCase { char command; - bool (*func)(const Player&, double&); + bool (*func)(double&); public: GameCase(); - GameCase(char, bool f(const Player&, double&)); + GameCase(char, bool f(double&)); char get_comm() const; - bool exec(const Player&, double&) const; + bool exec(double&) const; }; diff --git a/Year 1/Object-oriented Programming/07-Practice-05.04.2022/NumberHelpers.cpp b/Year 1/Object-oriented Programming/07-Practice-05.04.2022/NumberHelpers.cpp new file mode 100644 index 0000000..d7843b4 --- /dev/null +++ b/Year 1/Object-oriented Programming/07-Practice-05.04.2022/NumberHelpers.cpp @@ -0,0 +1,35 @@ +#include "NumberHelpers.h" + +bool isEven(int x) { + return x % 2 == 0; +} + +// The following functions are taken from my own Interval task solution + +bool isPowerOfTwo(int x) +{ + return x > 0 && // No (normal) power of 2 creates negatives or 0 + (x & (x - 1)) == 0; // Thanks https://stackoverflow.com/a/600306/12036073, original implementation was a lot less efficient +} + +bool isPrime(int num) // Forked from my own implementation - https://gitlab.com/Syndamia/algorithms/-/blob/master/C/IsPrime.c +{ + if (num < 0) num *= -1; // This is required, since we calculate sqrt(num) + + if (num == 2 || num == 3 || num == 5 || num == 7 || num == 11 || num == 13) + return true; + + // A lot of numbers are divisible by these ones, so we're going to do a bit of simple optimization + if (num == 0 || num == 1 || num % 2 == 0 || num % 3 == 0 || num % 5 == 0 || num % 7 == 0 || num % 11 == 0 || num % 13 == 0) + return false; + + // All primes follow the formula 6n +- 1 (where n >= 1). Since we've already checked up to 13, we're going to + // start with 18 - 1 = 17. Also using root of number to eliminate a lot of checks. + // Primary source: https://en.wikipedia.org/wiki/Primality_test#Simple_methods + for (int i = 18, root = sqrt(num); i - 1 <= root; i += 6) + { + if (num % (num - 1) == 0 || num % (num + 1) == 0) + return false; + } + return true; +} diff --git a/Year 1/Object-oriented Programming/07-Practice-05.04.2022/NumberHelpers.h b/Year 1/Object-oriented Programming/07-Practice-05.04.2022/NumberHelpers.h index 2e1050b..159f0f3 100644 --- a/Year 1/Object-oriented Programming/07-Practice-05.04.2022/NumberHelpers.h +++ b/Year 1/Object-oriented Programming/07-Practice-05.04.2022/NumberHelpers.h @@ -1,3 +1,5 @@ +#include <math.h> + bool isEven(int); -bool isPrimary(int); bool isPowerOfTwo(int); +bool isPrime(int); diff --git a/Year 1/Object-oriented Programming/07-Practice-05.04.2022/Player.cpp b/Year 1/Object-oriented Programming/07-Practice-05.04.2022/Player.cpp index eaca839..cb76553 100644 --- a/Year 1/Object-oriented Programming/07-Practice-05.04.2022/Player.cpp +++ b/Year 1/Object-oriented Programming/07-Practice-05.04.2022/Player.cpp @@ -23,7 +23,7 @@ bool Player::isValidPassword(const char* passwordAttempt) { /* Public */ -Player::Player(const char* name, const char* pass, unsigned age, double currentBalance) { +Player::Player(const char* name, const char* pass, unsigned age, double balance) { this->name = new char[strlen(name) + 1]; strcpy(this->name, name); this->pass = new char[strlen(pass) + 1]; diff --git a/Year 1/Object-oriented Programming/07-Practice-05.04.2022/source.cpp b/Year 1/Object-oriented Programming/07-Practice-05.04.2022/source.cpp index e69de29..1a3f4ba 100644 --- a/Year 1/Object-oriented Programming/07-Practice-05.04.2022/source.cpp +++ b/Year 1/Object-oriented Programming/07-Practice-05.04.2022/source.cpp @@ -0,0 +1,98 @@ +#include "Game.h" +#include "NumberHelpers.h" + +bool gameCase_evenOrOdd(double& bet) { + int rnd = getRandomBetween(1, 100); + std::cout << "Is the number [e]ven or [o]dd? "; + char buffer; + std::cin >> buffer; + + while (buffer != 'e' && buffer != 'o') { + std::cout << "Unknown option '" << buffer << "', choice must be either 'e' or 'o'." << std::endl << "Is the number [e]ven or [o]dd? "; + std::cin >> buffer; + } + + bool result = isEven(rnd) == (buffer == 'e'); + bet = (result) ? bet / 5 : 0; + std::cout << "The number was: " << rnd << std::endl; + return result; +} + +bool gameCase_isPrime(double& bet) { + int rnd = getRandomBetween(1, 100); + + bool result = isPrime(rnd); + bet = (result) ? bet / 2 : 0; + std::cout << "The number was: " << rnd << std::endl; + return result; +} + +bool gameCase_isPowerOfTwo(double& bet) { + int rnd = getRandomBetween(1, 100); + + bool result = isPowerOfTwo(rnd); + bet = (result) ? bet / 2 : 0; + std::cout << "The number was: " << rnd << std::endl; + return result; +} + +bool gameCase_higherOrLower(double& bet) { + int rnd = getRandomBetween(1, 100); + + std::cout << "Your number [20...60] "; + int num; + std::cin >> num; + + while (num < 20 || num > 60) { + std::cout << "Number not in range! Enter number [20...60] "; + std::cin >> num; + } + + std::cout << num << " will be [h]igher or [l]ower than random? "; + char guess; + std::cin >> guess; + + while (guess != 'h' && guess != 'l') { + std::cout << "Invalid option '" << guess << "', must be either 'h' or 'l'." << std::endl << num << " will be [h]igher or [l]ower than random? "; + std::cin >> guess; + } + + bool result = (rnd > num) == (guess == 'h'); + bet = (result) ? bet / 4 : 0; + std::cout << "The number was: " << rnd << std::endl; + return result; +} + +bool gameCase_guess(double& bet) { + int rnd = getRandomBetween(1, 100); + + std::cout << "Your guess: "; + int num; + std::cin >> num; + + bool result = num == rnd; + bet = (result) ? bet * 10 : 0; + std::cout << "The number was: " << rnd << std::endl; + return result; +} + +int main() { + GameCase numberGambleCases[] = { + GameCase('e', gameCase_evenOrOdd), + GameCase('p', gameCase_isPrime), + GameCase('t', gameCase_isPowerOfTwo), + GameCase('h', gameCase_higherOrLower), + GameCase('g', gameCase_guess) + }; + Game numberGamble(numberGambleCases, 5); + + Player yorgus("Yorgus", "yorgus", 23, 57741.39); + + char buffer = '\0'; + while (buffer != 'n' && buffer != 'N') { + numberGamble.play(yorgus); + std::cout << "Do you want to play again? [y/n] "; + std::cin >> buffer; + } + std::cout << "Your balance: " << yorgus.get_balance() << std::endl; +} |
