2024-12-02 17:47:09 +01:00
# include "std_lib_inc.h"
2024-12-14 17:32:06 +01:00
// Ein Programm, welches dir erlaubt ein Labyrinth zu erkunden mit 'w', 'a', 's', und 'd'.
2024-12-02 17:47:09 +01:00
2024-12-21 00:33:27 +01:00
// ** KONSTANTEN ** //
const vector < char > allowed_symbols_in_maze = { ' Z ' , ' . ' , ' # ' , ' A ' , ' K ' , ' T ' } ;
class UnknownAction { } ;
class MalformedMaze { } ;
class ExitGame { } ;
class MovementNotPossible { } ;
class PositionVector
2024-12-02 17:47:09 +01:00
{
2024-12-21 00:33:27 +01:00
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 )
2024-12-16 23:20:04 +01:00
{
2024-12-21 00:33:27 +01:00
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 ] ) ) ;
}
2024-12-17 15:09:50 +01:00
2024-12-21 00:33:27 +01:00
/// 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 ) ;
2024-12-17 14:22:03 +01:00
2024-12-21 00:33:27 +01:00
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 ( ) ;
2024-12-16 23:21:24 +01:00
}
2024-12-21 00:33:27 +01:00
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 mz = get_complete_maze_from_user ( ) ;
Player pl = Player ( mz . the_player_start_position ) ;
GameState gs = GameState ( mz , pl ) ;
game_loop ( gs ) ;
} catch ( MalformedMaze & _ )
2024-12-16 23:20:04 +01:00
{
cout < < " Fehler beim Einlesen des Labyrinths. \n " ;
2024-12-17 14:39:33 +01:00
} catch ( ExitGame & _ )
2024-12-17 14:35:22 +01:00
{
2024-12-17 14:39:33 +01:00
cout < < " Schoenen Tag noch! " < < " \n " ;
2024-12-16 23:20:04 +01:00
}
2024-12-21 00:33:27 +01:00
2024-12-02 17:47:09 +01:00
return 0 ;
2024-12-14 17:32:06 +01:00
}