# Dungeon Glawl juego para la terminal -- ++ campo con game campo con console campo con homework camp codereview Relacionados El problema

## Dungeon Crawl game for the terminal

19

### problema

Español

Estoy aprendiendo C ++ y intenté hacer un ejercicio que encontré: Dungeon Crawl. El objetivo de este juego es llegar al tesoro moviendo tu personaje a lo largo de la pizarra.

El ejercicio solicita no usar clases para que haya intentado lograr un poco de nivel de abstracción con ` structs ` y ` 9988776655544333 `. He seguido el estilo de mi universidad para comentarios.

` ` #include <climits> #include <ctime> #include <iostream> #include <random> #include <string>  /**  * DUNGEON: a simple game for the terminal. The objective of the  * game is that the player ("P") reaches the treasure ("X")  * avoiding the traps ("T") and the bandits ("B").  * Bandits move randomly each turn.  * */ int NUMBEROFTRAPS = 3; int NUMBEROFBANDITS = 2;  // Represents a place in the board. // xPosition is the x-axis index and yPosition is the y-axis index struct Location {   int xPosition;   int yPosition; };  // Represents the player. // It is guaranteed Player position is in the board. // Position is altered through function movePlayer. struct Player {   Location position;   char symbol = 'P';   std::string name = "alvaro"; };  // Represents traps on the board // It is guarateed Trap position is in the board. struct Trap {   Location position;   char symbol = 'T'; };  // Represents Bandits moving around the map. // Position is altered through funtion moveBandit. struct Bandit {   Location position;   char symbol = 'B'; };  // Represents the treasure. // The game ends as soon Player.position == Treasure.position struct Treasure {   Location position;   char symbol = 'X'; };  // Represents the board. struct {   int xDimension;   int yDimension; } board = {.xDimension = 10, .yDimension = 10};  // Possible directions. WRONG_DIRECTION is used to report incorrect input enum Direction { RIGHT, LEFT, TOP, BOTTOM, WRONG_DIRECTION }; enum Result { VICTORY, DEFEAT };  void drawBoard(Player, Trap[], Bandit[], Treasure); void endGame(Result); void movePlayer(Player &, Direction); void moveBandit(Bandit &); Direction askDirection();  int main() {   std::srand(std::time(0));    // Treasure position is decided randomly.   Treasure treasure = {       .position = {.xPosition = std::rand() % board.xDimension,                    .yPosition = std::rand() % board.yDimension}};    // Traps are placed around the map. It is not guaranteed   // that traps position doesn't converge.   // In that case, the second trap can be assumed to not exist.   Trap trapsInMap[NUMBEROFTRAPS];   for (int i = 0; i < NUMBEROFTRAPS; i++) {     int xPos = std::rand() % board.xDimension;     int yPos = std::rand() % board.yDimension;     Trap trap = {.position = {.xPosition = xPos, .yPosition = yPos}};     trapsInMap[i] = trap;   }    // Bandits are placed around the map. It is not guaranteed   // that bandits position doesn't converge, but they will move   // anyway.   Bandit banditsInMap[NUMBEROFBANDITS];   for (int i = 0; i < NUMBEROFBANDITS; i++) {     int xPos = std::rand() % board.xDimension;     int yPos = std::rand() % board.yDimension;     Bandit bandit = {.position = {.xPosition = xPos, .yPosition = yPos}};     banditsInMap[i] = bandit;   }    // Player position on the 1st turn is randomly decided.   // It can not be the same of a bandit or a trap.   bool match = false;   int xPos;   int yPos;   do {     xPos = std::rand() % board.xDimension;     yPos = std::rand() % board.yDimension;     for (int i = 0; i < NUMBEROFTRAPS; i++) {       if ((xPos == trapsInMap[i].position.xPosition &&            yPos == trapsInMap[i].position.yPosition) ||           (xPos == banditsInMap[i].position.xPosition &&            yPos == banditsInMap[i].position.yPosition)) {         match = true;       }     }   } while (match);    Player alvaro = {.position = {.xPosition = xPos, .yPosition = yPos}};    // The order of the turn is the following:   // 1. Board is drawn.   // 2. User is asked for movement direction.   // 3. Player moves in the chosen direction.   // 4. Bandits move.   int maxTurnos = INT_MAX;   for (int i = 0; i <= maxTurnos; i++) {     drawBoard(alvaro, trapsInMap, banditsInMap, treasure);     Direction direction;     do {       direction = askDirection();       std::cout << std::endl;     } while (direction == WRONG_DIRECTION);     movePlayer(alvaro, direction);     for (int i = 0; i < NUMBEROFBANDITS; i++) {       moveBandit(banditsInMap[i]);     }     std::cout << "x1B[2Jx1B[H";   } }  void drawBoard(     /* in */ Player player,     /* in */ Trap totalTraps[],     /* in */ Bandit totalBandits[],     /* in */ Treasure treasure)  // Draws a (board.xDimension * board.yDimension) grid. // Elements are drawn using .location.?Dimensions.  // Precondition: 0 <= Player.xPosition <= board.xDimension && //      0 <= player.position.yPosition <= board.yDimension  && //      board.xDimension > 0  && board.yDimension > 0 && // Postcondition: The grid has been drawn. //      All elements have been drawn. //      If the player is in the same square than the treasure, //      the game ends with victory. //      If the player is in the same square than a bandit or //      a trap, the game ends with defeat. {   bool squareDrawn = false;   for (int y = 0; y <= board.yDimension; y++) {     for (int x = 0; x <= board.xDimension; x++) {       // Traps are drawn       for (int z = 0; z <= NUMBEROFTRAPS; z++) {         Trap trapToDraw = totalTraps[z];         if (trapToDraw.position.xPosition == x &&             trapToDraw.position.yPosition == y) {           std::cout << trapToDraw.symbol;           squareDrawn = true;         }       }       // Bandits are drawn.       // In case of collision with a trap,       // only the second is drawn.       for (int z = 0; z <= NUMBEROFBANDITS; z++) {         Bandit banditToDraw = totalBandits[z];         if (banditToDraw.position.xPosition == x &&             banditToDraw.position.yPosition == y && !squareDrawn) {           std::cout << banditToDraw.symbol;           squareDrawn = true;         }       }        // Treasure is drawn. If position of treasure == position of player       // game ends with victory       if (x == treasure.position.xPosition &&           y == treasure.position.yPosition) {         if (treasure.position.xPosition == player.position.xPosition &&             treasure.position.yPosition == player.position.yPosition) {           endGame(VICTORY);         }          std::cout << "X";         continue;       }        if (x == player.position.xPosition && y == player.position.yPosition) {         if (squareDrawn)           endGame(DEFEAT);         std::cout << "P";         continue;       }       // Empty square "." is drawn. It only gets printed if there is nothing       // on the square.       if (!squareDrawn)         std::cout << ".";       squareDrawn = false;     }     std::cout << std::endl;   } }  Direction askDirection() {    // Asks the user to input a direction and returns it.   // Precondition: -   // Poscondition:   // Return: a Direction value containing the direction chosen or   // WRONG_DIRECTION.    std::cout << "Select [L]eft, [R]ight, [T]op or [B]ottom: ";   char answer;   std::cin.get(answer);    Direction chosenDirection;   switch (std::toupper(answer)) {   case 'L':     chosenDirection = LEFT;     break;   case 'R':     chosenDirection = RIGHT;     break;   case 'T':     chosenDirection = TOP;     break;   case 'B':     chosenDirection = BOTTOM;     break;   default:     chosenDirection = WRONG_DIRECTION;   }   return chosenDirection; }  void movePlayer(     /* inout */ Player &player,   // Player of the game     /* in */ Direction direction) // Direction previously chosen.                                   // It is represented by a Direction object,                                   // different from WRONG_DIRECTION.  // Moves player in the chosen direction, by altering its coordinates. If the // player would finish out of the board, no movement is made.  // Precondition: 0 <= Player.xPosension <= board.xDimension && //        0 <= player.position.yPosition <= board.yDimension  && //        board.xDimension > 0  && board.yDimension > 0 && //        direction in {LEFT; RIGHT; TOP; BOTTOM} && // Postcondition: player coordinates have been altered && //        player remains inside the board. {   switch (direction) {   case RIGHT:     if (player.position.xPosition < board.xDimension)       player.position.xPosition += 1;     break;   case LEFT:     if (player.position.xPosition > 0)       player.position.xPosition -= 1;     break;   case TOP:     if (player.position.yPosition > 0)       player.position.yPosition -= 1;     break;   case BOTTOM:     if (player.position.yPosition < board.yDimension)       player.position.yPosition += 1;     break;   } }  void moveBandit(     /* inout */ Bandit &bandit) // Player of the game                                 // It is represented by a Direction object,                                 // different from WRONG_DIRECTION.  // Moves player in the chosen direction, by altering its coordinates. If the // player would finish out of the board, no movement is made.  // Precondition: 0 <= Player.xPosension <= board.xDimension && //        0 <= player.position.yPosition <= board.yDimension  && //        board.xDimension > 0  && board.yDimension > 0 && //        direction in {LEFT; RIGHT; TOP; BOTTOM} && // Postcondition: player coordinates have been altered && //        player remains inside the board. {    int direction = std::rand() % 4;   switch (direction) {   case 0:     if (bandit.position.xPosition < board.xDimension)       bandit.position.xPosition += 1;     break;   case 1:     if (bandit.position.xPosition > 0)       bandit.position.xPosition -= 1;     break;   case 2:     if (bandit.position.yPosition > 0)       bandit.position.yPosition -= 1;     break;   case 3:     if (bandit.position.yPosition < board.yDimension)       bandit.position.yPosition += 1;     break;   } }  void endGame(     /* in */ Result result) // Result of the game.                             // It is either VICTORY or DEFEAT // Cleans screen, prints a good bye message // and ends the game. // Precondition: a condition for ending the game has been found. //              Either player.position == bandit.position || //              player.position == trap.position [DEFEAT] //              or player.position == treasure.position [VICTORY] // Poscondition: game is ended. Greeting message is printed. {   std::string announcement = (result == VICTORY) ? "YOU WIN" : "GAME OVER";   std::cout << "x1B[2Jx1B[H"; // Resets terminal   std::cout << std::endl << std::endl;   std::cout << "===========================" << std::endl;   std::cout << "||   ||" << std::endl;   std::cout << "|| " << announcement << "  ||" << std::endl;   std::cout << "||   ||" << std::endl;   std::cout << "===========================" << std::endl;   exit(1); }  ` `
Original en ingles

