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
vote

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
 
vote

¡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.

Presioné la clave incorrecta

Si presiono "Z", esto sucede:

  Treasure0  

Así que dejes atrás mi error, entonces imprimes una línea vacía, entonces me dices que seleccionara una dirección dos veces. Sugiero que simplemente limpie la línea cuando el jugador cometa un error.

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.

[60-61] Enums tipificados débilmente

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  

De esta manera, puede verificar si el jugador ingresó demasiados caracteres:

  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.

Random hangs

Sometimes, the executable hangs when I launch it. But only sometimes. It's almost as if it happens randomly! 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 constant.

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 ints 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
 
vote

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; } 
 
 
     
     

Relacionados problema

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...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos