Browse Source

rewrite the game with my code styling and modern c++ view

master
Constantin Fürst 8 months ago
parent
commit
59796d33b0
  1. 64
      components/Point.cpp
  2. 30
      components/Point.h
  3. 27
      components/Snack.cpp
  4. 6
      components/Snack.h
  5. 196
      components/Snake.cpp
  6. 40
      components/Snake.h
  7. 83
      game/Controller.cpp
  8. 28
      game/Controller.h
  9. 87
      game/Game.cpp
  10. 32
      game/Game.h
  11. 99
      input-output/Graphics.cpp
  12. 45
      input-output/Graphics.h
  13. 43
      input-output/Player.cpp
  14. 19
      input-output/Player.h

64
components/Point.cpp

@ -1,58 +1,50 @@
#include <iostream>
#include <string>
#include "Point.h" #include "Point.h"
/*snake will be an array of points*/
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(uint32_t y, uint32_t x, int img)
: x_ {x}, y_ {y}, img_ {img}
{ } { }
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_ = ' ';
} }

30
components/Point.h

@ -4,23 +4,25 @@
class Point{ class Point{
private: private:
int x;
int y;
graphics_input img;
uint32_t x_;
uint32_t y_;
int img_;
public: 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 moveUp();
void moveDown(); void moveDown();
void moveLeft(); void moveLeft();
void moveRight(); 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();
}; };

27
components/Snack.cpp

@ -1,22 +1,17 @@
#include "Snack.h" #include "Snack.h"
#include <cstdlib>
using namespace std;
#include <random>
void generateSnack(Point* snack){
std::random_device dev;
static std::mt19937 prng(dev());
static std::uniform_int_distribution<std::mt19937::result_type> distX(0, GAME_RIGHT_WALL_X);
static std::uniform_int_distribution<std::mt19937::result_type> distY(0, GAME_BOTTOM_WALL_Y);
const unsigned int snackScore = 10;
const uint32_t x = distX(prng);
const uint32_t y = distY(prng);
void generateSnack(Point &snack){
int x, y;
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();
} }

6
components/Snack.h

@ -2,8 +2,6 @@
#include "Point.h" #include "Point.h"
#define SNACK '*'
static constexpr int SNACK_CHAR = '*';
//snack methods
void generateSnack(Point &snack);
unsigned int getSnackScore(void);
void generateSnack(Point* snack);

196
components/Snake.cpp

@ -1,38 +1,35 @@
#include "Snake.h" #include "Snake.h"
#include <iostream> #include <iostream>
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<Point>::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; return true;
body_part++;
}
} }
return false; 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) || return (head.getY() < GAME_TOP_WALL_Y) ||
(head.getY() > GAME_BOTTOM_WALL_Y) || (head.getY() > GAME_BOTTOM_WALL_Y) ||
@ -40,119 +37,122 @@ bool Snake::hasCrashedWall(void){
(head.getX() > GAME_RIGHT_WALL_X); (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();
void Snake::incSize(){
const auto tail = std::prev(snake_.end());
const uint32_t tailX = tail->getX();
const uint32_t 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();
const auto prev = std::prev(tail);
const uint32_t prevX = prev->getX();
const uint32_t prevY = prev->getY();
if (prevY == tailY){ 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::updateHead(void){
auto head = snake.begin();
switch (this->direction)
{
// 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(){
switch (direction_) {
case UP: case UP:
head->moveUp();
snake_.front().moveUp();
break; break;
case DOWN: case DOWN:
head->moveDown();
snake_.front().moveDown();
break; break;
case LEFT: case LEFT:
head->moveLeft();
snake_.front().moveLeft();
break; break;
case RIGHT: case RIGHT:
head->moveRight();
snake_.front().moveRight();
break; break;
} }
} }
void Snake::printSnake(void){
void Snake::printSnake() const {
//We print each element of the snake-list //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(), ' ');
void Snake::move(){
// updates the tail by clearing it since
// the snake moved forward (overwrites with ' ')
snake_.back().clear();
//and now we have to update all the other nodes of the body
// 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
auto bodyP1 = tail;
auto bodyP2 = --tail;
while(bodyP2 != snake.begin()){
*bodyP1 = *bodyP2;
bodyP1--;
bodyP2--;
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();
} }

40
components/Snake.h

@ -1,34 +1,34 @@
#pragma once #pragma once
#include <vector>
#include "Point.h" #include "Point.h"
#include "Snack.h" #include "Snack.h"
#include <list>
static constexpr int SNAKE_BODY_CHAR = 'o';
static constexpr uint32_t SNAKE_DEFAULT_SIZE = 4;
#define BODY 'o'
class Snake{ class Snake{
private: private:
std::list<Point> 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<Point> 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();
}; };

83
game/Controller.cpp

@ -1,86 +1,69 @@
#include "Controller.h" #include "Controller.h"
#include <assert.h>
#include <string>
using namespace std;
#include <string>
Controller::Controller() Controller::Controller()
: snack{SNACK} ,inpt{0}, currentScore{0}
{
snake = new Snake();
generateSnack(snack);
}
Controller::Controller(Snake *_snake)
: snake{_snake}, snack{SNACK}, inpt{0}, currentScore{0}
: input_{0}, score_{0}, snack_{Point(0,0,0)}
{ {
assert(this->snake != NULL);
generateSnack(&snack_);
} }
unsigned int Controller::getCurrScore(void){
return this->currentScore;
uint32_t Controller::getCurrScore() const {
return score_;
} }
void Controller::resetScore(void){
this->currentScore = 0;
void Controller::resetScore() {
score_ = 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){
int Controller::act() {
if (snake_.hasBitSnack(snack_.getY(), snack_.getX())) {
score_ += 10;
snake_.incSize();
if (snake->hasBitSnack(this->snack.getY(), this->snack.getX()) == true)
{
this->currentScore += 10;
generateSnack(&snack_);
Graphics::get().advanceDifficulty();
advanceDifficulty();
generateSnack(this->snack);
this->snake->incSize();
printScore(currentScore);
printScore(score_);
} }
switch (this->inpt)
{
switch (input_) {
case UP: case UP:
snake->moveUp();
snake_.moveUp();
break; break;
case DOWN: case DOWN:
snake->moveDown();
snake_.moveDown();
break; break;
case LEFT: case LEFT:
snake->moveLeft();
snake_.moveLeft();
break; break;
case RIGHT: case RIGHT:
snake->moveRight();
snake_.moveRight();
break; break;
default: 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 DEFEAT;
}
return 0; 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;
bool Controller::wantsToQuit() const {
return input_ == EXIT_GAME;
} }

28
game/Controller.h

@ -1,27 +1,31 @@
#pragma once #pragma once
#include <memory>
#include "../input-output/Graphics.h" #include "../input-output/Graphics.h"
#include "../components/Snake.h" #include "../components/Snake.h"
#include "../components/Point.h" #include "../components/Point.h"
#define DEFEAT -1
static constexpr int DEFEAT = -1;
class Controller { class Controller {
private: 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: public:
Controller(Snake* _snake);
Controller(); 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;
}; };

87
game/Game.cpp

@ -1,77 +1,64 @@
#include "Game.h" #include "Game.h"
#include <algorithm> #include <algorithm>
#include <limits.h> #include <limits.h>
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<string, unsigned int> 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(curBest.second > highScore){
highScore = curBest.second;
bestPlayer = curBest.first;
if (find == players_.end()) {
players_.emplace_back(Player(name));
find = std::prev(players_.end());
} }
cout << "Highscore: " << highScore << " by " << bestPlayer << "\n" <<endl;
}
Graphics::get().init(game_name_);
void SnakeGame::play(void){
while(1){
string playerName;
cout << "Who's playing: ";
cin >> playerName;
cout << endl;
list<Player>::iterator p;
for(p=players.begin(); p!=players.end(); p++){
if(p->getName() == playerName)
break;
find->play();
Graphics::get().finalize();
if (find->getHighScore() > high_score_){
high_score_ = find->getHighScore();
best_player_ = find->getName();
} }
if(p == players.end()){
//if the player isn't in the list, add him/her
addPlayer(playerName);
std::cout << "Highscore: " << high_score_ << " by " << best_player_ << std::endl;
} }
void SnakeGame::play(){
while(1) {
std::string name;
std::cout << "Who's playing: ";
std::cin >> name;
std::cout << std::endl;
play(playerName); //get the player to play the game
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Do you want to play again? (yes or no): ";
string ans;
play(name);
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "Do you or someone else want to play again? (yes or no): ";
std::string ans;
cin >> ans;
std::cin >> ans;
if (ans != "yes") { if (ans != "yes") {
cout << "Exiting ..." << endl;
std::cout << "Exiting ..." << std::endl;
break; break;
} }
cout << "Perfect...\n" << endl;
std::cout << "Perfect..." << std::endl;
} }
} }

32
game/Game.h

@ -1,31 +1,27 @@
#pragma once #pragma once
#include <string>
#include <vector>
#include "Controller.h" #include "Controller.h"
#include "../components/Snake.h" #include "../components/Snake.h"
#include "../input-output/Player.h" #include "../input-output/Player.h"
#include <string>
class SnakeGame{ class SnakeGame{
private: private:
std::string gameName;
std::list<Player> players;
unsigned int highScore;
std::string bestPlayer;
const std::string game_name_ = "Snake Game for C++ Course";
std::vector<Player> players_;
void play(std::string playerName);
void addPlayer(std::string playerName);
public:
SnakeGame(); //intialize graphics and set the game screen
~SnakeGame();
uint32_t high_score_ = 0;
std::string best_player_ = "None";
void play(const std::string& name);
void addPlayer(const std::string& name);
unsigned int getHighScore(void);
std::string getBestPlayer(void);
//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();
}; };

99
input-output/Graphics.cpp

@ -4,86 +4,89 @@
#include <time.h> #include <time.h>
#include <cstdlib> #include <cstdlib>
///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)); 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); nodelay(stdscr, true);
curs_set(0); //to hide the cursor
//We must clear the screen from unecessary garbage
curs_set(0);
clear(); clear();
//Print the title
mvprintw(0, (COLS/2) - 12, gameName);
mvprintw(0, (COLS/2) - 12, gameName.c_str());
refresh(); refresh();
//create the game box
createBox(); createBox();
} }
//Exit function
void endGraphics(void){
void Graphics::finalize() {
curs_set(1); curs_set(1);
destroyBox(); destroyBox();
endwin(); 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(); refresh();
wrefresh(_box);
wrefresh(box_);
} }
void printMsg(int y, int x, char* str){
if(y>0 && x>0)
mvwaddstr(_box, y, x, str);
void Graphics::printMsg(int y, int x, const std::string& str) {
if(y > 0 && x > 0) {
mvwaddstr(box_, y, x, str.c_str());
}
else { else {
if(y < 0) y = 2 + y;
if(y < 0) y += 2;
if(x < 0) x = 0; if(x < 0) x = 0;
mvaddstr(y, x, str);
mvaddstr(y, x, str.c_str());
} }
refresh(); refresh();
wrefresh(_box);
wrefresh(box_);
} }
char readChar(int y, int x){
char Graphics::readChar(int y, int x) {
refresh(); refresh();
wrefresh(_box);
return mvwgetch(_box, y, x);
wrefresh(box_);
return mvwgetch(box_, y, x);
} }
int readInpt(){
int Graphics::readInpt() {
return getch(); 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;
} }

45
input-output/Graphics.h

@ -1,26 +1,39 @@
#pragma once #pragma once
#include <curses.h> #include <curses.h>
#include <string>
#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);
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); char readChar(int y, int x);
int readInpt(); int readInpt();
void advanceDifficulty(void);
void advanceDifficulty();
};

43
input-output/Player.cpp

@ -1,43 +1,32 @@
#include "Player.h" #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;
}
void Player::addPoints(unsigned int _points){
points += _points;
const std::string& Player::getName() const {
return name_;
} }
unsigned int Player::getPoints(void){
return this->points;
uint32_t Player::getHighScore() const {
return high_score_;
} }
std::pair<std::string, unsigned int> 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; Controller controller;
while (controller.wantsToQuit() == false)
{
while (controller.wantsToQuit() == false) {
controller.readInput(); controller.readInput();
if (controller.act() == DEFEAT)
if (controller.act() == DEFEAT) {
break; break;
} }
}
points = controller.getCurrScore();
const uint32_t score = controller.getCurrScore();
controller.resetScore(); controller.resetScore();
return {this->name, points};
if (score > high_score_) {
high_score_ = score;
}
} }

19
input-output/Player.h

@ -7,20 +7,15 @@
class Player{ class Player{
private: private:
std::string name;
unsigned int points;
unsigned int timesPlayed;
std::string name_;
uint32_t high_score_ = 0;
uint32_t timesPlayed_ = 0;
public: public:
Player();
Player(std::string _name);
~Player();
Player(std::string name);
std::pair<std::string, unsigned int> play(void);
void play();
//Point managment methods
unsigned int getPoints(void);
void addPoints(unsigned int _points);
std::string getName(void);
uint32_t getHighScore() const;
const std::string& getName() const;
}; };
Loading…
Cancel
Save