I am learning C++ and I attempted to do one exercise I found: Dungeon Crawl. The goal of this game is to reach the treasure by moving your character along the board.

The exercise asks not to use classes so I have tried to achieve some level of abstraction with `structs` and `arrays`. I have followed my university's style for comments.

``#include <climits> #include <ctime> #include <iostream> #include <random> #include <string>  /**  * DUNGEON: a simple game for the terminal. The objective of the  * game is that the player ("P") reaches the treasure ("X")  * avoiding the traps ("T") and the bandits ("B").  * Bandits move randomly each turn.  * */ int NUMBEROFTRAPS = 3; int NUMBEROFBANDITS = 2;  // Represents a place in the board. // xPosition is the x-axis index and yPosition is the y-axis index struct Location {   int xPosition;   int yPosition; };  // Represents the player. // It is guaranteed Player position is in the board. // Position is altered through function movePlayer. struct Player {   Location position;   char symbol = 'P';   std::string name = "alvaro"; };  // Represents traps on the board // It is guarateed Trap position is in the board. struct Trap {   Location position;   char symbol = 'T'; };  // Represents Bandits moving around the map. // Position is altered through funtion moveBandit. struct Bandit {   Location position;   char symbol = 'B'; };  // Represents the treasure. // The game ends as soon Player.position == Treasure.position struct Treasure {   Location position;   char symbol = 'X'; };  // Represents the board. struct {   int xDimension;   int yDimension; } board = {.xDimension = 10, .yDimension = 10};  // Possible directions. WRONG_DIRECTION is used to report incorrect input enum Direction { RIGHT, LEFT, TOP, BOTTOM, WRONG_DIRECTION }; enum Result { VICTORY, DEFEAT };  void drawBoard(Player, Trap[], Bandit[], Treasure); void endGame(Result); void movePlayer(Player &, Direction); void moveBandit(Bandit &); Direction askDirection();  int main() {   std::srand(std::time(0));    // Treasure position is decided randomly.   Treasure treasure = {       .position = {.xPosition = std::rand() % board.xDimension,                    .yPosition = std::rand() % board.yDimension}};    // Traps are placed around the map. It is not guaranteed   // that traps position doesn't converge.   // In that case, the second trap can be assumed to not exist.   Trap trapsInMap[NUMBEROFTRAPS];   for (int i = 0; i < NUMBEROFTRAPS; i++) {     int xPos = std::rand() % board.xDimension;     int yPos = std::rand() % board.yDimension;     Trap trap = {.position = {.xPosition = xPos, .yPosition = yPos}};     trapsInMap[i] = trap;   }    // Bandits are placed around the map. It is not guaranteed   // that bandits position doesn't converge, but they will move   // anyway.   Bandit banditsInMap[NUMBEROFBANDITS];   for (int i = 0; i < NUMBEROFBANDITS; i++) {     int xPos = std::rand() % board.xDimension;     int yPos = std::rand() % board.yDimension;     Bandit bandit = {.position = {.xPosition = xPos, .yPosition = yPos}};     banditsInMap[i] = bandit;   }    // Player position on the 1st turn is randomly decided.   // It can not be the same of a bandit or a trap.   bool match = false;   int xPos;   int yPos;   do {     xPos = std::rand() % board.xDimension;     yPos = std::rand() % board.yDimension;     for (int i = 0; i < NUMBEROFTRAPS; i++) {       if ((xPos == trapsInMap[i].position.xPosition &&            yPos == trapsInMap[i].position.yPosition) ||           (xPos == banditsInMap[i].position.xPosition &&            yPos == banditsInMap[i].position.yPosition)) {         match = true;       }     }   } while (match);    Player alvaro = {.position = {.xPosition = xPos, .yPosition = yPos}};    // The order of the turn is the following:   // 1. Board is drawn.   // 2. User is asked for movement direction.   // 3. Player moves in the chosen direction.   // 4. Bandits move.   int maxTurnos = INT_MAX;   for (int i = 0; i <= maxTurnos; i++) {     drawBoard(alvaro, trapsInMap, banditsInMap, treasure);     Direction direction;     do {       direction = askDirection();       std::cout << std::endl;     } while (direction == WRONG_DIRECTION);     movePlayer(alvaro, direction);     for (int i = 0; i < NUMBEROFBANDITS; i++) {       moveBandit(banditsInMap[i]);     }     std::cout << "\x1B[2J\x1B[H";   } }  void drawBoard(     /* in */ Player player,     /* in */ Trap totalTraps[],     /* in */ Bandit totalBandits[],     /* in */ Treasure treasure)  // Draws a (board.xDimension * board.yDimension) grid. // Elements are drawn using .location.?Dimensions.  // Precondition: 0 <= Player.xPosition <= board.xDimension && //      0 <= player.position.yPosition <= board.yDimension  && //      board.xDimension > 0  && board.yDimension > 0 && // Postcondition: The grid has been drawn. //      All elements have been drawn. //      If the player is in the same square than the treasure, //      the game ends with victory. //      If the player is in the same square than a bandit or //      a trap, the game ends with defeat. {   bool squareDrawn = false;   for (int y = 0; y <= board.yDimension; y++) {     for (int x = 0; x <= board.xDimension; x++) {       // Traps are drawn       for (int z = 0; z <= NUMBEROFTRAPS; z++) {         Trap trapToDraw = totalTraps[z];         if (trapToDraw.position.xPosition == x &&             trapToDraw.position.yPosition == y) {           std::cout << trapToDraw.symbol;           squareDrawn = true;         }       }       // Bandits are drawn.       // In case of collision with a trap,       // only the second is drawn.       for (int z = 0; z <= NUMBEROFBANDITS; z++) {         Bandit banditToDraw = totalBandits[z];         if (banditToDraw.position.xPosition == x &&             banditToDraw.position.yPosition == y && !squareDrawn) {           std::cout << banditToDraw.symbol;           squareDrawn = true;         }       }        // Treasure is drawn. If position of treasure == position of player       // game ends with victory       if (x == treasure.position.xPosition &&           y == treasure.position.yPosition) {         if (treasure.position.xPosition == player.position.xPosition &&             treasure.position.yPosition == player.position.yPosition) {           endGame(VICTORY);         }          std::cout << "X";         continue;       }        if (x == player.position.xPosition && y == player.position.yPosition) {         if (squareDrawn)           endGame(DEFEAT);         std::cout << "P";         continue;       }       // Empty square "." is drawn. It only gets printed if there is nothing       // on the square.       if (!squareDrawn)         std::cout << ".";       squareDrawn = false;     }     std::cout << std::endl;   } }  Direction askDirection() {    // Asks the user to input a direction and returns it.   // Precondition: -   // Poscondition:   // Return: a Direction value containing the direction chosen or   // WRONG_DIRECTION.    std::cout << "Select [L]eft, [R]ight, [T]op or [B]ottom: ";   char answer;   std::cin.get(answer);    Direction chosenDirection;   switch (std::toupper(answer)) {   case 'L':     chosenDirection = LEFT;     break;   case 'R':     chosenDirection = RIGHT;     break;   case 'T':     chosenDirection = TOP;     break;   case 'B':     chosenDirection = BOTTOM;     break;   default:     chosenDirection = WRONG_DIRECTION;   }   return chosenDirection; }  void movePlayer(     /* inout */ Player &player,   // Player of the game     /* in */ Direction direction) // Direction previously chosen.                                   // It is represented by a Direction object,                                   // different from WRONG_DIRECTION.  // Moves player in the chosen direction, by altering its coordinates. If the // player would finish out of the board, no movement is made.  // Precondition: 0 <= Player.xPosension <= board.xDimension && //        0 <= player.position.yPosition <= board.yDimension  && //        board.xDimension > 0  && board.yDimension > 0 && //        direction in {LEFT; RIGHT; TOP; BOTTOM} && // Postcondition: player coordinates have been altered && //        player remains inside the board. {   switch (direction) {   case RIGHT:     if (player.position.xPosition < board.xDimension)       player.position.xPosition += 1;     break;   case LEFT:     if (player.position.xPosition > 0)       player.position.xPosition -= 1;     break;   case TOP:     if (player.position.yPosition > 0)       player.position.yPosition -= 1;     break;   case BOTTOM:     if (player.position.yPosition < board.yDimension)       player.position.yPosition += 1;     break;   } }  void moveBandit(     /* inout */ Bandit &bandit) // Player of the game                                 // It is represented by a Direction object,                                 // different from WRONG_DIRECTION.  // Moves player in the chosen direction, by altering its coordinates. If the // player would finish out of the board, no movement is made.  // Precondition: 0 <= Player.xPosension <= board.xDimension && //        0 <= player.position.yPosition <= board.yDimension  && //        board.xDimension > 0  && board.yDimension > 0 && //        direction in {LEFT; RIGHT; TOP; BOTTOM} && // Postcondition: player coordinates have been altered && //        player remains inside the board. {    int direction = std::rand() % 4;   switch (direction) {   case 0:     if (bandit.position.xPosition < board.xDimension)       bandit.position.xPosition += 1;     break;   case 1:     if (bandit.position.xPosition > 0)       bandit.position.xPosition -= 1;     break;   case 2:     if (bandit.position.yPosition > 0)       bandit.position.yPosition -= 1;     break;   case 3:     if (bandit.position.yPosition < board.yDimension)       bandit.position.yPosition += 1;     break;   } }  void endGame(     /* in */ Result result) // Result of the game.                             // It is either VICTORY or DEFEAT // Cleans screen, prints a good bye message // and ends the game. // Precondition: a condition for ending the game has been found. //              Either player.position == bandit.position || //              player.position == trap.position [DEFEAT] //              or player.position == treasure.position [VICTORY] // Poscondition: game is ended. Greeting message is printed. {   std::string announcement = (result == VICTORY) ? "YOU WIN" : "GAME OVER";   std::cout << "\x1B[2J\x1B[H"; // Resets terminal   std::cout << std::endl << std::endl;   std::cout << "===========================" << std::endl;   std::cout << "||\t\t\t||" << std::endl;   std::cout << "||\t" << announcement << "\t\t||" << std::endl;   std::cout << "||\t\t\t||" << std::endl;   std::cout << "===========================" << std::endl;   exit(1); } ``

