Untitled
unknown
plain_text
2 years ago
10 kB
4
Indexable
#include <iostream>
#include <fstream>
#include <string>
#include "logic.h"
using std::cout, std::endl, std::ifstream, std::string;
/**
* TODO: Student implement this function
* Load representation of the dungeon level from file into the 2D map.
* Calls createMap to allocate the 2D array.
* @param fileName File name of dungeon level.
* @param maxRow Number of rows in the dungeon table (aka height).
* @param maxCol Number of columns in the dungeon table (aka width).
* @param player Player object by reference to set starting position.
* @return pointer to 2D dynamic array representation of dungeon map with player's location., or nullptr if loading fails for any reason
* @updates maxRow, maxCol, player
*/
char** loadLevel(const string& fileName, int& maxRow, int& maxCol, Player& player) {
std::ifstream file(fileName);
if (!file) {
std::cerr << "Error loading level: " << fileName << std::endl;
return nullptr;
}
// Read the dimensions of the level from the file
file >> maxRow >> maxCol;
// Allocate memory for the map
char** map = createMap(maxRow, maxCol);
// Read the map from the file
for (int i = 0; i < maxRow; ++i) {
for (int j = 0; j < maxCol; ++j) {
file >> map[i][j];
if (map[i][j] == TILE_PLAYER) {
player.row = i;
player.col = j;
}
}
}
// Update the player's initial position to 'o'
map[player.row][player.col] = TILE_PLAYER;
return map;
}
/**
* TODO: Student implement this function
* Translate the character direction input by the user into row or column change.
* That is, updates the nextRow or nextCol according to the player's movement direction.
* @param input Character input by the user which translates to a direction.
* @param nextRow Player's next row on the dungeon map (up/down).
* @param nextCol Player's next column on dungeon map (left/right).
* @updates nextRow, nextCol
*/
void getDirection(char input, int& nextRow, int& nextCol) {
switch (input) {
case MOVE_UP:
nextRow = -1;
nextCol = 0;
break;
case MOVE_DOWN:
nextRow = 1;
nextCol = 0;
break;
case MOVE_LEFT:
nextRow = 0;
nextCol = -1;
break;
case MOVE_RIGHT:
nextRow = 0;
nextCol = 1;
break;
default:
break;
}
}
/**
* TODO: [suggested] Student implement this function
* Allocate the 2D map array.
* Initialize each cell to TILE_OPEN.
* @param maxRow Number of rows in the dungeon table (aka height).
* @param maxCol Number of columns in the dungeon table (aka width).
* @return 2D map array for the dungeon level, holds char type.
*/
char** createMap(int maxRow, int maxCol) {
char** map = new char*[maxRow];
for(int i = 0; i < maxRow; ++i)
map[i] = new char[maxCol];
for(int i = 0; i < maxRow; ++i)
for(int j = 0; j < maxCol; ++j)
map[i][j] = TILE_OPEN;
return map;
}
/**
* TODO: Student implement this function
* Deallocates the 2D map array.
* @param map Dungeon map.
* @param maxRow Number of rows in the dungeon table (aka height).
* @return None
* @update map, maxRow
*/
void deleteMap(char**& map, int& maxRow) {
for (int i = 0; i < maxRow; ++i) {
delete[] map[i];
}
delete[] map;
}
/**
* TODO: Student implement this function
* Resize the 2D map by doubling both dimensions.
* Copy the current map contents to the right, diagonal down, and below.
* Do not duplicate the player, and remember to avoid memory leaks!
* You can use the STATUS constants defined in logic.h to help!
* @param map Dungeon map.
* @param maxRow Number of rows in the dungeon table (aka height), to be doubled.
* @param maxCol Number of columns in the dungeon table (aka width), to be doubled.
* @return pointer to a dynamically-allocated 2D array (map) that has twice as many columns and rows in size.
* @update maxRow, maxCol
*/
char** resizeMap(char** map, int& maxRow, int& maxCol) {
int newMaxRow = maxRow * 2;
int newMaxCol = maxCol * 2;
char** newMap = new char*[newMaxRow];
for (int i = 0; i < newMaxRow; ++i) {
newMap[i] = new char[newMaxCol];
}
// Initialize new map with empty spaces
for (int i = 0; i < newMaxRow; ++i) {
for (int j = 0; j < newMaxCol; ++j) {
newMap[i][j] = TILE_OPEN;
}
}
// Copy old map into new map
for (int i = 0; i < maxRow; ++i) {
for (int j = 0; j < maxCol; ++j) {
newMap[i * 2][j * 2] = map[i][j];
}
}
// Delete old map
for (int i = 0; i < maxRow; ++i) {
delete[] map[i];
}
delete[] map;
maxRow = newMaxRow;
maxCol = newMaxCol;
return newMap;
}
/**
* TODO: Student implement this function
* Checks if the player can move in the specified direction and performs the move if so.
* Cannot move out of bounds or onto TILE_PILLAR or TILE_MONSTER.
* Cannot move onto TILE_EXIT without at least one treasure.
* If TILE_TREASURE, increment treasure by 1.
* Remember to update the map tile that the player moves onto and return the appropriate status.
* You can use the STATUS constants defined in logic.h to help!
* @param map Dungeon map.
* @param maxRow Number of rows in the dungeon table (aka height).
* @param maxCol Number of columns in the dungeon table (aka width).
* @param player Player object to by reference to see current location.
* @param nextRow Player's next row on the dungeon map (up/down).
* @param nextCol Player's next column on dungeon map (left/right).
* @return Player's movement status after updating player's position.
* @update map contents, player
*/
int doPlayerMove(char** map, int maxRow, int maxCol, Player& player, int nextRow, int nextCol) {
char nextPosition = map[nextRow][nextCol];
// Check if the next position is an empty space, a door, or a treasure
if (nextPosition == TILE_OPEN || nextPosition == TILE_DOOR || nextPosition == TILE_TREASURE) {
// Update the player's position
map[player.row][player.col] = TILE_OPEN;
player.row = nextRow;
player.col = nextCol;
map[player.row][player.col] = TILE_PLAYER;
// Check if the next position is a treasure
if (nextPosition == TILE_TREASURE) {
player.treasure++;
return STATUS_TREASURE;
}
// Check if the next position is a door
if (nextPosition == TILE_DOOR) {
// Check if the player has at least one treasure to exit
if (player.treasure > 0) {
return STATUS_LEAVE;
} else {
// Player cannot exit without treasures
return STATUS_STAY;
}
}
// Player moved to an empty space
return STATUS_MOVE;
}
// Invalid move: player hit a wall or encountered a monster
return STATUS_STAY;
}
/**
* TODO: Student implement this function
* Update monster locations:
* We check up, down, left, right from the current player position.
* If we see an obstacle, there is no line of sight in that direction, and the monster does not move.
* If we see a monster before an obstacle, the monster moves one tile toward the player.
* We should update the map as the monster moves.
* At the end, we check if a monster has moved onto the player's tile.
* @param map Dungeon map.
* @param maxRow Number of rows in the dungeon table (aka height).
* @param maxCol Number of columns in the dungeon table (aka width).
* @param player Player object by reference for current location.
* @return Boolean value indicating player status: true if monster reaches the player, false if not.
* @update map contents
*/
bool doMonsterAttack(char** map, int maxRow, int maxCol, const Player& player) {
char** tempMap = createMap(maxRow, maxCol);
for (int i = 0; i < maxRow; ++i) {
for (int j = 0; j < maxCol; ++j) {
tempMap[i][j] = map[i][j];
}
}
// Update monster locations
for (int i = 0; i < maxRow; ++i) {
for (int j = 0; j < maxCol; ++j) {
if (tempMap[i][j] == TILE_MONSTER) {
// Move monsters one tile toward the player
int rowDiff = player.row - i;
int colDiff = player.col - j;
if (abs(rowDiff) >= abs(colDiff)) {
// Move vertically
tempMap[i][j] = TILE_OPEN;
i += (rowDiff > 0) ? 1 : -1;
tempMap[i][j] = TILE_MONSTER;
} else {
// Move horizontally
tempMap[i][j] = TILE_OPEN;
j += (colDiff > 0) ? 1 : -1;
tempMap[i][j] = TILE_MONSTER;
}
// Check if monster has reached the player's tile
if (i == player.row && j == player.col) {
deleteMap(tempMap, maxRow);
return true; // Player is caught by a monster
}
}
}
}
// Update the original map with the new monster positions
for (int i = 0; i < maxRow; ++i) {
for (int j = 0; j < maxCol; ++j) {
map[i][j] = tempMap[i][j];
}
}
// Clean up the temporary map
deleteMap(tempMap, maxRow);
return false; // Player is not caught by a monster
}Editor is loading...