forked from University/epr24pr42-ojanssen2
Reset Exercise
This commit is contained in:
parent
882695c6b6
commit
d48e9d7b28
20 changed files with 380 additions and 1110 deletions
|
@ -1,108 +0,0 @@
|
|||
#include "Game.h"
|
||||
#include "Maze.h"
|
||||
#include "../Exceptions/MovementNotPossible.h"
|
||||
#include "../Exceptions/UnkownAction.h"
|
||||
#include "../Util/Vector2d.h"
|
||||
|
||||
using game::Player;
|
||||
using game::Maze;
|
||||
using game_exceptions::UnkownAction;
|
||||
using game_exceptions::MovementNotPossible;
|
||||
|
||||
namespace game
|
||||
{
|
||||
Game::Game(Maze& maze) : maze(maze), player(0, 0), enemies({}), state(GameState::RUNNING), infomode_enabled(false)
|
||||
{
|
||||
Vector2d player_start_position = this->maze.get_player_start_position();
|
||||
|
||||
this->player = Player(player_start_position);
|
||||
this->enemies = maze.get_entities();
|
||||
}
|
||||
|
||||
GameState Game::get_state() const {
|
||||
return this->state;
|
||||
}
|
||||
|
||||
void Game::handle_user_input(const char& input)
|
||||
{
|
||||
switch (input)
|
||||
{
|
||||
case 'w':
|
||||
case 'a':
|
||||
case 's':
|
||||
case 'd':
|
||||
break;
|
||||
case 'i':
|
||||
this->infomode_enabled = !this->infomode_enabled;
|
||||
break;
|
||||
case 'q':
|
||||
this->state = GameState::QUITTING;
|
||||
break;
|
||||
case 'h':
|
||||
cout <<
|
||||
"Du wurdest von einem Zauberer in ein Labyrinth gesperrt, nachdem du seine Künste beleidigt hast.\n"
|
||||
<< "Er laesst dich leben, wenn du es schaffst den Ausgang (Z) zu finden. Solltest du keinen Erfolg haben, laesst er dich verhungern.\n"
|
||||
<< "Auf deinem Abenteuer wirst du dabei boesen Geistern (A) begegnen und mit Schluesseln (K) Tueren (T) aufschliessen.\n"
|
||||
<< "Bewege dich mit 'w', 'a', 's' und 'd'.\n";
|
||||
break;
|
||||
default:
|
||||
throw UnkownAction("Diese Eingabe kenne ich nicht. Gib 'h' ein, um eine Hilfe zu erhalten.");
|
||||
}
|
||||
}
|
||||
|
||||
bool Game::is_enemy_at_pos(const Vector2d& position) const {
|
||||
for (Entity e : this->enemies)
|
||||
if (e.is_at_position(position))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Game::should_end_game() const
|
||||
{
|
||||
return this->state != GameState::RUNNING;
|
||||
}
|
||||
|
||||
void Game::run_game()
|
||||
{
|
||||
char game_input;
|
||||
|
||||
// Hauptschleife
|
||||
while (true)
|
||||
{
|
||||
this->maze.render(this->player, this->enemies, this->infomode_enabled);
|
||||
|
||||
if (this->maze.is_player_at_goal(this->player))
|
||||
{
|
||||
cout << "Ziel erreicht! Herzlichen Glueckwunsch!\n";
|
||||
break;
|
||||
}
|
||||
|
||||
cin >> game_input;
|
||||
|
||||
if (!cin)
|
||||
this->state = GameState::QUITTING;
|
||||
|
||||
try
|
||||
{
|
||||
this->handle_user_input(game_input);
|
||||
this->player.handle_user_input(this->maze, game_input);
|
||||
} catch (UnkownAction& err)
|
||||
{
|
||||
cout << err.what() << "\n";
|
||||
} catch (MovementNotPossible& err)
|
||||
{
|
||||
cout << err.what() << "\n";
|
||||
}
|
||||
|
||||
this->state = this->player.tick(*this, this->maze);
|
||||
|
||||
for (Entity& e : this->enemies)
|
||||
e.tick(this->maze, this->player.get_pos());
|
||||
|
||||
this->state = this->player.tick(*this, this->maze);
|
||||
|
||||
if (this->should_end_game())
|
||||
return;
|
||||
}
|
||||
}
|
||||
} // game
|
|
@ -1,52 +0,0 @@
|
|||
#include "Maze.h"
|
||||
#include "../Entities/Player.h"
|
||||
#include "../Util/GameState.h"
|
||||
#include "../Entities/Entity.h"
|
||||
|
||||
#ifndef GAME_H
|
||||
#define GAME_H
|
||||
|
||||
namespace game
|
||||
{
|
||||
/// Eine Instanz des Spiels
|
||||
class Game
|
||||
{
|
||||
private:
|
||||
/// Das Labyrinth
|
||||
Maze maze;
|
||||
/// Der Spieler
|
||||
Player player;
|
||||
/// Die Gegner des Spieles
|
||||
vector<Entity> enemies;
|
||||
/// Der Status des Spiels
|
||||
GameState state;
|
||||
///
|
||||
bool infomode_enabled;
|
||||
|
||||
public:
|
||||
explicit Game(Maze& maze);
|
||||
|
||||
/// Bearbeite die Eingabe des Spielers
|
||||
/// @param input Die Eingabe des Nutzers
|
||||
/// @return Der Bewegungsvektor, um den sich den Spieler bewegen möchte
|
||||
/// @throws UnkownAction Wenn die Eingabe des Spielers unbekannt ist
|
||||
void handle_user_input(const char& input);
|
||||
|
||||
/// Kontrolliere, ob das Spiel beendet werden sollte
|
||||
bool should_end_game() const;
|
||||
|
||||
/// Starte das Spiel
|
||||
void run_game();
|
||||
|
||||
/// Kriege den aktuellen Status des Spiels
|
||||
/// @returns Den aktuellen Status
|
||||
GameState get_state() const;
|
||||
|
||||
/// Krontroliere ob ein Geist sich an einer Position befindet
|
||||
/// @param position Die Position
|
||||
/// @returns Ob sich dort ein Geist aufhält
|
||||
bool is_enemy_at_pos(const Vector2d& position) const ;
|
||||
};
|
||||
} // game
|
||||
|
||||
#endif //GAME_H
|
|
@ -1,115 +0,0 @@
|
|||
#include "Maze.h"
|
||||
#include "../Entities/Player.h"
|
||||
#include "../Exceptions/MalformedMaze.h"
|
||||
#include "../Entities/Entity.h"
|
||||
#include "../Util/MathUtil.h"
|
||||
|
||||
using game_exceptions::MalformedMaze;
|
||||
|
||||
namespace game
|
||||
{
|
||||
class MathUtil;
|
||||
|
||||
Maze::Maze(const vector<vector<char>>& play_field, const vector<int>& player_start_position, const vector<Entity>& enemies):
|
||||
field(play_field),
|
||||
player_start_position(Vector2d{player_start_position[1], player_start_position[0]}),
|
||||
enemies(enemies)
|
||||
{
|
||||
if (!this->is_pos_free(this->player_start_position, false))
|
||||
throw MalformedMaze("Player oob");
|
||||
}
|
||||
|
||||
bool Maze::was_player_killed_by_ghost(const Player& player) const
|
||||
{
|
||||
return this->field[player.get_pos().y][player.get_pos().x] == 'A';
|
||||
}
|
||||
|
||||
bool Maze::is_player_at_goal(const Player& player) const
|
||||
{
|
||||
return this->field[player.get_pos().y][player.get_pos().x] == 'Z';
|
||||
}
|
||||
|
||||
bool Maze::is_pos_free(const Vector2d& pos, const bool& player_has_key) const
|
||||
{
|
||||
if (pos.x < 0 || pos.y < 0 || pos.y > field.size() - 1 || pos.x > field[pos.y].size() - 1)
|
||||
return false;
|
||||
if (field[pos.y][pos.x] == '#')
|
||||
return false;
|
||||
if (field[pos.y][pos.x] == 'T')
|
||||
return player_has_key;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Maze::render(const Player& player, const vector<Entity>& entities, const bool& infomode_enabled)
|
||||
{
|
||||
for (int y = 0; y < field.size(); ++y)
|
||||
{
|
||||
for (int x = 0; x < field[y].size(); ++x)
|
||||
{
|
||||
if (y == player.get_pos().y && x == player.get_pos().x)
|
||||
cout << "S";
|
||||
else {
|
||||
bool an_enemy_is_at_this_position = false;
|
||||
for (Entity e : entities)
|
||||
if (e.is_at_position({x, y})) {
|
||||
an_enemy_is_at_this_position = true;
|
||||
cout << e.get_display_character();
|
||||
}
|
||||
if (!an_enemy_is_at_this_position)
|
||||
cout << field[y][x];
|
||||
}
|
||||
cout << " ";
|
||||
}
|
||||
if (y == 0 && infomode_enabled)
|
||||
{
|
||||
const int steps = this->calculate_steps_until_win(player.get_pos(), 5);
|
||||
if (steps < 999)
|
||||
cout << steps << " Schritte bis zum Ziel";
|
||||
}
|
||||
cout << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
char Maze::get_field(const Vector2d& pos) const
|
||||
{
|
||||
return this->field[pos.y][pos.x];
|
||||
}
|
||||
|
||||
void Maze::update_field(const Vector2d& pos, const char& target)
|
||||
{
|
||||
this->field[pos.y][pos.x] = target;
|
||||
}
|
||||
|
||||
Vector2d Maze::get_player_start_position() const
|
||||
{
|
||||
return this->player_start_position;
|
||||
}
|
||||
|
||||
Vector2d Maze::get_delta_vector(const Vector2d& pos1, const Vector2d& pos2) const {
|
||||
int x_diff = pos1.x - pos2.x;
|
||||
int y_diff = pos1.y - pos2.y;
|
||||
|
||||
return {x_diff, y_diff};
|
||||
}
|
||||
|
||||
int Maze::calculate_steps_until_win(Vector2d position, const int& steps) {
|
||||
if (!this->is_pos_free(position, false))
|
||||
return 999;
|
||||
if (this->get_field(position) == 'Z')
|
||||
return 0;
|
||||
if (steps <= 0)
|
||||
return 999;
|
||||
|
||||
vector<int> i;
|
||||
i.push_back(this->calculate_steps_until_win(position.get_new_updated(0, -1), steps - 1));
|
||||
i.push_back(this->calculate_steps_until_win(position.get_new_updated(0, 1), steps - 1));
|
||||
i.push_back(this->calculate_steps_until_win(position.get_new_updated(1, 0), steps - 1));
|
||||
i.push_back(this->calculate_steps_until_win(position.get_new_updated(-1, 0), steps - 1));
|
||||
|
||||
return MathUtil::get_min(i) + 1;
|
||||
}
|
||||
|
||||
vector<Entity> Maze::get_entities() {
|
||||
return this->enemies;
|
||||
}
|
||||
} // game
|
|
@ -1,80 +0,0 @@
|
|||
#include "../std_lib_inc.h"
|
||||
#include "../Util/Vector2d.h"
|
||||
|
||||
#ifndef MAZE_H
|
||||
#define MAZE_H
|
||||
|
||||
namespace game
|
||||
{
|
||||
class Player;
|
||||
class Entity;
|
||||
|
||||
/// Ein Labyrinth.
|
||||
/// Besitzt ein Feld
|
||||
class Maze
|
||||
{
|
||||
// class -> members private by default
|
||||
private:
|
||||
/// Das Spielfeld
|
||||
vector<vector<char>> field;
|
||||
/// Die Startposition des Spielers
|
||||
Vector2d player_start_position;
|
||||
/// Eine Liste an Gegnern
|
||||
vector<Entity> enemies;
|
||||
|
||||
public:
|
||||
/// Das Spielfeld
|
||||
Maze(const Vector<Vector<char>>& play_field, const Vector<int>& player_start_position, const Vector<Entity>& enemies);
|
||||
/// Kontrolliere, ob der Spieler stirbt
|
||||
/// @param player Der Spieler
|
||||
/// @return Ob der Spieler tot ist
|
||||
bool was_player_killed_by_ghost(const Player& player) const;
|
||||
|
||||
/// Kontrolliere, ob der Spieler am Ziel ist
|
||||
/// @param player Der Spieler
|
||||
/// @return Ob der Spieler am Ziel ist
|
||||
bool is_player_at_goal(const Player& player) const;
|
||||
|
||||
/// Kontrolliere, ob eine bestimmte Position begehbar ist
|
||||
/// @param pos Die Position, die überprüft werden soll
|
||||
/// @param player_has_key If the player has at least one key
|
||||
/// @return Ob die Position begehbar ist
|
||||
bool is_pos_free(const Vector2d& pos, const bool& player_has_key) const;
|
||||
|
||||
/// Zeige das Spielfeld in der Konsole an
|
||||
/// @param player Der Spieler
|
||||
/// @param entities Die Entities auf dem Spielfeld
|
||||
/// @param infomode_enabled Ob der Infomode aktiv ist
|
||||
void render(const Player& player, const vector<Entity>& entities, const bool& infomode_enabled);
|
||||
|
||||
/// Kriege den Wert einer Position
|
||||
/// @param pos Die gewollte Position
|
||||
/// @return Der Wert der Position
|
||||
char get_field(const Vector2d& pos) const;
|
||||
|
||||
/// Ersetze den Wert von einer Position
|
||||
/// @param pos Die Position die ersetzt werden soll
|
||||
/// @param target Der Wert, auf den die Position gesetzt werden soll
|
||||
void update_field(const Vector2d& pos, const char& target);
|
||||
|
||||
/// Kriege die Startposition des Spielers
|
||||
/// @return Die Startposition des Spielers
|
||||
Vector2d get_player_start_position() const;
|
||||
|
||||
/// Berrechne den Abstand zwischen zwei Vektoren
|
||||
/// @return Der Abstand als Differenzvektor
|
||||
Vector2d get_delta_vector(const Vector2d& pos1, const Vector2d& pos2) const;
|
||||
|
||||
/// Berechne wie viele Schritte benötigt werden, um das Labyrinth zu schaffen
|
||||
/// @warning Steps nicht zu groß setzen! Diese Funktion ist 4-fach rekursiv!
|
||||
/// @param position Die Startposition
|
||||
/// @param steps Wie viele Schritte maximal gegangen werden sollten
|
||||
/// @returns Wie viele Schritte benötigt werden
|
||||
int calculate_steps_until_win(Vector2d position, const int& steps);
|
||||
|
||||
/// Kriege alle eingelesenen Entities
|
||||
vector<Entity> get_entities();
|
||||
};
|
||||
} // game
|
||||
|
||||
#endif //MAZE_H
|
Loading…
Add table
Add a link
Reference in a new issue