## Lista de respuestas

16

¡Ese es un pequeño juego increíble!

## Experiencia del usuario

Antes de zambullirnos en el código, hablemos del juego en sí.

### ` 99887766555443335 OM Cuelga `

A veces, el ejecutable se cuelga cuando lo lanza. Pero solo a veces. ¡Es casi como si suceda ` Bandit6 ` OMPLE! Podríamos encontrar la fuente de este error más tarde.

### ¿Qué se supone que debo hacer?

cuando se presenta con esto:

` ` Bandit7  ``

No está claro de inmediato lo que se supone que debo hacer. El comentario en la línea 7 fue muy útil.

` ` Bandit8 ` `

Sugiero que le diga al jugador cómo jugar el juego imprimiendo este comentario.

### Tal vez use diferentes teclas de movimiento

Este mensaje le dice al jugador que las claves presione:

` ` Bandit9  ``

No estoy seguro de por qué eligió escribir "TOP" e "Bottom" en lugar de "arriba" y "Abajo". El jugador "se desplaza". El jugador no "se mueve arriba". Además, las teclas LRTB no son realmente naturales para el movimiento. La mayoría de los jugadores se utilizarán para WASD (W-UP, A-IZQUIERDO, S-DOWN, D-DERECHO). Sospecho que si no le dices a los jugadores qué claves presionan, asumirán WASD. También es más cómodo para las manos. Puede poner su mano izquierda en WASD y su mano derecha en la tecla ENTER.

## El código

OK, eso es suficiente de eso. Esto es CODEREVIEW, NO GAMEREVIEWVIEW.

### [13-14] Constantes mutables

Para que tenga estas constantes que no son ` Treasure1 horm. `

` ` Treasure2 ` `

Para declarar una constante en C ++, use el ` 99887776655443343 palabra clave. Además, Treasure4 es generalmente reservado para macros. Así que deberías cambiar eso a esto: `

` ` Treasure5  ``

Decirle al compilador "Esta es una constante" podría hacer que sus líneas tengan un poco más, pero el compilador puede ayudarlo si le da una mejor comprensión de su programa. Si en algún momento de su programa, usted hace esto:

` ` Treasure6 ` `

El compilador le dirá que cometió un error.

### [18-21] Nombres de variables de miembro largo

Para mí, ` Treasure7 ` y ` Treasure8 son innecesariamente largos. No es necesario poner Treasure9 en el nombre porque el 99887766655443350 ya es una posición. Así que terminas haciendo escribiendo esto así: `

` ` Player1 ` `

Estás escribiendo "posición" dos veces. Realmente debería acortar estos nombres a su esencia y solo usar ` Player2 ` y ` Player3 `.

### [26-30] Una constante mutable y una constante no utilizada

Aquí está el ` Player4 ` Struct:

` ` Player5  ``

En ningún momento vi "Alvaro" impreso en la pantalla cuando estaba jugando este juego. No estoy seguro de por qué su ` Player6 está ahí. `

` Player7 Nunca cambie por lo que debe ser Player8 . Player9 , name0 name1 TODO LLEVAR ABAJO ESTE name2 . Cada name3 está almacenando el mismo name4 . Realmente debería poner esta información duplicada en un solo lugar. name5 debe ser name6 `. Esto significa que ahora se puede acceder a ` name7 como name8 o name9 . Aún puede acceder al símbolo de la instancia ( 99887766555443370 ), pero le sugiero que use GameEntity1 para evitar que los lectores confusos. Poniendo esto todos juntos, obtenemos este nuevo GameEntity2 struct. `

` ` GameEntity3 ` `

Debe usar ` GameEntity4 ` para ` GameEntity5 `, ` GameEntity6 ` y ` 998877665554433777 Structs también. `

### ` [54-57] Inicializando una variable global con inicializadores designados `

` Esto es bastante peculiar de código: GameEntity8 Está creando una estructura anónima, que se ve casi lo mismo que una estructura existente ( 99887776655443379 ). Está creando una variable global struct GameEntity { Location position; char symbol; }; 0 . Creo que realmente quieres crear una constante global. También estás usando DE inicializadores ignados struct GameEntity { Location position; char symbol; }; 1 . Si habilita todas las advertencias al pasar estas indicadoras a su compilador struct GameEntity { Location position; char symbol; }; 2 `, su compilador debe indicarle que "los inicializadores designados son una característica C99". Los inicializadores designados no son una característica de C ++. Debe usar la inicialización de abrazadera en su lugar. Sugiero que reemplace ese código con esto:

` ` struct GameEntity {     Location position;     char symbol; }; 3 ` `

En el futuro, siempre debe pasar al menos ` struct GameEntity { Location position; char symbol; }; 4 ` y editar su código hasta que no haya advertencias.

Aquí, está usando ` struct GameEntity { Location position; char symbol; }; 5 ` de nuevo. También estás usando enumanos de tipografía débil.

` ` struct GameEntity {     Location position;     char symbol; }; 6 ` `

Tipo débilmente escrito básicamente significa que este código es válido:

` ` struct GameEntity {     Location position;     char symbol; }; 7  ``

Los enumnos regulares son otra de esas características C que nunca debe usar en C ++. En C ++, debe usar enumeres fuertemente mecanografiados colocando ` struct GameEntity { Location position; char symbol; }; 8 ` (o ` struct GameEntity { Location position; char symbol; }; 99 ` pero la mayoría de las personas usan ` int main() { std::srand(std::time(0)); GameEntity treasure = { { std::rand() % board.xDimension, std::rand() % board.yDimension}, TREASURESYMBOL }; GameEntity trapsInMap[NUMBEROFTRAPS]; setEntityPositions(trapsInMap, NUMBEROFTRAPS, TRAPSYMBOL); GameEntity banditsInMap[NUMBEROFBANDITS]; setEntityPositions(banditsInMap, NUMBEROFBANDITS, BANDITSYMBOL); GameEntity alvaro; setPlayerPosition(alvaro, PLAYERSYMBOL); 0 `) Después de ` 99887776655443391 . Esto tiene dos efectos. En primer lugar, le impide simplemente escribir int main() { std::srand(std::time(0)); GameEntity treasure = { { std::rand() % board.xDimension, std::rand() % board.yDimension}, TREASURESYMBOL }; GameEntity trapsInMap[NUMBEROFTRAPS]; setEntityPositions(trapsInMap, NUMBEROFTRAPS, TRAPSYMBOL); GameEntity banditsInMap[NUMBEROFBANDITS]; setEntityPositions(banditsInMap, NUMBEROFBANDITS, BANDITSYMBOL); GameEntity alvaro; setPlayerPosition(alvaro, PLAYERSYMBOL); 2 o int main() { std::srand(std::time(0)); GameEntity treasure = { { std::rand() % board.xDimension, std::rand() % board.yDimension}, TREASURESYMBOL }; GameEntity trapsInMap[NUMBEROFTRAPS]; setEntityPositions(trapsInMap, NUMBEROFTRAPS, TRAPSYMBOL); GameEntity banditsInMap[NUMBEROFBANDITS]; setEntityPositions(banditsInMap, NUMBEROFBANDITS, BANDITSYMBOL); GameEntity alvaro; setPlayerPosition(alvaro, PLAYERSYMBOL); 3 . Le obliga a escribir int main() { std::srand(std::time(0)); GameEntity treasure = { { std::rand() % board.xDimension, std::rand() % board.yDimension}, TREASURESYMBOL }; GameEntity trapsInMap[NUMBEROFTRAPS]; setEntityPositions(trapsInMap, NUMBEROFTRAPS, TRAPSYMBOL); GameEntity banditsInMap[NUMBEROFBANDITS]; setEntityPositions(banditsInMap, NUMBEROFBANDITS, BANDITSYMBOL); GameEntity alvaro; setPlayerPosition(alvaro, PLAYERSYMBOL); 4 que es mucho más claro. En segundo lugar, no permite que los moldes implícitos en el tipo subyacente. Así que esos enumeres deben escribirse así: `

` ` int main() {     std::srand(std::time(0));      GameEntity treasure = {         { std::rand() % board.xDimension,           std::rand() % board.yDimension},         TREASURESYMBOL     };      GameEntity trapsInMap[NUMBEROFTRAPS];     setEntityPositions(trapsInMap, NUMBEROFTRAPS, TRAPSYMBOL);      GameEntity banditsInMap[NUMBEROFBANDITS];     setEntityPositions(banditsInMap, NUMBEROFBANDITS, BANDITSYMBOL);      GameEntity alvaro;     setPlayerPosition(alvaro, PLAYERSYMBOL); 5 ` `

### [63] Pasando las matrices de C a funciones

Aquí, está declarando una función que toma algunas matrices como parámetros.

` ` int main() {     std::srand(std::time(0));      GameEntity treasure = {         { std::rand() % board.xDimension,           std::rand() % board.yDimension},         TREASURESYMBOL     };      GameEntity trapsInMap[NUMBEROFTRAPS];     setEntityPositions(trapsInMap, NUMBEROFTRAPS, TRAPSYMBOL);      GameEntity banditsInMap[NUMBEROFBANDITS];     setEntityPositions(banditsInMap, NUMBEROFBANDITS, BANDITSYMBOL);      GameEntity alvaro;     setPlayerPosition(alvaro, PLAYERSYMBOL); 6 ` `

Las matrices de pila de paso a las funciones son otra cosa que usted puede hacerlo en C ++, pero probablemente no debería. Considere reemplazar todos sus usos de matrices de C con un contenedor de C ++ como ` int main() { std::srand(std::time(0)); GameEntity treasure = { { std::rand() % board.xDimension, std::rand() % board.yDimension}, TREASURESYMBOL }; GameEntity trapsInMap[NUMBEROFTRAPS]; setEntityPositions(trapsInMap, NUMBEROFTRAPS, TRAPSYMBOL); GameEntity banditsInMap[NUMBEROFBANDITS]; setEntityPositions(banditsInMap, NUMBEROFBANDITS, BANDITSYMBOL); GameEntity alvaro; setPlayerPosition(alvaro, PLAYERSYMBOL); 7 o Bandit98 . `

### [70] ` int main() { std::srand(std::time(0)); GameEntity treasure = { { std::rand() % board.xDimension, std::rand() % board.yDimension}, TREASURESYMBOL }; GameEntity trapsInMap[NUMBEROFTRAPS]; setEntityPositions(trapsInMap, NUMBEROFTRAPS, TRAPSYMBOL); GameEntity banditsInMap[NUMBEROFBANDITS]; setEntityPositions(banditsInMap, NUMBEROFBANDITS, BANDITSYMBOL); GameEntity alvaro; setPlayerPosition(alvaro, PLAYERSYMBOL); 9 CABEZ CABEITO ALEATORENTE PERO C ++ PERO UTILICE C 998877766554433100 en lugar `

en la línea 4, usted incluye el encabezado de números aleatorios de C ++

` ` Player01 ` `

Pero luego en la línea 70, sembrará el generador de números aleatorios de C con la función de tiempo C.

` ` Player02 ` `

El encabezado aleatorio de C ++ consiste en generadores y distribuciones. Los generadores de números pseudo-aleatorios producen una corriente de bits pseudo-aleatorios. Las distribuciones toman los bits aleatorios y distribúanlos a través de un rango. Sugiero que se siembra un ` Player03 generador usando un Player04 . `

` ` Player05 ` `

Ahora que ha sembrado el ` Player06 Player077 ` Player096554433109 Inclusive. Harías esto:

` ` Player10 ` `

Dado que la semilla ahora se almacena en un objeto 9988776665544331111 y no tiene que pasar ` Player12 ` a todas las funciones que necesitan variables aleatorias.

### Funciones grandes

Hay algunas funciones muy grandes. Debe cortar su programa en buenas funciones limpias que cada uno para hacer un trabajo específico. Por ejemplo, ` Player13 ` debe llamar a las funciones a ` Player14 `, ` Player15 `, ` Player16 Player17 ` .

### Funciones idénticas

` Player18 ` y ` Player19 son bastante iguales. Sugiero que tenga una función para mover "cosas". (Simplemente cambie el nombre Player20 a Player21 También debe tener una función para generar instrucciones aleatorias: `

` ` Player22  ``

Para mover un bandido, ` Player23 . `

Para mover un jugador, ` Player24 `.

### Comprobación de errores

La función ` Player25 puede devolver una dirección válida o puede devolver Player26 . Manejando el caso donde el jugador ingresa una dirección mala se maneja en otro lugar. Esto realmente no tiene sentido para mí. Player27 siempre debe devolver una dirección válida. Player28 debe ser responsable de tratar con el caso donde el jugador ingresa una dirección no válida. `

` Estás usando Player29 `

para obtener un carácter a la vez. Esto combinado con el manejo del error fuera de ` Player30 es la razón por la que esto sucede cuando el jugador ingresa un carácter no válido: `

` ` Player31  ``

realmente deberías estar gett ng toda la línea como esta:

` ` Player32  ``

` ` Player33  ``

Cuando el jugador ingresa un mal carácter, debe mover el cursor hacia arriba, desactivar la línea y volver a intentarlo. Con los códigos de escape ANSI, eso es ` Player34 ` y ` Player35 . También sugiero que coloque estas secuencias de caracteres en constantes para que el código sea más legible. Deberías poner algo así en la parte superior del archivo: `

` ` Player36  ``

Así es como implementaría ` Player37 `.

` ` Player38  ``

¡Estoy fuera de tiempo! Espero que hayas encontrado útil algunos de mis consejos!

That's an awesome little game!

## User experience

Before we dive into the code, let's talk about the game itself.

### `Rand`om hangs

Sometimes, the executable hangs when I launch it. But only sometimes. It's almost as if it happens `rand`omly! We might find the source of this bug later.

### What am I supposed to do?

When presented with this:

``........... ........... ...TX...T.. ......P.... ........... B.......... ........T.. ........... ........B.. ........... ........... Select [L]eft, [R]ight, [T]op or [B]ottom: ``

It's not immediately clear what I'm supposed to do. The comment on line 7 was quite helpful.

``/**  * DUNGEON: a simple game for the terminal. The objective of the  * game is that the player ("P") reaches the treasure ("X")  * avoiding the traps ("T") and the bandits ("B").  * Bandits move randomly each turn.  * */ ``

I suggest that tell the player how to play the game by printing this comment.

### Maybe use different movement keys

This message tells the player which keys to press:

``Select [L]eft, [R]ight, [T]op or [B]ottom: ``

I'm not sure why you chose to write "top" and "bottom" instead of "up" and "down". The player "moves up". The player doesn't "move top". Also, the keys LRTB aren't really natural for movement. Most players will be used to WASD (W-up, A-left, S-down, D-right). I suspect that if you don't tell players which keys to press, they will assume WASD. It's also more comfortable for the hands. You can put your left hand on WASD and your right hand on the enter key.

### I pressed the wrong key

If I press "Z", this happens:

``T........T. ....B...... ........B.. T.......... ........... ........... ........... ........P.. ........... ........X.. ........... Select [L]eft, [R]ight, [T]op or [B]ottom: Z  Select [L]eft, [R]ight, [T]op or [B]ottom: Select [L]eft, [R]ight, [T]op or [B]ottom: ``

So you leave behind my mistake, then you print out an empty line, then you tell me to select a direction twice. I suggest that you simply clear the line when the player makes a mistake.

## The code

OK, that's enough of that. This is CodeReview, not GameReview.

### [13-14] Mutable constants

So you have these constants that aren't `const`ant.

``int NUMBEROFTRAPS = 3; int NUMBEROFBANDITS = 2; ``

To declare a constant in C++, use the `const` keyword. Also, `ALLCAPS` is generally reserved for macros. So you should change that to this:

``const int number_of_traps = 3; const int number_of_bandits = 2; ``

Telling the compiler "this is a constant" might make your lines a little longer but the compiler can help you if you give it a better understanding of your program. If at some point in your program you do this:

``number_of_traps = 7; ``

The compiler will tell you that you made a mistake.

### [18-21] Long member variable names

To me, `xPosition` and `yPosition` are unnecessarily long. There's no need to put `Position` in the name because the `struct` is already a position. So you end up doing writing this like this:

``Location position; position.xPosition = 4; ``

You're writing "position" twice. You really should shorten these names to their essence and just use `x` and `y`.

### [26-30] A mutable constant and an unused constant

Here's the `Player` struct:

``struct Player {   Location position;   char symbol = 'P';   std::string name = "alvaro"; }; ``

At no point did I ever see "alvaro" printed to the screen when I was playing this game. I'm not sure why its `name` is there.

`symbol` never changes so it should be `const`. `Trap`, `Bandit` and `Treasure` all carry around this `char symbol`. Every `Bandit` instance is storing the same `symbol`. You really should put this duplicate information in one place. `symbol` should be `static`. This means that `symbol` can now be accessed as `Player::symbol` or `Bandit::symbol`. You can still access the symbol from the instance (`player.symbol`) but I suggest you use `Player::symbol` to avoid confusing readers. Putting this all together we get this new `Player` struct.

``struct Player {   Location position;   static const char symbol = 'P'; }; ``

You should use `static const` for the `Trap`, `Bandit` and `Treasure` structs as well.

### [54-57] Initializing a global variable with designated initializers

This is quite a peculiar bit of code:

``struct {   int xDimension;   int yDimension; } board = {.xDimension = 10, .yDimension = 10}; ``

You're creating an anonymous struct, which looks pretty much the same as an existing struct (`Location`). You're creating a global variable `board`. I think you actually want to create a global constant. You're also using designated initializers `{.xDimension = 10, .yDimension = 10}`. If you enable all warnings by passing these flags to your compiler `-Wall -Wextra -pedantic`, your compiler should tell you that "designated initializers are a C99 feature". Designated initializers are not a C++ feature. You should use brace-initialization instead. I suggest that you replace that code with this:

``const Location board_size = {10, 10}; ``

In future, you should always pass at least `-Wall -Wextra -pedantic` and edit your code until there are no warnings.

### [60-61] Weakly typed enums

Here, you're using `ALLCAPS` again. You're also using weakly typed enums.

``enum Direction { RIGHT, LEFT, TOP, BOTTOM, WRONG_DIRECTION }; enum Result { VICTORY, DEFEAT }; ``

Weakly typed basically means that this code is valid:

``int dir = TOP; ``

Regular enums are another one of those C features that you should never use in C++. In C++, you should use strongly typed enums by putting `class` (or `struct` but most people just use `class`) after `enum`. This has two effects. Firstly, it stops you from just writing `RIGHT` or `LEFT`. It forces you to write `Direction::RIGHT` which is much clearer. Secondly, it disallows implicit casts to the underlying type. So those enums should be written like this:

``enum class Direction {   right, left, top, bottom, wrong }; enum class Result {   victory, defeat }; ``

### [63] Passing C arrays to functions

Here, you're declaring a function that takes a few arrays as parameters.

``void drawBoard(Player, Trap[], Bandit[], Treasure); ``

Passing stack arrays to functions is another thing that you can do in C++ but you probably shouldn't. Consider replacing all of your usages of C arrays with a C++ container like `std::vector<Trap>` or `std::array<Trap, number_of_traps>`.

### [70] `#include` C++ random header but use C `rand` instead

At line 4, you include the C++ random numbers header

``#include <random> ``

But then at line 70, you seed the C random number generator with the C time function.

``std::srand(std::time(0)); ``

The C++ random header consists of generators and distributions. Pseudo-random number generators produce a stream of pseudo-random bits. Distributions take the random bits and distribute them across a range. I suggest that you seed an `std::mt19937` generator using an `std::random_device`.

``std::random_device device; std::mt19937 gen{device()}; ``

Now that you have seeded the `std::mt19937` pseudo-random number generator, you start generating some numbers. Let's say you want to generate random `int`s between `0` and `board_size.x - 1` inclusive. You would do this:

``std::uniform_int_distribution<int> dist{0, board_size.x - 1}; const int xPos = dist(gen); ``

Since the seed is now stored in an `std::mt19937` object and not globally, you have to pass `gen` to all of the functions that need random variables.

### Big functions

There are a few very big functions. You should chop up your program into nice neat little functions that each to do one specific job. For example, `drawBoard` should call functions to `drawPlayer`, `drawTreasure`, `drawBandit` and `drawTrap`.

### Identical functions

`moveBandit` and `movePlayer` are pretty much exactly the same. I suggest that you have one function for moving "things". (Just rename `movePlayer` to `moveObject(Location &, Direction)`. You should also have a function for generating random directions:

``Direction getRandDir(std::mt19937 &gen) {   std::uniform_int_distribution<int> dist{0, 3};   return static_cast<Direction>(dist(gen)); } ``

To move a bandit, `moveObject(bandit.pos, getRandDir())`.

To move a player, `moveObject(player.pos, askDir())`.

### Error checking

The function `askDirection` might return a valid direction or it might return `WRONG_DIRECTION`. Handling the case where the player inputs a bad direction is handled elsewhere. This doesn't really make sense to me. `askDirection` should always return a valid direction. `askDirection` should be responsible for dealing with the case where the player inputs an invalid direction.

You're using `std::cin.get` to get one character at a time. This combined with handling the error outside of `askDirection` is the reason why this happens when the player inputs an invalid character:

``T........T. ....B...... ........B.. T.......... ........... ........... ........... ........P.. ........... ........X.. ........... Select [L]eft, [R]ight, [T]op or [B]ottom: Z  Select [L]eft, [R]ight, [T]op or [B]ottom: Select [L]eft, [R]ight, [T]op or [B]ottom: ``

You really should be getting the whole the line like this:

``std::string input; std::cin >> input; ``

This way, you can check if the player inputted too many characters:

``if (input.size() != 1) {   std::cout << "One character please\n"; } ``

When the player inputs a bad character, you should move the cursor up, clear the line and try again. With ANSI escape codes, that's `"\x1B[1A"` and `"\x1B[0K"`. I also suggest that you put these character sequences into constants to make the code more readable. You should put something like this right at the top of the file:

``const char cursorUp[] = "\x1B[1A"; const char clearLine[] = "\x1B[0K"; ``

This is how I would implement `askDirection`.

``Dir askDirection() {   std::cout << "dir> ";   std::string input;   std::cin >> input;   if (input.size() == 1) {     switch (std::toupper(input[0])) {       case 'W':         return Dir::up;       case 'A':         return Dir::left;       case 'S':         return Dir::down;       case 'D':         return Dir::right;     }   }   std::cout << cursorUp << clearLine;   return askDirection(); } ``

I'm out of time! I hope you found some of my advice helpful!

22

En general, esto está realmente bien hecho. Se ha perdido las trampas habituales de usar números mágicos, no crear estructuras para artículos relacionados y otras cosas comunes. ¡Tan agradable trabajo! Creo que podría mejorarse con los siguientes cambios.

# tipos vs. variables

Has creado un tipo para ` Location es genial. Mirando los tipos para Player , Trap2 , Bandit3 y 9988776655544334 , son idénticos, excepto que < Código> 9988776655544335 ` tiene una cadena ` name65544336 , que nunca se usa en cualquier lugar del código. Dado que, tiene sentido para mí hacer un tipo algo como GameEntity , y crear variables para el jugador, trampas, bandidos y tesoros. Algo así: `

` ` struct GameEntity {     Location position;     char symbol; };  ` `

En Main, usted crearía las variables así:

` ` int main() {     std::srand(std::time(0));      GameEntity treasure = {         { std::rand() % board.xDimension,           std::rand() % board.yDimension},         TREASURESYMBOL     };      GameEntity trapsInMap[NUMBEROFTRAPS];     setEntityPositions(trapsInMap, NUMBEROFTRAPS, TRAPSYMBOL);      GameEntity banditsInMap[NUMBEROFBANDITS];     setEntityPositions(banditsInMap, NUMBEROFBANDITS, BANDITSYMBOL);      GameEntity alvaro;     setPlayerPosition(alvaro, PLAYERSYMBOL);   ``

La función ` Player0 solo itará sobre la matriz y establecería la posición a una posición aleatoria y el símbolo en el símbolo pasado para cada entidad en la matriz. (Y, por supuesto, deberá definir Player1 , Player2 , 99887766555443313 y 99887766555443314 apropiadamente). `

# Mejoras en bucle

No me gusta el bucle que tiene en ` Player5 `. Posita que hay un número máximo de turnos después de lo cual se realiza el juego. Pero ese no es el caso. El juego se hace cuando el jugador cae en una trampa, es robado por un bandido, o encuentra el tesoro. Además, el código que no detiene el juego se encuentra en una función diferente, lo que dificulta que alguien lee el código para descubrir la condición de finalización.

Lo que haría es tener ` Player6 ` devolver Player7 , ` Player18 `, o ` Player9 . Si devuelve Trap0 o Trap1 Llame Trap2 . No tendría Trap3 Llame Trap4 . En su lugar, después de que regresara, saldría del bucle. Así que Trap5 continuaría (de lo que tengo arriba) así: `

` ` Trap6 ` `

# DOCUMENTO OBSCURE BAPORTE

Notará que introduje una nueva función llamada desde ` Trap7 ` Nombrado ` Trap8 . Esto se debe a que esta línea es incomprensible: `

` ` Trap9 ` `

No hago muchos programas basados ​​en la consola, así que no tenía idea de lo que era. Cuando lo ejecuto en mi depurador, sale:

[2J [H ...........

......... t [2j [H

Cuando lo ejecuto en un terminal, se borra la pantalla que establece el cursor en la parte superior izquierda. Al ponerlo en una función, usted muestra claramente lo que hace. Además, puede llamarlo en otro lugar y saber que tiene la cadena correcta. Cuando ejecuto la aplicación, no se aclara antes de dibujar la placa la primera vez. Movería la llamada de la función en ` Bandit0 `.

# Use más funciones

Has hecho un buen trabajo que se rompe esto en funciones, pero creo que podrías hacer aún más. En ` Bandit11 , verificar el cuadrado actual contra trampas y bandidos es esencialmente el mismo código. Lo escribiría como algo así: `

` ` Bandit2 ` `

Luego, la función ` 998877766554433333 ` itería sobre la matriz pasada:

` ` Bandit4 ` `

Overall, this is really well done. You've missed the usual traps of using magic numbers, not creating structures for related items, and other common things. So nice work! I think it could be improved with the following changes.

# Types vs. Variables

You've created a type for `Location` which is great. Looking at the types for `Player`, `Trap`, `Bandit`, and `Treasure`, they're identical, except that `Player` has a `name` string, which is never used anywhere in the code. Given that, it makes sense to me to make a type something like `GameEntity`, and create variables for the player, traps, bandits, and treasures. Something like this:

``struct GameEntity {     Location position;     char symbol; }; ``

In main, you'd create the variables like so:

``int main() {     std::srand(std::time(0));      GameEntity treasure = {         { std::rand() % board.xDimension,           std::rand() % board.yDimension},         TREASURESYMBOL     };      GameEntity trapsInMap[NUMBEROFTRAPS];     setEntityPositions(trapsInMap, NUMBEROFTRAPS, TRAPSYMBOL);      GameEntity banditsInMap[NUMBEROFBANDITS];     setEntityPositions(banditsInMap, NUMBEROFBANDITS, BANDITSYMBOL);      GameEntity alvaro;     setPlayerPosition(alvaro, PLAYERSYMBOL); ``

The function `setEntityPositions()` would just iterate over the array and set the position to a random position and the symbolxc2xa0to the passed-in symbol for each entity in the array. (And of course, you'll need to define `TRAPSYMBOL`, `BANDITSYMBOL`, `PLAYERSYMBOL`, and `TREASURESYMBOL` appropriately.)

# Looping Improvements

I don't like the loop you have in `main()`. It posits that there is some maximum number of turns after which the game is done. But that's not the case. The game is done when the player falls into a trap, is robbed by a bandit, or finds the treasure. Additionally, the code that does stop the game is way down in a different function making it difficult for someone reading the code to figure out the ending condition.

What I would do is have `drawBoard()` return either `VICTORY`, `DEFEAT`, or `CONTINUE`. If it returns `VICTORY` or `DEFEAT` call `endGame()`. I would not have `endGame()` call `exit()`. Instead, after it returned, I would exit the loop. So `main()` would continue (from what I have above) like this:

``    int gameCondition = drawBoard(alvaro, trapsInMap, banditsInMap, treasure);     do {         Direction direction;         do {             direction = askDirection();             std::cout << std::endl;         } while (direction == WRONG_DIRECTION);         movePlayer(alvaro, direction);         for (int i = 0; i < NUMBEROFBANDITS; i++) {             moveBandit(banditsInMap[i]);         }         clearScreenAndMoveToHome();         gameCondition = drawBoard(alvaro, trapsInMap, banditsInMap, treasure);     } while (gameCondition == CONTINUE);     endGame (gameCondition); } ``

# Document Obscure Behavior

You'll notice that I introduced a new function called from `main()` named `clearScreenAndMoveToHome()`. This is because this line is incomprehensible:

``std::cout << "\x1B[2J\x1B[H"; ``

I don't do a lot of console-based programs, so I had no idea what this was. When I run it in my debugger, it outputs:

[2J[H...........

.........T[2J[H

When I run it in a terminal, it clears the screen sets the cursor to the upper left. By putting it into a function, you show clearly what it does. Furthermore, you can call it elsewhere and know you have the right string. When I run the app, it doesn't clear before drawing the board the first time. I would move the function call into `drawBoard()`.

# Use More Functions

You've done a really good job breaking this into functions, but I think you could do even more. In `drawBoard()`, checking the current square against traps and bandits is essentially the same code. I would write it as something like this:

``for (int y...) {     for (int x... {         bool squareDrawn = checkSquareAgainstEntity(x, y, totalTraps, NUMBEROFTRAPS);          if (!squareDrawn) {             squareDrawn = checkSquareAgainstEntity(x, y, totalBandits, NUMBEROFBANDITS);         }         // ... etc.     } } ``

Then the `checkSquareAgainstEntity()` function would iterate over the passed in array:

``bool checkSquareAgainstEntity(int x, int y, GameEntity* entities, int numEntities) {     bool result = false;     for (int z = 0; (z < numEntities) && (!result); z++ {         GameEntity nextEntity = entities [ z ];         if (nextEntity.position.xPosition == x &&             nextEntity.position.yPosition == y) {             std::cout << nextEntity.symbol;             result = true;         }     }     return result; } ``

9  Entrada de usuario y lectura de contenidos de archivo  ( User input and reading contents of file )
Para la divulgación completa: esta es una tarea para mi clase de programación y solo quiero consejos o consejos sobre algunos del código. Detalles de asigna...

2  Implementación de la lista de la cola prioritaria  ( Priority queue linked list implementation )
Soy nuevo en Python y quería asegurarme de que mi código responde a la pregunta de mi tarea debido. Mi tarea: Una cola de prioridad es una cola en la que...

4  Búsqueda a través de una lista de contactos para los criterios dados  ( Searching through a contact list for given criteria )
He estado mirando a este código por un tiempo ahora y estoy pensando que hay una manera de optimizarlo (a saber, el if - 9988777665544337 Declaración con ...

2  Solucionador de rompecabezas de rascacielos en Java [cerrado]  ( Skyscraper puzzle solver in java )
cerrado. Esta pregunta es off-topic . Actualmente no está aceptando respuestas. ¿Quieres ...

5  Un juego de sudoku hecho de la lengua del dardo de Google  ( A sudoku game made from googles dart language )
Este es mi primer proyecto web real y nunca he tocado a JavaScript (CSS apenas tocado), así que me salí y fui a Dart por diversión. Aquí hay una demostración...

0  Agregando dos números extremadamente grandes usando una estructura de datos personalizada  ( Adding two extremely large numbers using a custom data structure )
Tengo una implementación para agregar 2 números extremadamente grandes, mayor que el techo proporcionado por long , por ejemplo, 1238913893838383813813813813...

6  Programa de Convertidor de Infix a Postfix  ( Infix to postfix converter program )
Esta es mi tarea. Amablemente ayúdame a verificarlo? Las instrucciones son: Implementar una expresión de infIX en el convertidor de expresión postfix. De...

0  Producto cartesiano de dos tuplas - Python  ( Cartesian product of two tuples python )
Estoy resolviendo el ejercicio 4 de Discusión 3 de CS 61A (2012) de Berkley (2012) (consulte la página 4): Rellene la definición de cartesian_product . ...

10  Mini- (Docker) -Shell  ( Mini docker shell )
Me dieron una asignación para escribir una mini-shell: Para escribir su propia cáscara, deberá comenzar con un programa C que pedirá que el usuario ingre...

7  Optimizando el juego de la vida de Conway en C ++  ( Optimizing conways game of life in c )
¿Cómo podría optimizar aún más mi implementación del juego de la vida de Conway? ¿Y cómo criticarías mis estrategias actuales? Estoy tomando una clase de opti...