From 59796d33b0f2fb1c2a5b26d8f96625c8883f2cc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Constantin=20F=C3=BCrst?= Date: Tue, 30 Apr 2024 11:21:06 +0200 Subject: [PATCH] rewrite the game with my code styling and modern c++ view --- components/Point.cpp | 66 ++++++------- components/Point.h | 30 +++--- components/Snack.cpp | 27 +++-- components/Snack.h | 6 +- components/Snake.cpp | 200 +++++++++++++++++++------------------- components/Snake.h | 40 ++++---- game/Controller.cpp | 85 +++++++--------- game/Controller.h | 30 +++--- game/Game.cpp | 93 ++++++++---------- game/Game.h | 32 +++--- input-output/Graphics.cpp | 101 +++++++++---------- input-output/Graphics.h | 49 ++++++---- input-output/Player.cpp | 43 +++----- input-output/Player.h | 21 ++-- 14 files changed, 390 insertions(+), 433 deletions(-) diff --git a/components/Point.cpp b/components/Point.cpp index 6993299..934fc9f 100755 --- a/components/Point.cpp +++ b/components/Point.cpp @@ -1,58 +1,50 @@ -#include -#include #include "Point.h" -/*snake will be an array of points*/ +Point::Point(uint32_t y, uint32_t x, int img) + : x_ {x}, y_ {y}, img_ {img} +{ } -using namespace std; -Point::Point(int y, int x, graphics_input img) -: x {x}, y{y}, img{img} -{} -//delegating the previous constructor -Point::Point() -:Point(10, 10, '*') -{} - -Point::~Point(){/*No need to do something */} - -void Point::setPoint(int y, int x){ - this->x = x; - this->y = y; +void Point::setPoint(uint32_t y, uint32_t x) { + x_ = x; + y_ = y; } -int Point::getX(void){ - return this->x; +uint32_t Point::getX() const { + return x_; } -int Point::getY(void){ - return this->y; +uint32_t Point::getY() const { + return y_; } -void Point::moveUp(void){ - y--; +void Point::moveUp() { + y_--; } -void Point::moveDown(void){ - y++; +void Point::moveDown() { + y_++; } -void Point::moveLeft(void){ - x--; +void Point::moveLeft() { + x_--; } -void Point::moveRight(void){ - x++; +void Point::moveRight() { + x_++; } -graphics_input Point::getImg(){ - return this->img; +int Point::getImg() const { + return img_; } -void Point::setImg(graphics_input image){ - this->img = image; + +void Point::setImg(int image){ + img_ = image; } -void Point::printImg(){ - printChar(this->y, this->x, this->img); + +void Point::print() const { + Graphics::get().printChar(y_, x_, img_); } -void Point::erase(void){ - this->img = ' '; + +void Point::clear(){ + img_ = ' '; } \ No newline at end of file diff --git a/components/Point.h b/components/Point.h index e4f0105..96efdcb 100755 --- a/components/Point.h +++ b/components/Point.h @@ -4,23 +4,25 @@ class Point{ private: - int x; - int y; - graphics_input img; + uint32_t x_; + uint32_t y_; + int img_; + public: - Point(); - Point(int y = 10, int x = 10, graphics_input img = '*'); - ~Point(); - void setPoint(int y, int x); - int getX(); - int getY(); + Point(uint32_t y, uint32_t x, int img = '*'); + + void setPoint(uint32_t y, uint32_t x); + uint32_t getX() const; + uint32_t getY() const; + void moveUp(); void moveDown(); void moveLeft(); void moveRight(); - graphics_input getImg(); - void setImg(graphics_input image); - void printImg(); - void erase(); - void randomize(); + + int getImg() const; + void setImg(int image); + + void print() const; + void clear(); }; \ No newline at end of file diff --git a/components/Snack.cpp b/components/Snack.cpp index a4dad7f..865b08a 100755 --- a/components/Snack.cpp +++ b/components/Snack.cpp @@ -1,22 +1,17 @@ #include "Snack.h" -#include -using namespace std; +#include +void generateSnack(Point* snack){ + std::random_device dev; + static std::mt19937 prng(dev()); + static std::uniform_int_distribution distX(0, GAME_RIGHT_WALL_X); + static std::uniform_int_distribution distY(0, GAME_BOTTOM_WALL_Y); -const unsigned int snackScore = 10; - -void generateSnack(Point &snack){ - - int x, y; + const uint32_t x = distX(prng); + const uint32_t y = distY(prng); - x = rand() % GAME_RIGHT_WALL_X + 1; - y = rand() % GAME_BOTTOM_WALL_Y + 1; - - snack.setPoint(y, x); - - printChar(y, x, snack.getImg()); -} -unsigned int getSnackScore(void){ - return snackScore; + snack->setImg(SNACK_CHAR); + snack->setPoint(y, x); + snack->print(); } \ No newline at end of file diff --git a/components/Snack.h b/components/Snack.h index 09aa99e..86af25d 100755 --- a/components/Snack.h +++ b/components/Snack.h @@ -2,8 +2,6 @@ #include "Point.h" -#define SNACK '*' +static constexpr int SNACK_CHAR = '*'; -//snack methods -void generateSnack(Point &snack); -unsigned int getSnackScore(void); +void generateSnack(Point* snack); diff --git a/components/Snake.cpp b/components/Snake.cpp index a54bdb3..4960388 100755 --- a/components/Snake.cpp +++ b/components/Snake.cpp @@ -1,38 +1,35 @@ #include "Snake.h" + #include -using namespace std; -Snake::Snake(int headY, int headX) -:direction{LEFT} +Snake::Snake(uint32_t headY, uint32_t headX) + :direction_{LEFT} { - snake.push_back(Point{headY, headX, '>'}); //add the head of the snake - for(int i=1; i<=3; i++) - snake.push_back(Point{headY, headX+i, BODY}); -} + snake_.push_back(Point{headY, headX, '>'}); -Snake::~Snake(){} + for (uint32_t i = 1; i <= SNAKE_DEFAULT_SIZE - 1; i++) { + snake_.push_back(Point{headY, headX + i, SNAKE_BODY_CHAR}); + } +} -bool Snake::isBitten(void){ - Point head = *snake.begin(); +bool Snake::isBitten() const { + const Point& head = snake_.front(); - list::iterator body_part = snake.begin(); - body_part++; - while(body_part != snake.end()){ - if(body_part->getX() == head.getX() && body_part->getY() == head.getY()) + for (const Point& part : snake_) { + if (part.getX() == head.getX() && part.getY() == head.getY()) { return true; - body_part++; + } } return false; } -bool Snake::hasBitSnack(int snackY, int snackX){ - return snake.begin()->getY() == snackY - && snake.begin()->getX() == snackX; +bool Snake::hasBitSnack(uint32_t snackY, uint32_t snackX) const { + return snake_.front().getY() == snackY && snake_.front().getX() == snackX; } -bool Snake::hasCrashedWall(void){ - Point &head = *snake.begin(); +bool Snake::hasCrashedWall() const { + const Point& head = snake_.front(); return (head.getY() < GAME_TOP_WALL_Y) || (head.getY() > GAME_BOTTOM_WALL_Y) || @@ -40,119 +37,122 @@ bool Snake::hasCrashedWall(void){ (head.getX() > GAME_RIGHT_WALL_X); } -int Snake::getSize(void){ - return snake.size(); +uint32_t Snake::getSize() const { + return snake_.size(); } -void Snake::incSize(void){ - auto tail = snake.end(); - //since list::end() returns one element past the actual last one we will decrease by one the tail iterator - tail--; //now we actually pointing to the tail - int tailX = tail->getX(); - int tailY = tail->getY(); - - //now we must determine the direction which is easy by just fiding the coordinates of the previous to tail element - auto prev = --tail; - int prevX = prev->getX(); - int prevY = prev->getY(); - - if(prevY == tailY){ - //if the 2 part are on the same 'height' - if (prevX < tailX) //if the tail continues to the left: - snake.push_back(Point{tailY, tailX + 1, BODY}); // add one part to the right of the tail - else if(prevX > tailX) //if the tail continues to the right: - snake.push_back(Point{tailY, tailX - 1, BODY}); // add one part to the left of the tail - }else{ - if (prevY < tailY) //if the tail continues to the upper side: - snake.push_back(Point{tailY + 1, tailX, BODY}); // add one part facing down - else if (prevY > tailY) //if the tail continues to the lower side: - snake.push_back(Point{tailY - 1, tailX, BODY}); // add one part facing up +void Snake::incSize(){ + const auto tail = std::prev(snake_.end()); + const uint32_t tailX = tail->getX(); + const uint32_t tailY = tail->getY(); + + const auto prev = std::prev(tail); + const uint32_t prevX = prev->getX(); + const uint32_t prevY = prev->getY(); + + if (prevY == tailY){ + // if the two last parts are on the same 'height' (horizontal tail direction) + + if (prevX < tailX) { + // if the tail continues to the left: + // add one part to the right of the tail + snake_.push_back(Point{tailY, tailX + 1, SNAKE_BODY_CHAR}); + } + else { + // if the tail continues to the right: + // add one part to the left of the tail + snake_.push_back(Point{tailY, tailX - 1, SNAKE_BODY_CHAR}); + } + } + else { + // if the two last parts are on the same 'width' (vertical tail direction) + + if (prevY < tailY) { + // if the tail continues to the upper side: + // add one part facing down + snake_.push_back(Point{tailY + 1, tailX, SNAKE_BODY_CHAR}); + } + else { + // if the tail continues to the lower side: + // add one part facing up + snake_.push_back(Point{tailY - 1, tailX, SNAKE_BODY_CHAR}); + } } } -void Snake::updateHead(void){ - auto head = snake.begin(); - switch (this->direction) - { +void Snake::updateHead(){ + switch (direction_) { case UP: - head->moveUp(); + snake_.front().moveUp(); break; case DOWN: - head->moveDown(); + snake_.front().moveDown(); break; case LEFT: - head->moveLeft(); + snake_.front().moveLeft(); break; case RIGHT: - head->moveRight(); + snake_.front().moveRight(); break; } } -void Snake::printSnake(void){ +void Snake::printSnake() const { //We print each element of the snake-list - for(auto bodyPart : snake){ - bodyPart.printImg(); + for (const Point& part : snake_){ + part.print(); } - refreshScreen(); //finally call the previously implemented function at Graphics.cpp - //to update the screen so the changes become noticed + Graphics::get().refreshScreen(); } -void Snake::move(void){ - //now delete the tail print since teh snake moves forward - auto tail = snake.end(); - tail--; - printChar(tail->getY(), tail->getX(), ' '); - - //and now we have to update all the other nodes of the body - - auto bodyP1 = tail; - auto bodyP2 = --tail; - - while(bodyP2 != snake.begin()){ - *bodyP1 = *bodyP2; - bodyP1--; - bodyP2--; +void Snake::move(){ + // updates the tail by clearing it since + // the snake moved forward (overwrites with ' ') + snake_.back().clear(); + + // iterate through the snake step by step + // using iterators so that we can get prev + // and iterate from back to front as we want to + // update each element with the value of the next + // and would otherwise overwrite the next before + // and not updating first as head is handled separately + + for (auto it = std::prev(snake_.end()); it != snake_.begin(); it--) { + const auto prev = std::prev(it); + it->setPoint(prev->getY(), prev->getX()); } - //update the previous to head node - auto headPrev = snake.begin(); - headPrev++; - *headPrev = *snake.begin(); - headPrev->setImg(BODY); - - //based on direction, update the head - this->updateHead(); + // update the head depending on movement + updateHead(); - this->printSnake(); // print the snake and update the screen + // print the updated snake + printSnake(); } -//Move Functions: -//For the move functions we must change -void Snake::moveUp(void){ - snake.begin()->setImg('v'); - this->direction = UP; - this->move(); +void Snake::moveUp(){ + snake_.front().setImg('v'); + direction_ = UP; + move(); } -void Snake::moveDown(void){ - snake.begin()->setImg('^'); - this->direction = DOWN; - this->move(); +void Snake::moveDown(){ + snake_.front().setImg('^'); + direction_ = DOWN; + move(); } -void Snake::moveLeft(void){ - snake.begin()->setImg('>'); - this->direction = LEFT; - this->move(); +void Snake::moveLeft(){ + snake_.front().setImg('>'); + direction_ = LEFT; + move(); } -void Snake::moveRight(void){ - snake.begin()->setImg('<'); - this->direction = RIGHT; - this->move(); +void Snake::moveRight(){ + snake_.front().setImg('<'); + direction_ = RIGHT; + move(); } \ No newline at end of file diff --git a/components/Snake.h b/components/Snake.h index bbbb0a3..98b64f1 100755 --- a/components/Snake.h +++ b/components/Snake.h @@ -1,34 +1,34 @@ #pragma once +#include + #include "Point.h" #include "Snack.h" -#include +static constexpr int SNAKE_BODY_CHAR = 'o'; +static constexpr uint32_t SNAKE_DEFAULT_SIZE = 4; -#define BODY 'o' class Snake{ private: - std::list snake; //the snake will be implemented as a list of points where the first element is the head - graphics_input direction; - void updateHead(void); - void printSnake(void); -public: - Snake(int headY = LINES/2, int headX = COLS/2); //default constructor - ~Snake(); //destructor + std::vector snake_; + int direction_; - //basic move functions - void moveUp(void); - void moveDown(void); - void moveLeft(void); - void moveRight(void); + void updateHead(); + void printSnake() const; - bool isBitten(void); //function to check if the snake bit its self - bool hasBitSnack(int snackY, int snackX);//checks if the snake has bitten a snack +public: + Snake(uint32_t headY = LINES/2, uint32_t headX = COLS/2); - bool hasCrashedWall(void); // method to check if the snake crashed the walls + void moveUp(); + void moveDown(); + void moveLeft(); + void moveRight(); + void move(); - int getSize(void); //get the current length - void incSize(void); //function to increase the length + bool isBitten() const; + bool hasBitSnack(uint32_t snackY, uint32_t snackX) const; + bool hasCrashedWall() const; - void move(void); //function to refresh the image of the snake + uint32_t getSize() const; + void incSize(); }; diff --git a/game/Controller.cpp b/game/Controller.cpp index 7f3ea07..c930cc4 100755 --- a/game/Controller.cpp +++ b/game/Controller.cpp @@ -1,86 +1,69 @@ #include "Controller.h" -#include -#include -using namespace std; +#include Controller::Controller() -: snack{SNACK} ,inpt{0}, currentScore{0} + : input_{0}, score_{0}, snack_{Point(0,0,0)} { - snake = new Snake(); - generateSnack(snack); + generateSnack(&snack_); } -Controller::Controller(Snake *_snake) -: snake{_snake}, snack{SNACK}, inpt{0}, currentScore{0} -{ - - assert(this->snake != NULL); +uint32_t Controller::getCurrScore() const { + return score_; } -unsigned int Controller::getCurrScore(void){ - return this->currentScore; +void Controller::resetScore() { + score_ = 0; } -void Controller::resetScore(void){ - this->currentScore = 0; -} - -Controller::~Controller(){delete snake;} - -static void printScore(unsigned int _score){ - string str = "Score: " + to_string(_score); - printMsg(-1, -1, (char*)str.c_str()); //-1, -1 because otherwise it'll be printed inside the game box +void Controller::printScore(uint32_t score) const { + const std::string str = "Score: " + std::to_string(score); + // locate message at (-1,-1) because otherwise it'll be printed inside the game box + Graphics::get().printMsg(-1, -1, str); } -int Controller::act(void){ - - if (snake->hasBitSnack(this->snack.getY(), this->snack.getX()) == true) - { - this->currentScore += 10; +int Controller::act() { + if (snake_.hasBitSnack(snack_.getY(), snack_.getX())) { + score_ += 10; + snake_.incSize(); - advanceDifficulty(); - generateSnack(this->snack); + generateSnack(&snack_); + Graphics::get().advanceDifficulty(); - this->snake->incSize(); - - printScore(currentScore); + printScore(score_); } - switch (this->inpt) - { + switch (input_) { case UP: - snake->moveUp(); + snake_.moveUp(); break; case DOWN: - snake->moveDown(); + snake_.moveDown(); break; case LEFT: - snake->moveLeft(); + snake_.moveLeft(); break; case RIGHT: - snake->moveRight(); + snake_.moveRight(); break; default: - snake->move(); - break; + snake_.move(); } - refreshScreen(); + Graphics::get().refreshScreen(); - if(snake->isBitten()) - return DEFEAT; - if (snake->hasCrashedWall()) + if (snake_.isBitten() || snake_.hasCrashedWall()) { return DEFEAT; + } + return 0; } -graphics_input Controller::readInput(void){ - this->inpt = readInpt(); - refreshScreen(); - return inpt; +int Controller::readInput() { + input_ = Graphics::get().readInpt(); + return input_; } -bool Controller::wantsToQuit(void){ - return this->inpt == EXIT_GAME; -} \ No newline at end of file +bool Controller::wantsToQuit() const { + return input_ == EXIT_GAME; +} diff --git a/game/Controller.h b/game/Controller.h index c72bf11..7554283 100755 --- a/game/Controller.h +++ b/game/Controller.h @@ -1,27 +1,31 @@ #pragma once +#include + #include "../input-output/Graphics.h" #include "../components/Snake.h" #include "../components/Point.h" -#define DEFEAT -1 +static constexpr int DEFEAT = -1; -class Controller{ +class Controller { private: - Snake *snake; //the figure the controler controls - Point snack; - graphics_input inpt; - unsigned int currentScore; + Snake snake_; + Point snack_; + + int input_; + uint32_t score_; + + void printScore(uint32_t score) const; + public: - Controller(Snake* _snake); Controller(); - ~Controller(); //default destructor - unsigned int getCurrScore(void); - void resetScore(void); - graphics_input readInput(void); //basic input methods: sets inpt to what it read if i tread something + uint32_t getCurrScore() const; - int act(void); //basic act method: acts like a joystick + void resetScore(); + int readInput(); + int act(); - bool wantsToQuit(void); //returns true of the user wants to quit + bool wantsToQuit() const; }; \ No newline at end of file diff --git a/game/Game.cpp b/game/Game.cpp index cd06f9b..60ae342 100644 --- a/game/Game.cpp +++ b/game/Game.cpp @@ -1,77 +1,64 @@ #include "Game.h" + #include #include -using namespace std; - -SnakeGame::SnakeGame() -:gameName{"~Snake Game by VissaM~"},highScore{0}, bestPlayer{"None"} -{} -SnakeGame::~SnakeGame(){} - -void SnakeGame::addPlayer(string playerName){ - players.emplace_back( Player{playerName} ); +void SnakeGame::addPlayer(const std::string& name){ + players_.emplace_back(Player{name}); } -unsigned int SnakeGame::getHighScore(void){ - return highScore; +uint32_t SnakeGame::getHighScore() const { + return high_score_; } -string SnakeGame::getBestPlayer(void){ - return bestPlayer; +const std::string& SnakeGame::getBestPlayer() const { + return best_player_; } -void SnakeGame::play(string playerName){ - pair curBest{playerName, 0}; - for(auto player : players){ - if(player.getName() == playerName){ - initializeGraphics((char *)gameName.c_str()); - curBest = player.play(); - endGraphics(); - break; - } +void SnakeGame::play(const std::string& name){ + auto find = std::find(players_.begin(), players_.end(), [&name](const Player& p){ return p.getName() == name; }); + + if (find == players_.end()) { + players_.emplace_back(Player(name)); + find = std::prev(players_.end()); } - if(curBest.second > highScore){ - highScore = curBest.second; - bestPlayer = curBest.first; + Graphics::get().init(game_name_); + + find->play(); + + Graphics::get().finalize(); + + + if (find->getHighScore() > high_score_){ + high_score_ = find->getHighScore(); + best_player_ = find->getName(); } - cout << "Highscore: " << highScore << " by " << bestPlayer << "\n" <> playerName; - cout << endl; - - list::iterator p; - for(p=players.begin(); p!=players.end(); p++){ - if(p->getName() == playerName) - break; - } +void SnakeGame::play(){ + while(1) { + std::string name; + std::cout << "Who's playing: "; + std::cin >> name; + std::cout << std::endl; - if(p == players.end()){ - //if the player isn't in the list, add him/her - addPlayer(playerName); - } + play(name); + std::cin.clear(); + std::cin.ignore(std::numeric_limits::max(), '\n'); + std::cout << "Do you or someone else want to play again? (yes or no): "; + std::string ans; - play(playerName); //get the player to play the game - - cin.clear(); - cin.ignore(numeric_limits::max(), '\n'); - cout << "Do you want to play again? (yes or no): "; - string ans; - - cin >> ans; + std::cin >> ans; - if(ans != "yes"){ - cout << "Exiting ..." << endl; + if (ans != "yes") { + std::cout << "Exiting ..." << std::endl; break; } - cout << "Perfect...\n" << endl; + + std::cout << "Perfect..." << std::endl; } } \ No newline at end of file diff --git a/game/Game.h b/game/Game.h index 9cb673e..1537427 100755 --- a/game/Game.h +++ b/game/Game.h @@ -1,31 +1,27 @@ #pragma once +#include +#include + #include "Controller.h" #include "../components/Snake.h" #include "../input-output/Player.h" -#include - class SnakeGame{ private: - std::string gameName; - std::list players; - unsigned int highScore; - std::string bestPlayer; - - void play(std::string playerName); - void addPlayer(std::string playerName); - -public: - SnakeGame(); //intialize graphics and set the game screen - ~SnakeGame(); + const std::string game_name_ = "Snake Game for C++ Course"; + std::vector players_; + uint32_t high_score_ = 0; + std::string best_player_ = "None"; - unsigned int getHighScore(void); - std::string getBestPlayer(void); + void play(const std::string& name); + void addPlayer(const std::string& name); - //print the statistics (highest score & games played) of each player - //void printGameStatistics(void); +public: + uint32_t getHighScore() const; + const std::string& getBestPlayer() const; + void printGameStatistics() const; - void play(void); + void play(); }; \ No newline at end of file diff --git a/input-output/Graphics.cpp b/input-output/Graphics.cpp index 6ce0713..abb91f9 100755 --- a/input-output/Graphics.cpp +++ b/input-output/Graphics.cpp @@ -4,86 +4,89 @@ #include #include -///Utillities for the graphics -unsigned int sleepTime = 40000000; -static WINDOW *_box = NULL; - -static void createBox(void){ - _box = newwin(LINES-2, COLS, 2, 0); - box(_box, 0, 0); - wrefresh(_box); +void Graphics::createBox() { + box_ = newwin(LINES-2, COLS, 2, 0); + box(box_, 0, 0); + wrefresh(box_); } -static void destroyBox(void){ - wborder(_box, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '); - wrefresh(_box); - delwin(_box); + +void Graphics::destroyBox() { + wborder(box_, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '); + wrefresh(box_); + delwin(box_); } -//Initialization function -void initializeGraphics(char* gameName){ + +void Graphics::init(const std::string& gameName) { srand((unsigned int) time(NULL)); - initscr(); //initialize curses - cbreak(); //set line buffering to false - noecho(); //set input echo to false - keypad(stdscr, TRUE); //this step enables the use of arrow keys and other function keys + initscr(); + cbreak(); + noecho(); + keypad(stdscr, TRUE); nodelay(stdscr, true); - curs_set(0); //to hide the cursor - //We must clear the screen from unecessary garbage + curs_set(0); + clear(); - //Print the title - mvprintw(0, (COLS/2) - 12, gameName); + + mvprintw(0, (COLS/2) - 12, gameName.c_str()); refresh(); - //create the game box createBox(); } -//Exit function -void endGraphics(void){ +void Graphics::finalize() { curs_set(1); destroyBox(); endwin(); } -//Typical refresh function (ease the eye with a custom function instead of the actual one) -void refreshScreen(void){ - using namespace std::this_thread; // sleep_for, sleep_until - using namespace std::chrono; // nanoseconds, system_clock, seconds - sleep_for(nanoseconds(sleepTime)); +void Graphics::refreshScreen() { + using namespace std::this_thread; + using namespace std::chrono; + + sleep_for(nanoseconds(sleep_time_)); - refresh(); // just use the curses version ;p - wrefresh(_box); + refresh(); + wrefresh(box_); } -void printChar(int y, int x, graphics_input img){ - mvwaddch(_box, y, x, img); +void Graphics::printChar(int y, int x, int img) { + mvwaddch(box_, y, x, img); refresh(); - wrefresh(_box); + wrefresh(box_); } -void printMsg(int y, int x, char* str){ - if(y>0 && x>0) - mvwaddstr(_box, y, x, str); - else{ - if(y < 0) y = 2 + y; +void Graphics::printMsg(int y, int x, const std::string& str) { + if(y > 0 && x > 0) { + mvwaddstr(box_, y, x, str.c_str()); + } + else { + if(y < 0) y += 2; if(x < 0) x = 0; - mvaddstr(y, x, str); + mvaddstr(y, x, str.c_str()); } + refresh(); - wrefresh(_box); + wrefresh(box_); } -char readChar(int y, int x){ +char Graphics::readChar(int y, int x) { refresh(); - wrefresh(_box); - return mvwgetch(_box, y, x); + wrefresh(box_); + return mvwgetch(box_, y, x); } -int readInpt(){ +int Graphics::readInpt() { return getch(); } -void advanceDifficulty(void){ - if(sleepTime > 28000000) // we set 28000000 as teh min sleep time - sleepTime -= 1000000; +void Graphics::advanceDifficulty() { + if(sleep_time_ > 28000000) { + sleep_time_ -= 1000000; + } +} + +Graphics& Graphics::get() { + static Graphics graphics; + return graphics; } \ No newline at end of file diff --git a/input-output/Graphics.h b/input-output/Graphics.h index 129c1d1..47b70aa 100755 --- a/input-output/Graphics.h +++ b/input-output/Graphics.h @@ -1,26 +1,39 @@ #pragma once #include +#include -#define UP KEY_UP -#define DOWN KEY_DOWN -#define LEFT KEY_LEFT -#define RIGHT KEY_RIGHT -#define EXIT_GAME 'q' -typedef int graphics_input; +static constexpr int UP = KEY_UP; +static constexpr int DOWN = KEY_DOWN; +static constexpr int LEFT = KEY_LEFT; +static constexpr int RIGHT = KEY_RIGHT; +static constexpr int EXIT_GAME = 'q'; +static constexpr int GAME_TOP_WALL_Y = 1; +const int GAME_BOTTOM_WALL_Y = LINES - 4; +static constexpr int GAME_LEFT_WALL_X = 1; +const int GAME_RIGHT_WALL_X = COLS - 2; -#define GAME_TOP_WALL_Y 1 -#define GAME_BOTTOM_WALL_Y (LINES - 4) -#define GAME_LEFT_WALL_X 1 -#define GAME_RIGHT_WALL_X (COLS - 2) +class Graphics { +private: + unsigned int sleep_time_ = 40000000; + WINDOW* box_ = NULL; -void initializeGraphics(char* gameName); -void endGraphics(void); -void refreshScreen(void); -void printChar(int y, int x, graphics_input img); -void printMsg(int y, int x, char *str); -char readChar(int y, int x); -int readInpt(); + Graphics(); + void createBox(); + void destroyBox(); + +public: + static Graphics& get(); + void init(const std::string& game_name); + void finalize(); + + void refreshScreen(); + void printChar(int y, int x, int img); + void printMsg(int y, int x, const std::string& str); + char readChar(int y, int x); + int readInpt(); + + void advanceDifficulty(); +}; -void advanceDifficulty(void); \ No newline at end of file diff --git a/input-output/Player.cpp b/input-output/Player.cpp index 5d09297..502450f 100644 --- a/input-output/Player.cpp +++ b/input-output/Player.cpp @@ -1,43 +1,32 @@ #include "Player.h" -using namespace std; - -Player::Player() -: name{"Unknown"}, points{0}, timesPlayed{0} -{} - -Player::Player(string _name) -: name{_name}, points{0}, timesPlayed{0} +Player::Player(std::string name) + : name_{name} {} -Player::~Player() -{/* No need to do something */} - -string Player::getName(void){ - return this->name; +const std::string& Player::getName() const { + return name_; } -void Player::addPoints(unsigned int _points){ - points += _points; +uint32_t Player::getHighScore() const { + return high_score_; } -unsigned int Player::getPoints(void){ - return this->points; -} - -std::pair Player::play(void){ - //here we will implement the basic loop of the game since each player has its remote controller - //and can play the game +void Player::play(){ Controller controller; - while (controller.wantsToQuit() == false) - { + + while (controller.wantsToQuit() == false) { controller.readInput(); - if (controller.act() == DEFEAT) + + if (controller.act() == DEFEAT) { break; + } } - points = controller.getCurrScore(); + const uint32_t score = controller.getCurrScore(); controller.resetScore(); - return {this->name, points}; + if (score > high_score_) { + high_score_ = score; + } } \ No newline at end of file diff --git a/input-output/Player.h b/input-output/Player.h index 481c496..61b7fad 100755 --- a/input-output/Player.h +++ b/input-output/Player.h @@ -7,20 +7,15 @@ class Player{ private: - std::string name; - unsigned int points; - unsigned int timesPlayed; - -public: - Player(); - Player(std::string _name); - ~Player(); + std::string name_; + uint32_t high_score_ = 0; + uint32_t timesPlayed_ = 0; - std::pair play(void); +public: + Player(std::string name); - //Point managment methods - unsigned int getPoints(void); - void addPoints(unsigned int _points); + void play(); - std::string getName(void); + uint32_t getHighScore() const; + const std::string& getName() const; }; \ No newline at end of file