feat!: made code worse, due to skill issues by the tutors
This commit is contained in:
parent
45c45058b8
commit
5d07d946a0
16 changed files with 304 additions and 647 deletions
|
@ -8,18 +8,4 @@ include_directories(.)
|
|||
add_executable(epr24pr3_ojanssen2
|
||||
main.cpp
|
||||
std_lib_inc.h
|
||||
Player.cpp
|
||||
Player.h
|
||||
PositionVector.cpp
|
||||
PositionVector.h
|
||||
Maze.h
|
||||
Maze.cpp
|
||||
MazeParser.h
|
||||
MazeParser.cpp
|
||||
Game.h
|
||||
Game.cpp
|
||||
Exceptions/MovementNotPossible.h
|
||||
Exceptions/MalformedMaze.h
|
||||
Exceptions/UnkownAction.h
|
||||
Exceptions/ExitGame.h
|
||||
)
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
#ifndef EXITGAME_H
|
||||
#define EXITGAME_H
|
||||
|
||||
namespace game_exceptions
|
||||
{
|
||||
class ExitGame
|
||||
{
|
||||
string why;
|
||||
|
||||
public:
|
||||
ExitGame(string why): why(why)
|
||||
{
|
||||
}
|
||||
|
||||
string what()
|
||||
{
|
||||
return this->why;
|
||||
}
|
||||
};
|
||||
} // game_exceptions
|
||||
|
||||
#endif //EXITGAME_H
|
|
@ -1,22 +0,0 @@
|
|||
#ifndef MALFORMEDMAZE_H
|
||||
#define MALFORMEDMAZE_H
|
||||
|
||||
namespace game_exceptions
|
||||
{
|
||||
class MalformedMaze
|
||||
{
|
||||
string why;
|
||||
|
||||
public:
|
||||
MalformedMaze(string why): why(why)
|
||||
{
|
||||
}
|
||||
|
||||
string what()
|
||||
{
|
||||
return this->why;
|
||||
}
|
||||
};
|
||||
} // game_exceptions
|
||||
|
||||
#endif //MALFORMEDMAZE_H
|
|
@ -1,22 +0,0 @@
|
|||
#ifndef MOVEMENTNOTPOSSIBLE_H
|
||||
#define MOVEMENTNOTPOSSIBLE_H
|
||||
|
||||
namespace game_exceptions
|
||||
{
|
||||
class MovementNotPossible
|
||||
{
|
||||
string why;
|
||||
|
||||
public:
|
||||
MovementNotPossible(string why): why(why)
|
||||
{
|
||||
}
|
||||
|
||||
string what()
|
||||
{
|
||||
return this->why;
|
||||
}
|
||||
};
|
||||
} // game_exceptions
|
||||
|
||||
#endif //MOVEMENTNOTPOSSIBLE_H
|
|
@ -1,22 +0,0 @@
|
|||
#ifndef UNKOWNACTION_H
|
||||
#define UNKOWNACTION_H
|
||||
|
||||
namespace game_exceptions
|
||||
{
|
||||
class UnkownAction
|
||||
{
|
||||
string why;
|
||||
|
||||
public:
|
||||
UnkownAction(string why): why(why)
|
||||
{
|
||||
}
|
||||
|
||||
string what()
|
||||
{
|
||||
return this->why;
|
||||
}
|
||||
};
|
||||
} // game_exceptions
|
||||
|
||||
#endif //UNKOWNACTION_H
|
95
Game.cpp
95
Game.cpp
|
@ -1,95 +0,0 @@
|
|||
#include "Game.h"
|
||||
#include "Player.h"
|
||||
#include "Maze.h"
|
||||
#include "Exceptions/ExitGame.h"
|
||||
#include "Exceptions/MovementNotPossible.h"
|
||||
#include "Exceptions/UnkownAction.h"
|
||||
|
||||
using game::Player;
|
||||
using game::Maze;
|
||||
using game_exceptions::UnkownAction;
|
||||
using game_exceptions::MovementNotPossible;
|
||||
using game_exceptions::ExitGame;
|
||||
|
||||
namespace game
|
||||
{
|
||||
Game::Game(Maze& maze): maze(maze), player(0, 0)
|
||||
{
|
||||
PositionVector player_start_position = this->maze.get_player_start_position();
|
||||
|
||||
this->player = Player(player_start_position);
|
||||
}
|
||||
|
||||
PositionVector Game::handle_user_input(const char& input)
|
||||
{
|
||||
PositionVector movement_vector = PositionVector(0, 0);
|
||||
|
||||
switch (input)
|
||||
{
|
||||
case 'w':
|
||||
movement_vector.update(0, -1);
|
||||
break;
|
||||
case 'a':
|
||||
movement_vector.update(-1, 0);
|
||||
break;
|
||||
case 's':
|
||||
movement_vector.update(0, 1);
|
||||
break;
|
||||
case 'd':
|
||||
movement_vector.update(1, 0);
|
||||
break;
|
||||
case 'q':
|
||||
throw ExitGame("Schoenen Tag noch!");
|
||||
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.");
|
||||
}
|
||||
|
||||
return movement_vector;
|
||||
}
|
||||
|
||||
void Game::run_game()
|
||||
{
|
||||
char game_input;
|
||||
|
||||
// Hauptschleife
|
||||
while (true)
|
||||
{
|
||||
if (this->maze.was_player_killed_by_ghost(player))
|
||||
{
|
||||
cout << "Sie haben einen Geist getroffen! Game Over!\n";
|
||||
break;
|
||||
}
|
||||
|
||||
this->maze.render(player);
|
||||
|
||||
if (this->maze.is_player_at_goal(player))
|
||||
{
|
||||
cout << "Ziel erreicht! Herzlichen Glueckwunsch!\n";
|
||||
break;
|
||||
}
|
||||
|
||||
cin >> game_input;
|
||||
|
||||
PositionVector movement_vector = PositionVector(0, 0);
|
||||
|
||||
try
|
||||
{
|
||||
movement_vector = handle_user_input(game_input);
|
||||
player.move(this->maze, movement_vector);
|
||||
} catch (UnkownAction& err)
|
||||
{
|
||||
cout << err.what() << "\n";
|
||||
} catch (MovementNotPossible& err)
|
||||
{
|
||||
cout << err.what() << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
} // game
|
30
Game.h
30
Game.h
|
@ -1,30 +0,0 @@
|
|||
#include "Maze.h"
|
||||
#include "Player.h"
|
||||
|
||||
#ifndef GAME_H
|
||||
#define GAME_H
|
||||
|
||||
namespace game
|
||||
{
|
||||
/// Eine Instanz des Spiels
|
||||
class Game
|
||||
{
|
||||
private:
|
||||
Maze maze;
|
||||
Player player;
|
||||
|
||||
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
|
||||
static PositionVector handle_user_input(const char& input);
|
||||
|
||||
/// Starte das Spiel
|
||||
void run_game();
|
||||
};
|
||||
} // game
|
||||
|
||||
#endif //GAME_H
|
68
Maze.cpp
68
Maze.cpp
|
@ -1,68 +0,0 @@
|
|||
#include "Maze.h"
|
||||
#include "Player.h"
|
||||
#include "Exceptions/MalformedMaze.h"
|
||||
|
||||
using game_exceptions::MalformedMaze;
|
||||
|
||||
namespace game
|
||||
{
|
||||
Maze::Maze(const vector<vector<char>> play_field, const vector<int> player_start_position):
|
||||
field(play_field),
|
||||
player_start_position(PositionVector{player_start_position[1], player_start_position[0]})
|
||||
{
|
||||
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 PositionVector& 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
|
||||
{
|
||||
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
|
||||
cout << field[y][x];
|
||||
cout << " ";
|
||||
}
|
||||
cout << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
char Maze::get_field(const PositionVector& pos) const
|
||||
{
|
||||
return this->field[pos.y][pos.x];
|
||||
}
|
||||
|
||||
void Maze::update_field(const PositionVector& pos, const char& target)
|
||||
{
|
||||
this->field[pos.y][pos.x] = target;
|
||||
}
|
||||
|
||||
PositionVector Maze::get_player_start_position() const
|
||||
{
|
||||
return this->player_start_position;
|
||||
}
|
||||
} // game
|
62
Maze.h
62
Maze.h
|
@ -1,62 +0,0 @@
|
|||
#include "std_lib_inc.h"
|
||||
#include "PositionVector.h"
|
||||
|
||||
#ifndef MAZE_H
|
||||
#define MAZE_H
|
||||
|
||||
namespace game
|
||||
{
|
||||
class Player;
|
||||
|
||||
/// Ein Labyrinth.
|
||||
/// Besitzt ein Feld
|
||||
class Maze
|
||||
{
|
||||
// class -> members private by default
|
||||
private:
|
||||
/// Das Spielfeld
|
||||
vector<vector<char>> field;
|
||||
/// Die Startposition des Spielers
|
||||
PositionVector player_start_position;
|
||||
|
||||
public:
|
||||
/// Das Spielfeld
|
||||
Maze(vector<vector<char>> play_field, vector<int> player_start_position);
|
||||
|
||||
/// 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 PositionVector& pos, const bool& player_has_key) const;
|
||||
|
||||
/// Zeige das Spielfeld in der Konsole an
|
||||
/// @param player Der Spieler
|
||||
void render(const Player& player) const;
|
||||
|
||||
/// Kriege den Wert einer Position
|
||||
/// @param pos Die gewollte Position
|
||||
/// @return Der Wert der Position
|
||||
char get_field(const PositionVector& 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 PositionVector& pos, const char& target);
|
||||
|
||||
/// Kriege die Startposition des Spielers
|
||||
/// @return Die Startposition des Spielers
|
||||
PositionVector get_player_start_position() const;
|
||||
};
|
||||
} // game
|
||||
|
||||
#endif //MAZE_H
|
|
@ -1,68 +0,0 @@
|
|||
#include "MazeParser.h"
|
||||
#include "Maze.h"
|
||||
#include "Exceptions/ExitGame.h"
|
||||
#include "Exceptions/MalformedMaze.h"
|
||||
|
||||
using game_exceptions::MalformedMaze;
|
||||
using game_exceptions::ExitGame;
|
||||
|
||||
namespace game
|
||||
{
|
||||
vector<int> MazeParser::request_numbers_from_user(const int& amount_of_numbers)
|
||||
{
|
||||
int input;
|
||||
vector<int> list;
|
||||
|
||||
for (int i = 0; i < amount_of_numbers; ++i)
|
||||
{
|
||||
cin >> input;
|
||||
if (!cin)
|
||||
throw MalformedMaze("Cin failed while reading numbers!");
|
||||
|
||||
list.push_back(input);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
bool MazeParser::validate_maze_element(const char& target)
|
||||
{
|
||||
for (const char c : valid_maze_elements)
|
||||
if (c == target)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
Maze MazeParser::request_maze_from_user()
|
||||
{
|
||||
vector<int> maze_size = request_numbers_from_user(2);
|
||||
|
||||
char input;
|
||||
vector<vector<char>> field;
|
||||
|
||||
for (int y = 0; y < maze_size[0]; ++y)
|
||||
{
|
||||
vector<char> row;
|
||||
for (int x = 0; x < maze_size[1]; ++x)
|
||||
{
|
||||
cin >> input;
|
||||
if (!cin)
|
||||
throw MalformedMaze("Cin failed while reading chars!");
|
||||
|
||||
if (input == 'q')
|
||||
throw ExitGame("Schoenen Tag noch!");
|
||||
|
||||
if (!validate_maze_element(input))
|
||||
throw MalformedMaze("The given input is not a valid element of a maze!");
|
||||
|
||||
row.push_back(input);
|
||||
}
|
||||
|
||||
field.push_back(row);
|
||||
}
|
||||
|
||||
vector<int> player_start_pos = request_numbers_from_user(2);
|
||||
|
||||
return Maze(field, player_start_pos);
|
||||
} // Beispieleingabe: `4 3 #.# #.K #T# #Z# 0 1`
|
||||
} // game
|
43
MazeParser.h
43
MazeParser.h
|
@ -1,43 +0,0 @@
|
|||
#include "std_lib_inc.h"
|
||||
|
||||
#ifndef MAZEPARSER_H
|
||||
#define MAZEPARSER_H
|
||||
|
||||
/* Legende
|
||||
* S - Spieler
|
||||
* Z - Ziel
|
||||
* . - Leerer Raum (begehbar)
|
||||
* # - Wand
|
||||
* A - Geist
|
||||
* K - Schlüssel
|
||||
* T - Tür
|
||||
*/
|
||||
namespace game
|
||||
{
|
||||
/// Erlaubte Zeichen in einem Labyrinth
|
||||
/// Ist eine Konstante, darf also in global scope
|
||||
static const vector<char> valid_maze_elements = {'Z', '.', '#', 'A', 'K', 'T'};
|
||||
|
||||
class Maze;
|
||||
class MazeParser
|
||||
{
|
||||
private:
|
||||
/// Lese eine bestimmte Anzahl an Nummern aus der Konsole
|
||||
/// @param amount_of_numbers Wie viele Nummern eingelesen werden sollen
|
||||
/// @return Die eingelesenen Nummern
|
||||
static vector<int> request_numbers_from_user(const int& amount_of_numbers);
|
||||
|
||||
/// Kontrolliere, ob ein Zeichen im Labyrinth vorkommen darf
|
||||
/// @param target Das Zeichen, welches Kontrolliert werden soll
|
||||
/// @return Ob das gegebene Zeichen in einem Labyrinth vorkommen darf
|
||||
static bool validate_maze_element(const char& target);
|
||||
|
||||
public:
|
||||
/// Lese ein Labyrinth aus der Konsole
|
||||
/// @return Das Labyrinth
|
||||
/// @throws runtime_exception Falls die Eingabe nicht korrekt verlaufen ist.
|
||||
static Maze request_maze_from_user();
|
||||
};
|
||||
} // game
|
||||
|
||||
#endif //MAZEPARSER_H
|
60
Player.cpp
60
Player.cpp
|
@ -1,60 +0,0 @@
|
|||
#include "std_lib_inc.h"
|
||||
#include "Player.h"
|
||||
#include "Maze.h"
|
||||
#include "Exceptions/MovementNotPossible.h"
|
||||
|
||||
using game_exceptions::MovementNotPossible;
|
||||
|
||||
namespace game
|
||||
{
|
||||
Player::Player(const int target_x, const int target_y): pos(target_x, target_y), keys_in_inventory(0)
|
||||
{
|
||||
}
|
||||
|
||||
Player::Player(const PositionVector pos) : pos(pos), keys_in_inventory(0)
|
||||
{
|
||||
}
|
||||
|
||||
PositionVector Player::get_pos() const
|
||||
{
|
||||
return this->pos;
|
||||
}
|
||||
|
||||
void Player::update_position(const PositionVector& target)
|
||||
{
|
||||
this->pos = target;
|
||||
}
|
||||
|
||||
|
||||
Maze Player::move(Maze& maze, const PositionVector& move_vector)
|
||||
{
|
||||
const PositionVector target_position = PositionVector(this->get_pos().x + move_vector.x,
|
||||
this->get_pos().y + move_vector.y);
|
||||
|
||||
if (maze.is_pos_free(target_position, this->has_key_available()))
|
||||
{
|
||||
this->update_position(target_position);
|
||||
|
||||
switch (maze.get_field(target_position))
|
||||
{
|
||||
case 'K':
|
||||
++this->keys_in_inventory;
|
||||
maze.update_field(target_position, '.');
|
||||
break;
|
||||
case 'T':
|
||||
--this->keys_in_inventory;
|
||||
maze.update_field(target_position, '.');
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
else
|
||||
throw MovementNotPossible("Bewegung nicht moeglich!");
|
||||
return maze;
|
||||
}
|
||||
|
||||
bool Player::has_key_available() const
|
||||
{
|
||||
return this->keys_in_inventory > 0;
|
||||
}
|
||||
} // game
|
49
Player.h
49
Player.h
|
@ -1,49 +0,0 @@
|
|||
#include "PositionVector.h"
|
||||
|
||||
#ifndef PLAYER_H
|
||||
#define PLAYER_H
|
||||
|
||||
namespace game
|
||||
{
|
||||
class Maze;
|
||||
|
||||
/// Ein Spieler.
|
||||
/// Besitzt einen veränderbaren Positionsvektor
|
||||
class Player
|
||||
{
|
||||
/// Die Position des Spielers
|
||||
PositionVector pos;
|
||||
int keys_in_inventory;
|
||||
|
||||
public:
|
||||
/// Ein Spieler.
|
||||
/// Besitzt einen veränderbaren Positionsvektor
|
||||
/// @param target_x Die Startposition des Spielers (X-Koordinate)
|
||||
/// @param target_y Die Startposition des Spielers (Y-Koordinate)
|
||||
Player(int target_x, int target_y);
|
||||
|
||||
/// Ein Spieler
|
||||
/// @param pos Die Startposition des Spielers
|
||||
explicit Player(PositionVector pos);
|
||||
|
||||
/// Kriege die Position des Spielers
|
||||
/// @return Die Position des Spielers
|
||||
PositionVector get_pos() const;
|
||||
|
||||
/// Aktuallisiere die Position des Spielers ohne weitere Checks
|
||||
/// @param target Das ziel
|
||||
void update_position(const PositionVector& target);
|
||||
|
||||
/// Bewege den Splieler um den Bewegungsvektor, insofern die Zielposition begehbar ist
|
||||
/// @param maze Das Maze
|
||||
/// @param move_vector Die gewollte Bewegung
|
||||
/// @return Die neue Position des Spielers
|
||||
Maze move(Maze& maze, const PositionVector& move_vector);
|
||||
|
||||
/// Check, if a player has at least one key
|
||||
/// @return If the player as an available key
|
||||
bool has_key_available() const;
|
||||
};
|
||||
} // maze
|
||||
|
||||
#endif //PLAYER_H
|
|
@ -1,16 +0,0 @@
|
|||
#include "PositionVector.h"
|
||||
|
||||
namespace game
|
||||
{
|
||||
PositionVector::PositionVector(const int x, const int y)
|
||||
{
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
}
|
||||
|
||||
void PositionVector::update(const int& x, const int& y)
|
||||
{
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
}
|
||||
} // game
|
|
@ -1,28 +0,0 @@
|
|||
#ifndef POSITION_H
|
||||
#define POSITION_H
|
||||
|
||||
namespace game
|
||||
{
|
||||
/// Ein Vector aus zwei zahlen.
|
||||
/// Kann eine Position oder eine Differenz zwischen zwei Positionen darstellen.
|
||||
struct PositionVector
|
||||
{
|
||||
// struct -> members public by default
|
||||
// Die beiden Variablen des Vectors
|
||||
int x;
|
||||
int y;
|
||||
|
||||
/// Ein Vector aus zwei zahlen.
|
||||
/// Kann eine Position oder eine Differenz zwischen zwei Positionen darstellen.
|
||||
/// @param x Die 'X'-Koordinate
|
||||
/// @param y Die 'Y'-Koordinate
|
||||
PositionVector(int x, int y);
|
||||
|
||||
/// Aktualisiere die Werte des Vectors
|
||||
/// @param x Die neue 'X'-Koordinate
|
||||
/// @param y Die neue 'Y'-Koordinate
|
||||
void update(const int& x, const int& y);
|
||||
};
|
||||
} // game
|
||||
|
||||
#endif //POSITION_H
|
330
main.cpp
330
main.cpp
|
@ -1,37 +1,314 @@
|
|||
#include "std_lib_inc.h"
|
||||
#include "Maze.h"
|
||||
#include "PositionVector.h"
|
||||
#include "MazeParser.h"
|
||||
#include "Game.h"
|
||||
#include "Exceptions/ExitGame.h"
|
||||
#include "Exceptions/MalformedMaze.h"
|
||||
#include "Exceptions/MovementNotPossible.h"
|
||||
#include "Exceptions/UnkownAction.h"
|
||||
|
||||
using game::Player;
|
||||
using game::PositionVector;
|
||||
using game::Maze;
|
||||
using game::MazeParser;
|
||||
using game::Game;
|
||||
|
||||
using game_exceptions::MalformedMaze;
|
||||
using game_exceptions::UnkownAction;
|
||||
using game_exceptions::MovementNotPossible;
|
||||
using game_exceptions::ExitGame;
|
||||
|
||||
// Ein Programm, welches dir erlaubt ein Labyrinth zu erkunden mit 'w', 'a', 's', und 'd'.
|
||||
|
||||
// ** KONSTANTEN ** //
|
||||
const vector<char> allowed_symbols_in_maze = {'Z', '.', '#', 'A', 'K', 'T'};
|
||||
|
||||
class UnknownAction{};
|
||||
class MalformedMaze{};
|
||||
class ExitGame{};
|
||||
class MovementNotPossible{};
|
||||
|
||||
class PositionVector
|
||||
{
|
||||
public:
|
||||
int vec_x;
|
||||
int vec_y;
|
||||
|
||||
PositionVector(const int x, const int y)
|
||||
{
|
||||
vec_x = x;
|
||||
vec_y = y;
|
||||
}
|
||||
};
|
||||
|
||||
class Maze
|
||||
{
|
||||
public:
|
||||
vector<vector<char>> the_maze_vector = {{}};
|
||||
PositionVector the_player_start_position = {0, 0};
|
||||
|
||||
Maze(vector<vector<char>> field, PositionVector player_start_position)
|
||||
{
|
||||
the_maze_vector = field;
|
||||
the_player_start_position = player_start_position;
|
||||
}
|
||||
};
|
||||
|
||||
class Player
|
||||
{
|
||||
public:
|
||||
|
||||
PositionVector the_pos = {0, 1};
|
||||
int keys = 0;
|
||||
|
||||
Player(PositionVector pos)
|
||||
{
|
||||
the_pos = pos;
|
||||
keys = 0;
|
||||
}
|
||||
};
|
||||
|
||||
class GameState
|
||||
{
|
||||
public:
|
||||
Maze the_maze = {{},{{},{}}};
|
||||
Player the_player = {{{}, {}}};
|
||||
|
||||
GameState(Maze maze, Player player)
|
||||
{
|
||||
the_maze = maze;
|
||||
the_player = player;
|
||||
}
|
||||
};
|
||||
|
||||
/// Kontrolliere, ob der Spieler an einem Geist sterben sollte
|
||||
/// @param gs Der Zustand des Spiels
|
||||
/// @return Ob der Spieler sich auf einem Feld mit einem Geist befindet
|
||||
bool was_player_killed_by_ghost(const GameState& gs)
|
||||
{
|
||||
return gs.the_maze.the_maze_vector[gs.the_player.the_pos.vec_y][gs.the_player.the_pos.vec_x] == 'A';
|
||||
}
|
||||
|
||||
/// Kontrolliere, ob der Spieler das Ziel erreicht hat
|
||||
/// @param gs Der Zustand des Spiels
|
||||
/// @return Ob der Spieler das Ziel erreicht hat
|
||||
bool has_player_reached_goal(const GameState& gs)
|
||||
{
|
||||
return gs.the_maze.the_maze_vector[gs.the_player.the_pos.vec_y][gs.the_player.the_pos.vec_x] == 'Z';
|
||||
}
|
||||
|
||||
/// Zeige dem Nutzer das Spielfeld
|
||||
/// @param gs Der Zustand des Spiels
|
||||
void render_maze(const GameState& gs)
|
||||
{
|
||||
for (int y = 0; y < gs.the_maze.the_maze_vector.size(); ++y)
|
||||
{
|
||||
for (int x = 0; x < gs.the_maze.the_maze_vector[y].size(); ++x)
|
||||
{
|
||||
if (y == gs.the_player.the_pos.vec_y && x == gs.the_player.the_pos.vec_x)
|
||||
cout << "S";
|
||||
else
|
||||
cout << gs.the_maze.the_maze_vector[y][x];
|
||||
cout << " ";
|
||||
}
|
||||
cout << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
/// Kontrolliere, ob der Spieler eine Position gehen kann
|
||||
/// @param mz Das Labyrinth
|
||||
/// @param pv Die zu überprüfende Position
|
||||
/// @param does_player_have_key Ob der Spieler einen Schlüssel besitzt
|
||||
/// @return Ob der Spieler die Position begehen kann
|
||||
bool is_position_free(const Maze& mz, const PositionVector& pv, const bool& does_player_have_key)
|
||||
{
|
||||
if (pv.vec_x < 0 || pv.vec_y < 0 || pv.vec_y > mz.the_maze_vector.size() - 1 || pv.vec_x > mz.the_maze_vector[pv.vec_y].size() - 1)
|
||||
return false;
|
||||
if (mz.the_maze_vector[pv.vec_y][pv.vec_x] == '#')
|
||||
return false;
|
||||
if (mz.the_maze_vector[pv.vec_y][pv.vec_x] == 'T')
|
||||
return does_player_have_key;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/// Kontrolliere, ob ein gegebenes Symbol im Labyrinth vorkommen darf
|
||||
/// @param symbol Das zu überprüfende Zeichen
|
||||
/// @return Ob das gegebene Symbol in einem Labyrinth vorkommen darf
|
||||
bool is_symbol_valid_maze_element(const char& symbol)
|
||||
{
|
||||
for (char c : allowed_symbols_in_maze)
|
||||
if (c == symbol)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Lese beliebig viele Nummern aus der Konsolenausgabe aus
|
||||
/// @param amount_of_numbers_to_read Wie viele Nummern eingelesen werden sollen
|
||||
/// @return Die eingelesenen Nummern
|
||||
/// @throws MalformedMaze Wenn der Nutzer etwas anderes als Zahlen eingibt
|
||||
vector<int> get_numbers_from_user(const int& amount_of_numbers_to_read)
|
||||
{
|
||||
int input;
|
||||
vector<int> numbers_provided_by_user;
|
||||
for (int i = 0; i < amount_of_numbers_to_read; ++i)
|
||||
{
|
||||
cin >> input;
|
||||
if (!cin)
|
||||
throw MalformedMaze();
|
||||
numbers_provided_by_user.push_back(input);
|
||||
}
|
||||
|
||||
return numbers_provided_by_user;
|
||||
}
|
||||
|
||||
/// Lese ein Labyrinth aus
|
||||
/// @param rows Wie viele Reihen das Labyrinth haben soll
|
||||
/// @param columns Wie viele Zeilen das Labyrinth haben soll
|
||||
/// @return Das fertige Labyrinth
|
||||
/// @throw MalformedMaze Wenn ein eingegebenes Symbol kein char ist, oder ein Symbol eingegeben wird, welches nicht in einem Labyrinth erlaubt ist, oder die Dimension des Mazes falsch ist.
|
||||
/// @throw ExitGame Wenn 'q' eingegeben wird
|
||||
vector<vector<char>> get_field_from_user(const int& rows, const int& columns)
|
||||
{
|
||||
if ((rows <= 0 || rows > 20) || (columns <= 0 || columns > 20))
|
||||
throw MalformedMaze();
|
||||
|
||||
char input;
|
||||
vector<vector<char>> maze;
|
||||
|
||||
for (int current_row = 0; current_row < rows; ++current_row)
|
||||
{
|
||||
vector<char> current_column;
|
||||
for (int element_of_column = 0; element_of_column < columns; ++element_of_column)
|
||||
{
|
||||
cin >> input;
|
||||
if (!cin)
|
||||
throw MalformedMaze();
|
||||
if (input == 'q')
|
||||
throw ExitGame();
|
||||
if (!is_symbol_valid_maze_element(input))
|
||||
throw MalformedMaze();
|
||||
current_column.push_back(input);
|
||||
}
|
||||
maze.push_back(current_column);
|
||||
}
|
||||
return maze;
|
||||
}
|
||||
|
||||
/// Lasse den Spieler ein Labyrinth eingeben
|
||||
/// @return Ein vom Spieler eingegebenes Labyrinth
|
||||
Maze get_complete_maze_from_user()
|
||||
{
|
||||
vector<int> maze_dimensions = get_numbers_from_user(2);
|
||||
vector<vector<char>> field = get_field_from_user(maze_dimensions[0], maze_dimensions[1]);
|
||||
vector<int> player_start_position = get_numbers_from_user(2);
|
||||
|
||||
return Maze(field, PositionVector(player_start_position[1], player_start_position[0]));
|
||||
}
|
||||
|
||||
/// Lese aus der Eingabe des Spielers, was er machen möchte
|
||||
/// @param input Die Eingabe des Nutzers
|
||||
/// @return Die gewollte Bewegung des Spielers
|
||||
/// @throw ExitGame Wenn der Nutzer 'q' eingegeben hat und das Spiel verlassen möchte
|
||||
/// @throw UnknownAction Wenn der Nutzer einen Befehl eingibt, den das Programm nicht kennt
|
||||
PositionVector handle_user_input(const char& input)
|
||||
{
|
||||
PositionVector movement_vector = PositionVector(0, 0);
|
||||
|
||||
switch (input)
|
||||
{
|
||||
case 'w':
|
||||
movement_vector.vec_y = -1;
|
||||
break;
|
||||
case 'a':
|
||||
movement_vector.vec_x = -1;
|
||||
break;
|
||||
case 's':
|
||||
movement_vector.vec_y = 1;
|
||||
break;
|
||||
case 'd':
|
||||
movement_vector.vec_x = 1;
|
||||
break;
|
||||
case 'q':
|
||||
throw ExitGame();
|
||||
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 UnknownAction();
|
||||
}
|
||||
|
||||
return movement_vector;
|
||||
}
|
||||
|
||||
/// Bewege den Spieler um den gegebenen Vektor
|
||||
/// @param gs Der Spielzustand
|
||||
/// @param requested_movement Die gewollte Bewegung
|
||||
/// @returns The new GameState
|
||||
/// @throw MovementNotPossible Wenn die Bewegung aus irgendeinem Grund nicht möglich ist
|
||||
GameState move_player(GameState gs, PositionVector requested_movement)
|
||||
{
|
||||
const PositionVector target_position = PositionVector(gs.the_player.the_pos.vec_x + requested_movement.vec_x,
|
||||
gs.the_player.the_pos.vec_y + requested_movement.vec_y);
|
||||
|
||||
if (is_position_free(gs.the_maze, target_position, gs.the_player.keys > 0))
|
||||
{
|
||||
gs.the_player.the_pos = target_position;
|
||||
|
||||
switch (gs.the_maze.the_maze_vector[target_position.vec_y][target_position.vec_x])
|
||||
{
|
||||
case 'K':
|
||||
++gs.the_player.keys;
|
||||
gs.the_maze.the_maze_vector[target_position.vec_y][target_position.vec_x] = '.';
|
||||
break;
|
||||
case 'T':
|
||||
--gs.the_player.keys;
|
||||
gs.the_maze.the_maze_vector[target_position.vec_y][target_position.vec_x] = '.';
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
else
|
||||
throw MovementNotPossible();
|
||||
return gs;
|
||||
}
|
||||
|
||||
/// Die Hauptschleife des Spiels. Hier findet die Logik statt
|
||||
/// @param gs Der Spielzustand
|
||||
void game_loop(GameState& gs)
|
||||
{
|
||||
char game_input;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (was_player_killed_by_ghost(gs))
|
||||
{
|
||||
cout << "Sie haben einen Geist getroffen! Game Over!\n";
|
||||
break;
|
||||
}
|
||||
|
||||
render_maze(gs);
|
||||
|
||||
if (has_player_reached_goal(gs))
|
||||
{
|
||||
cout << "Ziel erreicht! Herzlichen Glueckwunsch!\n";
|
||||
break;
|
||||
}
|
||||
|
||||
cin >> game_input;
|
||||
|
||||
PositionVector movement_vector = PositionVector(0, 0);
|
||||
|
||||
try
|
||||
{
|
||||
movement_vector = handle_user_input(game_input);
|
||||
gs = move_player(gs, movement_vector);
|
||||
} catch (UnknownAction& _)
|
||||
{
|
||||
cout << "Diese Eingabe kenne ich nicht. Gib 'h' ein, um eine Hilfe zu erhalten." << "\n";
|
||||
} catch (MovementNotPossible& _)
|
||||
{
|
||||
cout << "Bewegung nicht moeglich!" << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
try
|
||||
{
|
||||
Maze maze = MazeParser::request_maze_from_user();
|
||||
|
||||
Game game = Game(maze);
|
||||
|
||||
game.run_game();
|
||||
}
|
||||
catch (MalformedMaze& _)
|
||||
Maze mz = get_complete_maze_from_user();
|
||||
Player pl = Player(mz.the_player_start_position);
|
||||
GameState gs = GameState(mz, pl);
|
||||
game_loop(gs);
|
||||
} catch (MalformedMaze& _)
|
||||
{
|
||||
cout << "Fehler beim Einlesen des Labyrinths.\n";
|
||||
} catch (ExitGame& _)
|
||||
|
@ -39,5 +316,6 @@ int main()
|
|||
cout << "Schoenen Tag noch!" << "\n";
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue