From 5d07d946a0d5f092ccf80fdf2c93ace7ecd6d7a7 Mon Sep 17 00:00:00 2001 From: moonleay Date: Sat, 21 Dec 2024 00:33:27 +0100 Subject: [PATCH] feat!: made code worse, due to skill issues by the tutors --- CMakeLists.txt | 14 -- Exceptions/ExitGame.h | 22 --- Exceptions/MalformedMaze.h | 22 --- Exceptions/MovementNotPossible.h | 22 --- Exceptions/UnkownAction.h | 22 --- Game.cpp | 95 --------- Game.h | 30 --- Maze.cpp | 68 ------- Maze.h | 62 ------ MazeParser.cpp | 68 ------- MazeParser.h | 43 ---- Player.cpp | 60 ------ Player.h | 49 ----- PositionVector.cpp | 16 -- PositionVector.h | 28 --- main.cpp | 330 ++++++++++++++++++++++++++++--- 16 files changed, 304 insertions(+), 647 deletions(-) delete mode 100644 Exceptions/ExitGame.h delete mode 100644 Exceptions/MalformedMaze.h delete mode 100644 Exceptions/MovementNotPossible.h delete mode 100644 Exceptions/UnkownAction.h delete mode 100644 Game.cpp delete mode 100644 Game.h delete mode 100644 Maze.cpp delete mode 100644 Maze.h delete mode 100644 MazeParser.cpp delete mode 100644 MazeParser.h delete mode 100644 Player.cpp delete mode 100644 Player.h delete mode 100644 PositionVector.cpp delete mode 100644 PositionVector.h 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; }