diff --git a/CMakeLists.txt b/CMakeLists.txt index f632763..df98554 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 ) diff --git a/Exceptions/ExitGame.h b/Exceptions/ExitGame.h deleted file mode 100644 index c06a808..0000000 --- a/Exceptions/ExitGame.h +++ /dev/null @@ -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 diff --git a/Exceptions/MalformedMaze.h b/Exceptions/MalformedMaze.h deleted file mode 100644 index 01cfa46..0000000 --- a/Exceptions/MalformedMaze.h +++ /dev/null @@ -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 diff --git a/Exceptions/MovementNotPossible.h b/Exceptions/MovementNotPossible.h deleted file mode 100644 index 54e4f6c..0000000 --- a/Exceptions/MovementNotPossible.h +++ /dev/null @@ -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 diff --git a/Exceptions/UnkownAction.h b/Exceptions/UnkownAction.h deleted file mode 100644 index 32f2f2a..0000000 --- a/Exceptions/UnkownAction.h +++ /dev/null @@ -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 diff --git a/Game.cpp b/Game.cpp deleted file mode 100644 index 56bad6d..0000000 --- a/Game.cpp +++ /dev/null @@ -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 diff --git a/Game.h b/Game.h deleted file mode 100644 index ebc6eaf..0000000 --- a/Game.h +++ /dev/null @@ -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 diff --git a/Maze.cpp b/Maze.cpp deleted file mode 100644 index 6f4f526..0000000 --- a/Maze.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include "Maze.h" -#include "Player.h" -#include "Exceptions/MalformedMaze.h" - -using game_exceptions::MalformedMaze; - -namespace game -{ - Maze::Maze(const vector> play_field, const vector 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 diff --git a/Maze.h b/Maze.h deleted file mode 100644 index 2c75141..0000000 --- a/Maze.h +++ /dev/null @@ -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> field; - /// Die Startposition des Spielers - PositionVector player_start_position; - - public: - /// Das Spielfeld - Maze(vector> play_field, vector 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 diff --git a/MazeParser.cpp b/MazeParser.cpp deleted file mode 100644 index 56c669e..0000000 --- a/MazeParser.cpp +++ /dev/null @@ -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 MazeParser::request_numbers_from_user(const int& amount_of_numbers) - { - int input; - vector 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 maze_size = request_numbers_from_user(2); - - char input; - vector> field; - - for (int y = 0; y < maze_size[0]; ++y) - { - vector 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 player_start_pos = request_numbers_from_user(2); - - return Maze(field, player_start_pos); - } // Beispieleingabe: `4 3 #.# #.K #T# #Z# 0 1` -} // game diff --git a/MazeParser.h b/MazeParser.h deleted file mode 100644 index 5093e5a..0000000 --- a/MazeParser.h +++ /dev/null @@ -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 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 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 diff --git a/Player.cpp b/Player.cpp deleted file mode 100644 index f3b4f3b..0000000 --- a/Player.cpp +++ /dev/null @@ -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 diff --git a/Player.h b/Player.h deleted file mode 100644 index 4818b77..0000000 --- a/Player.h +++ /dev/null @@ -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 diff --git a/PositionVector.cpp b/PositionVector.cpp deleted file mode 100644 index 7a19e94..0000000 --- a/PositionVector.cpp +++ /dev/null @@ -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 diff --git a/PositionVector.h b/PositionVector.h deleted file mode 100644 index ea032e1..0000000 --- a/PositionVector.h +++ /dev/null @@ -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 diff --git a/main.cpp b/main.cpp index d7629f8..1da0e73 100644 --- a/main.cpp +++ b/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 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> the_maze_vector = {{}}; + PositionVector the_player_start_position = {0, 0}; + + Maze(vector> 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 get_numbers_from_user(const int& amount_of_numbers_to_read) +{ + int input; + vector 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> get_field_from_user(const int& rows, const int& columns) +{ + if ((rows <= 0 || rows > 20) || (columns <= 0 || columns > 20)) + throw MalformedMaze(); + + char input; + vector> maze; + + for (int current_row = 0; current_row < rows; ++current_row) + { + vector 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 maze_dimensions = get_numbers_from_user(2); + vector> field = get_field_from_user(maze_dimensions[0], maze_dimensions[1]); + vector 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; }