epr24pr3_ojanssen2/main.cpp
2024-12-09 09:59:45 +01:00

197 lines
No EOL
5.6 KiB
C++

// Ein Labyrinth-Spiel
// Autor: Fritz Bökler
// Datum 20.11.2024
// MIT Lizenz
//
// Labyrinth wird in der Konsole ausgegeben.
// . Leeres Feld
// # Wand (nicht betretbar)
// Z Ziel
// S SpielerIn (wird nicht im Labyrinth gespeichert)
//
// Ziel des Spiels ist, das Ziel-Feld zu erreichen.
// Eingabe erfolgt zeilengepuffert über cin.
#include "std_lib_inc.h"
// Globale Labyrinth-Definition als konstanter Ausdruck
constexpr int kRows = 5;
constexpr int kCols = 5;
// Labyrinth-Daten
// Interpretiere als Zeilen, dann Spalten
const vector<vector<char>> kMaze = {
{'#', '.', '.', '.', '.'},
{'#', '.', '#', '.', '.'},
{'.', 'Z', '#', '.', '.'},
{'.', '#', '#', '#', '.'},
{'.', '.', '.', '.', '.'},
};
const vector<int> kPlayerStartPosition = {4, 0};
// Funktion zur Anzeige des Labyrinths
// player_position: Position der SpielerIn im Labyrinth
void display_maze(vector<int> player_position)
{
int player_row = player_position[0];
int player_col = player_position[1];
for(int i = 0; i < kRows; i++)
{
for(int j = 0; j < kCols; j++)
{
if(i == player_row && j == player_col)
{
cout << 'S';
}
else
{
cout << kMaze[i][j];
}
cout << " ";
}
cout << '\n';
}
}
// Funktion zur Umrechnung eines Kommandos zu einer neuen Position
// player_position: Position der SpielerIn im Labyrinth
// direction: Richtungskommando
// Rückgabe: Die neue SpielerInnenposition
// Vorbedingung: direction muss aus {w, s, a, d} kommen.
vector<int> new_position_by_direction(vector<int> player_position, char direction)
{
int row = player_position[0];
int col = player_position[1];
assert(direction == 'w' || direction == 's' || direction == 'a' || direction == 'd',
"new_position_by_direction: invalid direction. Must be from {w, s, a, d}.");
switch(direction)
{
case 'w':
return {row - 1, col};
case 's':
return {row + 1, col};
case 'a':
return {row, col - 1};
case 'd':
return {row, col + 1};
}
}
// Gibt true zurueck gdw. die Position position begehbar ist
// position: Zu testende Position
// Rückgabe: true gdw. die Position begehbar ist
bool position_is_valid(vector<int> position)
{
const int row = position[0];
const int col = position[1];
bool outside_playfield = row < 0 || col < 0 || row >= kRows || col >= kCols;
if(outside_playfield) // Erst prüfen, bevor Vector-Zugriff
{
return false;
}
return kMaze[row][col] != '#';
}
// Funktion zur Bewegung des Spielers
// player_position: Position der SpielerIn vor der Bewegung
// direction: Richtungskommando
// Rückgabe: Die neue SpielerInnenposition der SpielerIn
vector<int> move_player(vector<int> player_position, char direction)
{
vector<int> potential_new_position = new_position_by_direction(player_position, direction);
if(position_is_valid(potential_new_position))
{
return potential_new_position;
}
else
{
cout << "Bewegung nicht moeglich!\n";
return player_position;
}
}
// Gibt eine kurze Hilfe aus
void display_help()
{
cout << "Willkommen zum Labyrinth-Spiel!\n";
cout << "Ziel des Spiels: Finde den Weg vom Startpunkt (S) zum Ziel (Z).\n";
cout << "Spielfeld-Erklaerung:\n";
cout << "S - Startpunkt: Hier beginnt der Spieler.\n";
cout << "Z - Ziel: Erreiche diesen Punkt, um das Spiel zu gewinnen.\n";
cout << "# - Wand: Diese Felder sind nicht begehbar.\n";
cout << ". - Leeres Feld: Diese Felder koennen betreten werden.\n";
cout << "\nSteuerung:\n";
cout << "w - Nach oben bewegen\n";
cout << "a - Nach links bewegen\n";
cout << "s - Nach unten bewegen\n";
cout << "d - Nach rechts bewegen\n";
cout << "Nach jeder Befehlseingabe muss die Eingabetaste (Enter) gedrueckt werden, um sich zu bewegen.\n";
cout << "\nViel Erfolg im Labyrinth!\n";
}
// Reagiert auf das eingegebene Kommando und gibt an die jeweilige Funktion
// ab, die sich um genau dieses Kommando kuemmert.
// player_position: die aktuelle SpielerInnenposition
// input: Ein Eingabezeichen
// Rückgabe: Die neue SpielerInnenposition, falls sie sich aendert
vector<int> process_input(vector<int> player_position, char input)
{
switch(input)
{
case 'w': case 's': case 'a': case 'd':
return move_player(player_position, input);
case 'h':
display_help();
break;
default:
cout << "Diese Eingabe kenne ich nicht. Gib 'h' ein, um eine Hilfe zu erhalten.\n";
break;
}
return player_position;
}
// Gibt true zurueck, wenn das Ziel erreicht wurde
// player_position: Die aktuelle SpielerInnenposition
// Rückgabe: true gdw. das Ziel erreicht wurde
bool reached_goal(vector<int> player_position)
{
return kMaze[player_position[0]][player_position[1]] == 'Z';
}
// Die Hauptschleife des Spiels
// player_position: Die aktuelle SpielerInnenposition
void game_loop(vector<int> player_position)
{
char input;
bool not_won = true;
while(cin && not_won)
{
display_maze(player_position);
cin >> input;
if(cin)
{
player_position = process_input(player_position, input);
if(reached_goal(player_position))
{
display_maze(player_position);
cout << "Ziel erreicht! Herzlichen Glueckwunsch!\n";
not_won = false;
}
}
}
}
int main()
{
game_loop(kPlayerStartPosition);
return 0;
}