Constantin Fürst
8 months ago
14 changed files with 390 additions and 433 deletions
-
66components/Point.cpp
-
30components/Point.h
-
27components/Snack.cpp
-
6components/Snack.h
-
200components/Snake.cpp
-
40components/Snake.h
-
83game/Controller.cpp
-
30game/Controller.h
-
89game/Game.cpp
-
32game/Game.h
-
101input-output/Graphics.cpp
-
49input-output/Graphics.h
-
43input-output/Player.cpp
-
19input-output/Player.h
@ -1,58 +1,50 @@ |
|||
#include <iostream>
|
|||
#include <string>
|
|||
#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_ = ' '; |
|||
} |
@ -1,22 +1,17 @@ |
|||
#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(); |
|||
} |
@ -1,34 +1,34 @@ |
|||
#pragma once |
|||
|
|||
#include <vector> |
|||
|
|||
#include "Point.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{ |
|||
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(); |
|||
}; |
@ -1,86 +1,69 @@ |
|||
#include "Controller.h"
|
|||
#include <assert.h>
|
|||
#include <string>
|
|||
|
|||
using namespace std; |
|||
#include <string>
|
|||
|
|||
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){ |
|||
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: |
|||
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; |
|||
bool Controller::wantsToQuit() const { |
|||
return input_ == EXIT_GAME; |
|||
} |
@ -1,27 +1,31 @@ |
|||
#pragma once |
|||
|
|||
#include <memory> |
|||
|
|||
#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; |
|||
}; |
@ -1,77 +1,64 @@ |
|||
#include "Game.h"
|
|||
|
|||
#include <algorithm>
|
|||
#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; |
|||
find->play(); |
|||
|
|||
Graphics::get().finalize(); |
|||
|
|||
list<Player>::iterator p; |
|||
for(p=players.begin(); p!=players.end(); p++){ |
|||
if(p->getName() == playerName) |
|||
break; |
|||
} |
|||
|
|||
if(p == players.end()){ |
|||
//if the player isn't in the list, add him/her
|
|||
addPlayer(playerName); |
|||
if (find->getHighScore() > high_score_){ |
|||
high_score_ = find->getHighScore(); |
|||
best_player_ = find->getName(); |
|||
} |
|||
|
|||
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"){ |
|||
cout << "Exiting ..." << endl; |
|||
if (ans != "yes") { |
|||
std::cout << "Exiting ..." << std::endl; |
|||
break; |
|||
} |
|||
cout << "Perfect...\n" << endl; |
|||
|
|||
std::cout << "Perfect..." << std::endl; |
|||
} |
|||
} |
@ -1,31 +1,27 @@ |
|||
#pragma once |
|||
|
|||
#include <string> |
|||
#include <vector> |
|||
|
|||
#include "Controller.h" |
|||
#include "../components/Snake.h" |
|||
#include "../input-output/Player.h" |
|||
|
|||
#include <string> |
|||
|
|||
class SnakeGame{ |
|||
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(); |
|||
}; |
@ -1,26 +1,39 @@ |
|||
#pragma once |
|||
|
|||
#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); |
|||
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); |
@ -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; |
|||
} |
|||
|
|||
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; |
|||
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; |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue