Advertisement
Cinestra

rabbits

Feb 7th, 2023
947
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 24.75 KB | None | 0 0
  1. // rabbits.cpp
  2.  
  3. // Portions you are to complete are marked with a TODO: comment.
  4. // We've provided some incorrect return statements (so indicated) just
  5. // to allow this skeleton program to compile and run, albeit incorrectly.
  6. // The first thing you probably want to do is implement the utterly trivial
  7. // functions (marked TRIVIAL).  Then get Arena::display going.  That gives
  8. // you more flexibility in the order you tackle the rest of the functionality.
  9. // As you finish implementing each TODO: item, remove its TODO: comment.
  10.  
  11. #include <iostream>
  12. #include <string>
  13. #include <random>
  14. #include <utility>
  15. #include <cstdlib>
  16. #include <cctype>
  17. using namespace std;
  18.  
  19. ///////////////////////////////////////////////////////////////////////////
  20. // Manifest constants
  21. ///////////////////////////////////////////////////////////////////////////
  22.  
  23. const int MAXROWS = 20;               // max number of rows in the arena
  24. const int MAXCOLS = 25;               // max number of columns in the arena
  25. const int MAXRABBITS = 100;           // max number of rabbits allowed
  26.  
  27. const int NORTH = 0;
  28. const int EAST = 1;
  29. const int SOUTH = 2;
  30. const int WEST = 3;
  31. const int NUMDIRS = 4;
  32.  
  33. const int EMPTY = 0;
  34. const int HAS_POISON = 1;
  35.  
  36. ///////////////////////////////////////////////////////////////////////////
  37. // Type definitions
  38. ///////////////////////////////////////////////////////////////////////////
  39.  
  40. class Arena;  // This is needed to let the compiler know that Arena is a
  41. // type name, since it's mentioned in the Rabbit declaration.
  42.  
  43. class Rabbit
  44. {
  45. public:
  46.     // Constructor
  47.     Rabbit(Arena* ap, int r, int c);
  48.  
  49.     // Accessors
  50.     int  row() const;
  51.     int  col() const;
  52.     bool isDead() const;
  53.  
  54.     // Mutators
  55.     void move();
  56.  
  57. private:
  58.     Arena* m_arena;
  59.     int    m_row;
  60.     int    m_col;
  61.     int poison;
  62.     int slow_counter;
  63.     // TODO: You'll probably find that a rabbit object needs additional
  64.     // data members to support your implementation of the behavior affected
  65.     // by poisoned carrots.
  66. };
  67.  
  68. class Player
  69. {
  70. public:
  71.     // Constructor
  72.     Player(Arena* ap, int r, int c);
  73.  
  74.     // Accessors
  75.     int  row() const;
  76.     int  col() const;
  77.     bool isDead() const;
  78.  
  79.     // Mutators
  80.     string dropPoisonedCarrot();
  81.     string move(int dir);
  82.     void   setDead();
  83.  
  84. private:
  85.     Arena* m_arena;
  86.     int    m_row;
  87.     int    m_col;
  88.     bool   m_dead;
  89. };
  90.  
  91. class Arena
  92. {
  93. public:
  94.     // Constructor/destructor
  95.     Arena(int nRows, int nCols);
  96.     ~Arena();
  97.  
  98.     // Accessors
  99.     int     rows() const;
  100.     int     cols() const;
  101.     Player* player() const;
  102.     int     rabbitCount() const;
  103.     int     getCellStatus(int r, int c) const;
  104.     int     numberOfRabbitsAt(int r, int c) const;
  105.     void    display(string msg) const;
  106.  
  107.     // Mutators
  108.     void setCellStatus(int r, int c, int status);
  109.     bool addRabbit(int r, int c);
  110.     bool addPlayer(int r, int c);
  111.     void moveRabbits();
  112.  
  113. private:
  114.     int     m_grid[MAXROWS][MAXCOLS];
  115.     int     m_rows;
  116.     int     m_cols;
  117.     Player* m_player;
  118.     Rabbit* m_rabbits[MAXRABBITS];
  119.     int     m_nRabbits;
  120.     int     m_turns;
  121.  
  122.     // Helper functions
  123.     void checkPos(int r, int c, string functionName) const;
  124.     bool isPosInBounds(int r, int c) const;
  125. };
  126.  
  127. class Game
  128. {
  129. public:
  130.     // Constructor/destructor
  131.     Game(int rows, int cols, int nRabbits);
  132.     ~Game();
  133.  
  134.     // Mutators
  135.     void play();
  136.  
  137. private:
  138.     Arena* m_arena;
  139.  
  140.     // Helper functions
  141.     string takePlayerTurn();
  142. };
  143.  
  144. ///////////////////////////////////////////////////////////////////////////
  145. //  Auxiliary function declarations
  146. ///////////////////////////////////////////////////////////////////////////
  147.  
  148. int randInt(int lowest, int highest);
  149. bool decodeDirection(char ch, int& dir);
  150. bool attemptMove(const Arena& a, int dir, int& r, int& c);
  151. bool recommendMove(const Arena& a, int r, int c, int& bestDir);
  152. int assessRisk(const Arena& a, int row, int c);
  153. void clearScreen();
  154.  
  155. ///////////////////////////////////////////////////////////////////////////
  156. //  Rabbit implementation
  157. ///////////////////////////////////////////////////////////////////////////
  158.  
  159. Rabbit::Rabbit(Arena* ap, int r, int c)
  160. {
  161.     if (ap == nullptr)
  162.     {
  163.         cout << "***** A rabbit must be created in some Arena!" << endl;
  164.         exit(1);
  165.     }
  166.     if (r < 1 || r > ap->rows() || c < 1 || c > ap->cols())
  167.     {
  168.         cout << "***** Rabbit created with invalid coordinates (" << r << ","
  169.             << c << ")!" << endl;
  170.         exit(1);
  171.     }
  172.     m_arena = ap;
  173.     m_row = r;
  174.     m_col = c;
  175.     poison = 0;
  176.     slow_counter = 0;
  177. }
  178.  
  179. int Rabbit::row() const
  180. {
  181.     return m_row;
  182. }
  183.  
  184. int Rabbit::col() const
  185. {
  186.     return m_col;
  187. }
  188.  
  189. bool Rabbit::isDead() const
  190. {
  191.     // TODO: Return whether the Rabbit is dead
  192.  
  193.     if (poison == 2) {
  194.         return true;
  195.     }
  196.  
  197.     else {
  198.         return false;
  199.     }
  200. }
  201.  
  202. void Rabbit::move()
  203. {
  204.     // TODO:
  205.     //   Return without moving if the rabbit has eaten one poisoned
  206.     //   carrot (so is supposed to move only every other turn) and
  207.     //   this is a turn it does not move.
  208.  
  209.     //   Otherwise, attempt to move in a random direction; if can't
  210.     //   move, don't move.  If it lands on a poisoned carrot, eat the
  211.     //   carrot and remove it from the game (so it is no longer on that
  212.     //   grid point).
  213.  
  214.     int Random_direction = randInt(1, 4);
  215.  
  216.     if (poison == 1 && slow_counter == 1){
  217.         slow_counter--;
  218.         return;
  219.     }
  220.  
  221.     if (slow_counter == 0) {
  222.         attemptMove(*m_arena, Random_direction, m_row, m_col);
  223.  
  224.         if (m_arena->getCellStatus(m_row, m_col) == HAS_POISON) {
  225.             m_arena->setCellStatus(m_row, m_col, EMPTY);
  226.             poison++;
  227.         }
  228.     }
  229.  
  230.     if (poison == 1 && slow_counter == 0) {
  231.         slow_counter++;
  232.     }
  233. }
  234.  
  235. ///////////////////////////////////////////////////////////////////////////
  236. //  Player implementation
  237. ///////////////////////////////////////////////////////////////////////////
  238.  
  239. Player::Player(Arena* ap, int r, int c)
  240. {
  241.     if (ap == nullptr)
  242.     {
  243.         cout << "***** The player must be created in some Arena!" << endl;
  244.         exit(1);
  245.     }
  246.     if (r < 1 || r > ap->rows() || c < 1 || c > ap->cols())
  247.     {
  248.         cout << "**** Player created with invalid coordinates (" << r
  249.             << "," << c << ")!" << endl;
  250.         exit(1);
  251.     }
  252.     m_arena = ap;
  253.     m_row = r;
  254.     m_col = c;
  255.     m_dead = false;
  256. }
  257.  
  258. int Player::row() const
  259. {
  260.     return m_row;
  261. }
  262.  
  263. int Player::col() const
  264. {
  265.     return m_col;
  266. }
  267.  
  268. string Player::dropPoisonedCarrot()
  269. {
  270.     if (m_arena->getCellStatus(m_row, m_col) == HAS_POISON)
  271.         return "There's already a poisoned carrot at this spot.";
  272.     m_arena->setCellStatus(m_row, m_col, HAS_POISON);
  273.     return "A poisoned carrot has been dropped.";
  274. }
  275.  
  276. string Player::move(int dir)
  277. {
  278.     // TODO:  Attempt to move the player one step in the indicated
  279.     //        direction.  If this fails,
  280.     //        return "Player couldn't move; player stands."
  281.     //        A player who moves onto a rabbit, and this
  282.     //        returns "Player walked into a rabbit and died."
  283.     //        Otherwise, return one of "Player moved north.",
  284.     //        "Player moved east.", "Player moved south.", or
  285.     //        "Player moved west."
  286.  
  287.     return "Player couldn't move; player stands.";  // This implementation compiles, but is incorrect.
  288.  
  289.     if (attemptMove(*m_arena, dir, m_row, m_col))
  290.     {
  291.         if (m_arena->numberOfRabbitsAt(m_row, m_col) > 0)
  292.         {
  293.             setDead();
  294.             return "Player walked into a rabbit and died";
  295.         }
  296.  
  297.         if (dir == NORTH)
  298.             return "Player moved north. ";
  299.         else if (dir == EAST)
  300.             return "Player moved east. ";
  301.         else if (dir == WEST)
  302.             return "Player moved west. ";
  303.         else if (dir == SOUTH)
  304.             return "Player moved south. ";
  305.         else
  306.             return "Player couldn't move; player stands. ";
  307.  
  308.     }
  309.  
  310. }
  311.  
  312. bool Player::isDead() const
  313. {
  314.     // TODO: Return whether the Player is dead
  315.     // Delete the following line and replace it with the correct code.
  316.     return m_dead;  // This implementation compiles, but is incorrect.
  317. }
  318.  
  319. void Player::setDead()
  320. {
  321.     m_dead = true;
  322. }
  323.  
  324. ///////////////////////////////////////////////////////////////////////////
  325. //  Arena implementation
  326. ///////////////////////////////////////////////////////////////////////////
  327.  
  328. Arena::Arena(int nRows, int nCols)
  329. {
  330.     if (nRows <= 0 || nCols <= 0 || nRows > MAXROWS || nCols > MAXCOLS)
  331.     {
  332.         cout << "***** Arena created with invalid size " << nRows << " by "
  333.             << nCols << "!" << endl;
  334.         exit(1);
  335.     }
  336.     m_rows = nRows;
  337.     m_cols = nCols;
  338.     m_player = nullptr;
  339.     m_nRabbits = 0;
  340.     m_turns = 0;
  341.     for (int r = 1; r <= m_rows; r++)
  342.         for (int c = 1; c <= m_cols; c++)
  343.             setCellStatus(r, c, EMPTY);
  344. }
  345.  
  346. Arena::~Arena()
  347. {
  348.     // TODO:  Deallocate the player and all remaining dynamically allocated
  349.     //        rabbits.
  350.  
  351.     delete m_player;
  352.  
  353.     for (int i = 0; i < m_nRabbits; i++)
  354.     {
  355.         delete m_rabbits[i];
  356.     }
  357.     // Delete each entry in the array of pointers to Rabbits
  358. }
  359.  
  360. int Arena::rows() const
  361. {
  362.     // TODO: TRIVIAL:  Return the number of rows in the arena
  363.     // Delete the following line and replace it with the correct code.
  364.     return m_rows;
  365. }
  366.  
  367. int Arena::cols() const
  368. {
  369.     // TODO: TRIVIAL:  Return the number of columns in the arena
  370.     // Delete the following line and replace it with the correct code.
  371.     return m_cols;
  372. }
  373.  
  374. Player* Arena::player() const
  375. {
  376.     return m_player;
  377. }
  378.  
  379. int Arena::rabbitCount() const
  380. {
  381.     // TODO: TRIVIAL:  Return the number of rabbits in the arena
  382.     // Delete the following line and replace it with the correct code.
  383.     return m_nRabbits;
  384.  
  385. }
  386.  
  387. int Arena::getCellStatus(int r, int c) const
  388. {
  389.     checkPos(r, c, "Arena::getCellStatus");
  390.     return m_grid[r - 1][c - 1];
  391. }
  392.  
  393. int Arena::numberOfRabbitsAt(int r, int c) const
  394. {
  395.     // TODO:  Return the number of rabbits at row r, column c
  396.     // Delete the following line and replace it with the correct code.
  397.  
  398.     int count = 0;
  399.  
  400.     for (int i = 0; i < m_nRabbits; i++)
  401.     {
  402.         if ((m_rabbits[i]->row() == r && m_rabbits[i]->col() == c))
  403.             count++;
  404.     }
  405.  
  406.     return count;  // This implementation compiles, but is incorrect.
  407. }
  408.  
  409. void Arena::display(string msg) const
  410. {
  411.     char displayGrid[MAXROWS][MAXCOLS];
  412.     int r, c;
  413.  
  414.     // Fill displayGrid with dots (empty) and stars (poisoned carrots)
  415.     for (r = 1; r <= rows(); r++)
  416.         for (c = 1; c <= cols(); c++)
  417.             displayGrid[r - 1][c - 1] = (getCellStatus(r, c) == EMPTY ? '.' : '*');
  418.     // c = (a>b) ? a : b mean that if the expression being evaluated is true then a is returned whereas if it is false then b is returned
  419.  
  420.     // Indicate each rabbit's position
  421.     // TODO:  If one rabbit is at some grid point, set the displayGrid char
  422.     //        to 'R'.  If it's 2 though 8, set it to '2' through '8'.
  423.     //        For 9 or more, set it to '9'.
  424.  
  425.     for (r = 1; r <= rows(); r++)
  426.     {
  427.         for (c = 1; c <= cols(); c++)
  428.         {
  429.             int rabbit_count = numberOfRabbitsAt(r, c);
  430.  
  431.             if (rabbit_count == 1)
  432.                 displayGrid[r - 1][c - 1] = 'R';
  433.  
  434.             else if (rabbit_count > 2 && rabbit_count < 9)
  435.                 displayGrid[r - 1][c - 1] = rabbit_count;
  436.  
  437.             else if (rabbit_count > 9)
  438.                 displayGrid[r - 1][c - 1] = '9';
  439.         }
  440.     }
  441.  
  442.  
  443.     // Indicate the player's position
  444.     if (m_player != nullptr)
  445.         displayGrid[m_player->row() - 1][m_player->col() - 1] = (m_player->isDead() ? 'X' : '@');
  446.  
  447.     // Draw the grid
  448.     clearScreen();
  449.     for (r = 1; r <= rows(); r++)
  450.     {
  451.         for (c = 1; c <= cols(); c++)
  452.             cout << displayGrid[r - 1][c - 1];
  453.         cout << endl;
  454.     }
  455.     cout << endl;
  456.  
  457.     // Write message, rabbit, and player info
  458.     if (msg != "")
  459.         cout << msg << endl;
  460.     cout << "There are " << rabbitCount() << " rabbits remaining." << endl;
  461.     if (m_player == nullptr)
  462.         cout << "There is no player!" << endl;
  463.     else if (m_player->isDead())
  464.         cout << "The player is dead." << endl;
  465.     cout << m_turns << " turns have been taken." << endl;
  466. }
  467.  
  468. void Arena::setCellStatus(int r, int c, int status)
  469. {
  470.     checkPos(r, c, "Arena::setCellStatus");
  471.     m_grid[r - 1][c - 1] = status;
  472. }
  473.  
  474. bool Arena::addRabbit(int r, int c)
  475. {
  476.     if (!isPosInBounds(r, c))
  477.         return false;
  478.  
  479.     // Don't add a rabbit on a spot with a poisoned carrot
  480.     if (getCellStatus(r, c) != EMPTY)
  481.         return false;
  482.  
  483.     // Don't add a rabbit on a spot with a player
  484.     if (m_player != nullptr && m_player->row() == r && m_player->col() == c)
  485.         return false;
  486.  
  487.     // If there are MAXRABBITS existing rabbits, return false.  Otherwise,
  488.     // dynamically allocate a new rabbit at coordinates (r,c).  Save the
  489.     // pointer to newly allocated rabbit and return true.
  490.  
  491.     // TODO:  Implement this.
  492.  
  493.     if (rabbitCount() == 100)
  494.         return false;
  495.  
  496.     else
  497.     {
  498.         m_rabbits[m_nRabbits] = new Rabbit(this, r, c);
  499.         m_nRabbits++;
  500.         return true;
  501.     }
  502. }
  503.  
  504. bool Arena::addPlayer(int r, int c)
  505. {
  506.     if (!isPosInBounds(r, c))
  507.         return false;
  508.  
  509.     // Don't add a player if one already exists
  510.     if (m_player != nullptr)
  511.         return false;
  512.  
  513.     // Don't add a player on a spot with a rabbit
  514.     if (numberOfRabbitsAt(r, c) > 0)
  515.         return false;
  516.  
  517.     m_player = new Player(this, r, c);
  518.     return true;
  519. }
  520.  
  521. void Arena::moveRabbits()
  522. {
  523.     // Move all rabbits
  524.     // TODO:  Move each rabbit.  Mark the player as dead if necessary.
  525.     //        Deallocate any dead dynamically allocated rabbit.
  526.  
  527.     // Another turn has been taken
  528.  
  529.     for (int i = 0; i < m_nRabbits; i++)
  530.     {
  531.         Rabbit* pointer_rabbit = m_rabbits[i];
  532.         // m_rabbits[(variable)] is an array of pointers to rabbits
  533.         // Create a pointer that will be able to manipulate a given rabbit
  534.  
  535.         pointer_rabbit->move();
  536.         // Now that the rabbit has moved, let's either see if it is dead or if it kills the player
  537.  
  538.         if (pointer_rabbit->isDead())
  539.         {
  540.             delete pointer_rabbit;
  541.             m_rabbits[i] = m_rabbits[m_nRabbits - 1];
  542.             m_nRabbits--;
  543.             i--;
  544.         }
  545.  
  546.         if (m_player->row() == pointer_rabbit->row() && m_player->col() == pointer_rabbit->col())
  547.         {
  548.             m_player->setDead();
  549.         }
  550.     }
  551.  
  552.     m_turns++;
  553. }
  554.  
  555. bool Arena::isPosInBounds(int r, int c) const
  556. {
  557.     return (r >= 1 && r <= m_rows && c >= 1 && c <= m_cols);
  558. }
  559.  
  560. void Arena::checkPos(int r, int c, string functionName) const
  561. {
  562.     if (!isPosInBounds(r, c))
  563.     {
  564.         cout << "***** " << "Invalid arena position (" << r << ","
  565.             << c << ") in call to " << functionName << endl;
  566.         exit(1);
  567.     }
  568. }
  569.  
  570. ///////////////////////////////////////////////////////////////////////////
  571. //  Game implementation
  572. ///////////////////////////////////////////////////////////////////////////
  573.  
  574. Game::Game(int rows, int cols, int nRabbits)
  575. {
  576.     if (nRabbits < 0)
  577.     {
  578.         cout << "***** Cannot create Game with negative number of rabbits!" << endl;
  579.         exit(1);
  580.     }
  581.     if (nRabbits > MAXRABBITS)
  582.     {
  583.         cout << "***** Trying to create Game with " << nRabbits
  584.             << " rabbits; only " << MAXRABBITS << " are allowed!" << endl;
  585.         exit(1);
  586.     }
  587.     int nEmpty = rows * cols - nRabbits - 1;  // 1 for Player
  588.     if (nEmpty < 0)
  589.     {
  590.         cout << "***** Game created with a " << rows << " by "
  591.             << cols << " arena, which is too small too hold a player and "
  592.             << nRabbits << " rabbits!" << endl;
  593.         exit(1);
  594.     }
  595.  
  596.     // Create arena
  597.     m_arena = new Arena(rows, cols);
  598.  
  599.     // Add player
  600.     int rPlayer;
  601.     int cPlayer;
  602.     do
  603.     {
  604.         rPlayer = randInt(1, rows);
  605.         cPlayer = randInt(1, cols);
  606.     } while (m_arena->getCellStatus(rPlayer, cPlayer) != EMPTY);
  607.     m_arena->addPlayer(rPlayer, cPlayer);
  608.  
  609.     // Populate with rabbits
  610.     while (nRabbits > 0)
  611.     {
  612.         int r = randInt(1, rows);
  613.         int c = randInt(1, cols);
  614.         if (r == rPlayer && c == cPlayer)
  615.             continue;
  616.         m_arena->addRabbit(r, c);
  617.         nRabbits--;
  618.     }
  619. }
  620.  
  621. Game::~Game()
  622. {
  623.     delete m_arena;
  624. }
  625.  
  626. string Game::takePlayerTurn()
  627. {
  628.     for (;;)
  629.     {
  630.         cout << "Your move (n/e/s/w/c or nothing): ";
  631.         string playerMove;
  632.         getline(cin, playerMove);
  633.  
  634.         Player* player = m_arena->player();
  635.         int dir;
  636.  
  637.         if (playerMove.size() == 0)
  638.         {
  639.             if (recommendMove(*m_arena, player->row(), player->col(), dir))
  640.                 return player->move(dir);
  641.             else
  642.                 return player->dropPoisonedCarrot();
  643.         }
  644.         else if (playerMove.size() == 1)
  645.         {
  646.             if (tolower(playerMove[0]) == 'c')
  647.                 return player->dropPoisonedCarrot();
  648.             else if (decodeDirection(playerMove[0], dir))
  649.                 return player->move(dir);
  650.         }
  651.         cout << "Player move must be nothing, or 1 character n/e/s/w/c." << endl;
  652.     }
  653. }
  654.  
  655. void Game::play()
  656. {
  657.     m_arena->display("");
  658.     Player* player = m_arena->player();
  659.     if (player == nullptr)
  660.         return;
  661.     while (!player->isDead() && m_arena->rabbitCount() > 0)
  662.     {
  663.         string msg = takePlayerTurn();
  664.         m_arena->display(msg);
  665.         if (player->isDead())
  666.             break;
  667.         m_arena->moveRabbits();
  668.         m_arena->display(msg);
  669.     }
  670.     if (player->isDead())
  671.         cout << "You lose." << endl;
  672.     else
  673.         cout << "You win." << endl;
  674. }
  675.  
  676. ///////////////////////////////////////////////////////////////////////////
  677. //  Auxiliary function implementation
  678. ///////////////////////////////////////////////////////////////////////////
  679.  
  680.   // Return a uniformly distributed random int from lowest to highest, inclusive
  681. int randInt(int lowest, int highest)
  682. {
  683.     if (highest < lowest)
  684.         swap(highest, lowest);
  685.     static random_device rd;
  686.     static default_random_engine generator(rd());
  687.     uniform_int_distribution<> distro(lowest, highest);
  688.     return distro(generator);
  689. }
  690.  
  691. bool decodeDirection(char ch, int& dir)
  692. {
  693.     switch (tolower(ch))
  694.     {
  695.     default:  return false;
  696.     case 'n': dir = NORTH; break;
  697.     case 'e': dir = EAST;  break;
  698.     case 's': dir = SOUTH; break;
  699.     case 'w': dir = WEST;  break;
  700.     }
  701.     return true;
  702. }
  703.  
  704. // Return false without changing anything if moving one step from (r,c)
  705. // in the indicated direction would run off the edge of the arena.
  706. // Otherwise, update r and c to the position resulting from the move and
  707. // return true.
  708. bool attemptMove(const Arena& a, int dir, int& r, int& c)
  709. {
  710.     // TODO:  Implement this function
  711.     // Delete the following line and replace it with the correct code.
  712.  
  713.     // To move up, you need to subtract rows. The first row is at the top. The last row is at the bottom.
  714.     // To move right, you need to add cols. The first col is at the left. The last row is at the right.
  715.  
  716.     // Check if it's trying to move within bounds, if it is then return false. If not then move accordingly.
  717.  
  718.     if (dir == NORTH) {
  719.         if (r <= 1) return false;
  720.         else r--;
  721.     }
  722.  
  723.     else if (dir == EAST) {
  724.         if (c >= a.cols()) return false;
  725.         else c++;
  726.     }
  727.  
  728.     else if (dir == WEST) {
  729.         if (c <= 1) return false;
  730.         else c--;
  731.     }
  732.  
  733.     else if (dir == SOUTH) {
  734.         if (r >= a.rows()) return false;
  735.         else r++;
  736.     }
  737.  
  738.     return true;
  739. }
  740.  
  741. // Recommend a move for a player at (r,c):  A false return means the
  742. // recommendation is that the player should drop a poisoned carrot and
  743. // not move; otherwise, this function sets bestDir to the recommended
  744. // direction to move and returns true.
  745. bool recommendMove(const Arena& a, int r, int c, int& bestDir)
  746. {
  747.     // TODO:  Implement this function
  748.     // Delete the following line and replace it with your code.
  749.  
  750.     int idle_risk = assessRisk(a, r, c);
  751.  
  752.     if (idle_risk == 0)
  753.         return false;
  754.    
  755.     int least_risk = idle_risk;
  756.  
  757.     int north_risk = assessRisk(a, r - 1, c);
  758.     int south_risk = assessRisk(a, r + 1, c);
  759.     int west_risk = assessRisk(a, r, c - 1);
  760.     int east_risk = assessRisk(a, r, c + 1);
  761.  
  762.     if (north_risk < least_risk && r != 1) {
  763.         least_risk = north_risk;
  764.         bestDir = NORTH;
  765.     }
  766.     if (south_risk < least_risk && r != a.rows()) {
  767.         least_risk = south_risk;
  768.         bestDir = SOUTH;
  769.     }
  770.     if (west_risk < least_risk && c!=1) {
  771.         least_risk = west_risk;
  772.         bestDir = WEST;
  773.     }
  774.     if (east_risk < least_risk && c!=a.cols()) {
  775.         least_risk = east_risk;
  776.         bestDir = EAST;
  777.     }
  778.  
  779.     // Now let's check if least risk is different from idle risk
  780.     // If it is different, then we would recommend moving
  781.     if (idle_risk < least_risk)
  782.     {
  783.         return true;
  784.     }
  785.  
  786.     // If it isn't different, simply return false.
  787.     return false;
  788.  
  789.     // Your replacement implementation should do something intelligent.
  790.     // You don't have to be any smarter than the following, although
  791.     // you can if you want to be:  If staying put runs the risk of a
  792.     // rabbit possibly moving onto the player's location when the rabbits
  793.     // move, yet moving in a particular direction puts the player in a
  794.     // position that is safe when the rabbits move, then the chosen
  795.     // action is to move to a safer location.  Similarly, if staying put
  796.     // is safe, but moving in certain directions puts the player in
  797.     // danger of dying when the rabbits move, then the chosen action should
  798.     // not be to move in one of the dangerous directions; instead, the player
  799.     // should stay put or move to another safe position.  In general, a
  800.     // position that may be moved to by many rabbits is more dangerous than
  801.     // one that may be moved to by few.
  802.     //
  803.     // Unless you want to, you do not have to take into account that a
  804.     // rabbit might be poisoned and thus sometimes less dangerous than one
  805.     // that is not.  That requires a more sophisticated analysis that
  806.     // we're not asking you to do.
  807. }
  808.  
  809. int assessRisk(const Arena& a, int row, int col)
  810. {
  811.  
  812.     int risk = 0;
  813.  
  814.     if (a.numberOfRabbitsAt(row, col) > 0)
  815.     {
  816.         risk += 99;
  817.         return risk;
  818.         // Do not move here lmao
  819.     }
  820.  
  821.     else
  822.     {
  823.         risk += a.numberOfRabbitsAt(row - 1, col); // Rabbits above indicated location
  824.         risk += a.numberOfRabbitsAt(row + 1, col); // Rabbits below indicated location
  825.         risk += a.numberOfRabbitsAt(row, col - 1); // Rabbits left of indicated location
  826.         risk += a.numberOfRabbitsAt(row, col + 1); //Rabbits right of indicated location
  827.  
  828.         return risk;
  829.     }
  830. }
  831.  
  832. ///////////////////////////////////////////////////////////////////////////
  833. // main()
  834. ///////////////////////////////////////////////////////////////////////////
  835.  
  836. int main()
  837. {
  838.     // Create a game
  839.     // Use this instead to create a mini-game:   Game g(3, 5, 2);
  840.     Game g(10, 12, 40);
  841.  
  842.     // Play the game
  843.     g.play();
  844. }
  845.  
  846. ///////////////////////////////////////////////////////////////////////////
  847. //  clearScreen implementation
  848. ///////////////////////////////////////////////////////////////////////////
  849.  
  850. // DO NOT MODIFY OR REMOVE ANYTHING BETWEEN HERE AND THE END OF THE FILE!!!
  851. // THE CODE IS SUITABLE FOR VISUAL C++, XCODE, AND g++/g31 UNDER LINUX.
  852.  
  853. // Note to Xcode users:  clearScreen() will just write a newline instead
  854. // of clearing the window if you launch your program from within Xcode.
  855. // That's acceptable.  (The Xcode output window doesn't have the capability
  856. // of being cleared.)
  857.  
  858. #ifdef _WIN32
  859.  
  860. #include <windows.h>
  861.  
  862. void clearScreen()
  863. {
  864.     HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
  865.     CONSOLE_SCREEN_BUFFER_INFO csbi;
  866.     GetConsoleScreenBufferInfo(hConsole, &csbi);
  867.     DWORD dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
  868.     COORD upperLeft = { 0, 0 };
  869.     DWORD dwCharsWritten;
  870.     FillConsoleOutputCharacter(hConsole, TCHAR(' '), dwConSize, upperLeft,
  871.         &dwCharsWritten);
  872.     SetConsoleCursorPosition(hConsole, upperLeft);
  873. }
  874.  
  875. #else  // not _WIN32
  876.  
  877. #include <iostream>
  878. #include <cstring>
  879. #include <cstdlib>
  880. using namespace std;
  881.  
  882. void clearScreen()  // will just write a newline in an Xcode output window
  883. {
  884.     static const char* term = getenv("TERM");
  885.     if (term == nullptr || strcmp(term, "dumb") == 0)
  886.         cout << endl;
  887.     else
  888.     {
  889.         static const char* ESC_SEQ = "\x1B[";  // ANSI Terminal esc seq:  ESC [
  890.         cout << ESC_SEQ << "2J" << ESC_SEQ << "H" << flush;
  891.     }
  892. }
  893.  
  894. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement