Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create MazeRunner.cpp #80

Merged
merged 1 commit into from
Nov 1, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 158 additions & 0 deletions C++/MazeRunner.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>

// Maze dimensions
const int WIDTH = 10;
const int HEIGHT = 10;

// Symbols
const char PLAYER = 'P';
const char WALL = '#';
const char EMPTY = ' ';
const char KEY = 'K';
const char EXIT = 'E';
const char TRAP = 'T';
const char ENEMY = 'M';

// Structure to represent a point in the maze
struct Point {
int x, y;
};

// Function prototypes
void initializeMaze(std::vector<std::vector<char>>& maze, Point& playerPos, Point& exitPos);
void printMaze(const std::vector<std::vector<char>>& maze);
bool movePlayer(Point& playerPos, const std::string& direction, std::vector<std::vector<char>>& maze);
bool checkWinCondition(const Point& playerPos, const Point& exitPos, int keysCollected);

int main() {
srand(static_cast<unsigned int>(time(0))); // Seed for random number generation
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Consider using modern C++ random facilities instead of rand()

std::random_device and std::mt19937 provide better random number generation. Consider using std::uniform_int_distribution for range generation.

std::random_device rd;
std::mt19937 gen(rd());


std::vector<std::vector<char>> maze(HEIGHT, std::vector<char>(WIDTH, EMPTY));
Point playerPos;
Point exitPos;
int keysCollected = 0;
int totalKeys = 3; // Total keys to collect to unlock the exit

initializeMaze(maze, playerPos, exitPos);

std::string command;
bool gameRunning = true;

while (gameRunning) {
printMaze(maze);
std::cout << "Keys collected: " << keysCollected << "/" << totalKeys << "\n";
std::cout << "Enter command (e.g., 'move up', 'move down', etc.): ";
std::getline(std::cin, command);

// Extract direction from the command
std::string direction;
if (command.find("move ") == 0) {
direction = command.substr(5); // Get the part after "move "
} else {
std::cout << "Invalid command format!\n";
continue;
}

if (movePlayer(playerPos, direction, maze)) {
// Check for keys
if (maze[playerPos.y][playerPos.x] == KEY) {
keysCollected++;
maze[playerPos.y][playerPos.x] = EMPTY;
std::cout << "You collected a key!\n";
}

// Check for traps
if (maze[playerPos.y][playerPos.x] == TRAP) {
std::cout << "You stepped on a trap and lost the game!\n";
gameRunning = false;
continue;
}

// Check if player reached the exit
if (checkWinCondition(playerPos, exitPos, keysCollected)) {
std::cout << "You collected all keys and reached the exit! You win!\n";
gameRunning = false;
}
} else {
std::cout << "Invalid move!\n";
}
}

return 0;
}

void initializeMaze(std::vector<std::vector<char>>& maze, Point& playerPos, Point& exitPos) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (complexity): Consider extracting random element placement logic into a reusable helper function

The initializeMaze function contains duplicated random placement logic. This can be simplified with a helper function:

Point placeGameElement(std::vector<std::vector<char>>& maze, char element) {
    int x, y;
    do {
        x = rand() % (WIDTH - 2) + 1;
        y = rand() % (HEIGHT - 2) + 1;
    } while (maze[y][x] != EMPTY);
    maze[y][x] = element;
    return {x, y};
}

void initializeMaze(std::vector<std::vector<char>>& maze, Point& playerPos, Point& exitPos) {
    // Place walls (unchanged)
    ...

    // Place player and exit
    playerPos = {1, 1};
    maze[playerPos.y][playerPos.x] = PLAYER;
    exitPos = {WIDTH - 2, HEIGHT - 2}; 
    maze[exitPos.y][exitPos.x] = EXIT;

    // Place game elements
    for (int i = 0; i < 3; ++i) {
        placeGameElement(maze, KEY);
    }
    for (int i = 0; i < 3; ++i) {
        placeGameElement(maze, TRAP);
    }
}

This eliminates code duplication while making the placement logic more robust by consistently checking for empty spaces.

// Place walls around the maze
for (int i = 0; i < HEIGHT; ++i) {
for (int j = 0; j < WIDTH; ++j) {
if (i == 0 || i == HEIGHT - 1 || j == 0 || j == WIDTH - 1) {
maze[i][j] = WALL;
}
}
}

// Randomly place the player
playerPos = {1, 1};
maze[playerPos.y][playerPos.x] = PLAYER;

// Place the exit
exitPos = {WIDTH - 2, HEIGHT - 2};
maze[exitPos.y][exitPos.x] = EXIT;

// Randomly place keys, ensuring they are not on the player's position or the exit
for (int i = 0; i < 3; ++i) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: Keys should only be placed in EMPTY spaces to prevent overwriting existing keys

Add a check for maze[y][x] == EMPTY in the key placement loop, similar to the trap placement logic

int x, y;
do {
x = rand() % (WIDTH - 2) + 1;
y = rand() % (HEIGHT - 2) + 1;
} while ((x == playerPos.x && y == playerPos.y) || (x == exitPos.x && y == exitPos.y));
maze[y][x] = KEY;
}

// Randomly place traps, ensuring they are not on the player's position or the exit
for (int i = 0; i < 3; ++i) {
int x, y;
do {
x = rand() % (WIDTH - 2) + 1;
y = rand() % (HEIGHT - 2) + 1;
} while (maze[y][x] != EMPTY);
maze[y][x] = TRAP;
}
}

void printMaze(const std::vector<std::vector<char>>& maze) {
for (int i = 0; i < HEIGHT; ++i) {
for (int j = 0; j < WIDTH; ++j) {
std::cout << maze[i][j] << ' ';
}
std::cout << '\n';
}
}

bool movePlayer(Point& playerPos, const std::string& direction, std::vector<std::vector<char>>& maze) {
int dx = 0, dy = 0;
if (direction == "up") dy = -1;
else if (direction == "down") dy = 1;
else if (direction == "left") dx = -1;
else if (direction == "right") dx = 1;
else return false;

int newX = playerPos.x + dx;
int newY = playerPos.y + dy;

if (maze[newY][newX] != WALL) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Add bounds checking before accessing maze array

Add checks for newX >= 0 && newX < WIDTH && newY >= 0 && newY < HEIGHT before accessing maze[newY][newX]

    if (newX >= 0 && newX < WIDTH && newY >= 0 && newY < HEIGHT && maze[newY][newX] != WALL) {

maze[playerPos.y][playerPos.x] = EMPTY;
playerPos.x = newX;
playerPos.y = newY;
maze[newY][newX] = PLAYER;
return true;
}
return false;
}

bool checkWinCondition(const Point& playerPos, const Point& exitPos, int keysCollected) {
return playerPos.x == exitPos.x && playerPos.y == exitPos.y && keysCollected >= 3;
}
Loading