Advertisement
Guest User

SweeperBoard.cpp

a guest
Jul 2nd, 2011
480
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.34 KB | None | 0 0
  1. #include "SweeperBoard.h"
  2. #include <iostream>
  3. #include <vector>
  4. #include <string>
  5. #include <cstdlib>
  6.  
  7. using namespace std;
  8.  
  9. BoardSquare::BoardSquare() :
  10.     isVisible(false), isFlagged(false), isMine(false), numMinesAround(0)
  11. {
  12.     //Default initialisers for a board square - no function body needed.
  13. }
  14.  
  15. SweeperBoard::SweeperBoard(int width_x, int height_y, int minePercent) :
  16.     gameLost(false), gameWon(false), boardSize_x(width_x), boardSize_y(height_y)
  17. {
  18.     // Create a temporary 'child' vector of dimension Y
  19.     SubBoardType tempVector(width_x);
  20.  
  21.     // and assign it to a parent of dimension X
  22.     boardVector = new BoardType(height_y, tempVector);
  23.  
  24.     // Compute the number of mines from the percentage given
  25.     numMines = static_cast<int>(
  26.         ( static_cast<float>( minePercent ) / 100 ) * static_cast<float>( width_x * height_y ) );
  27.  
  28.     cout << "Placing " << numMines << " mines..." << endl;
  29.  
  30.  
  31.     // Place the mines
  32.     for(int numberMines = numMines; numberMines != 0; --numberMines) {
  33.         // Makes sure that a mine is created
  34.         while( !CreateMine(rand() % height_y, rand() % width_x) );
  35.     }
  36.  
  37. }
  38.  
  39. BoardSquare& SweeperBoard::SquareAt(int x, int y)
  40. {
  41.     //Macro function, inline. Simplifies a couple of calculations...
  42.     //Instead of '(*boardVector)[x][y]', you call 'SquareAt(x, y)'
  43.     return (*boardVector)[x][y];
  44. }
  45.  
  46. void SweeperBoard::CheckVictoryCondition()
  47. {
  48.     visSpace = 0;
  49.    
  50.     for( BoardType_iter iter = (*boardVector).begin(); iter != (*boardVector).end(); ++iter)
  51.         for( SubBoardType_iter iter2 = iter->begin(); iter2 != iter->end(); ++iter2 )
  52.             if(iter2->isVisible)
  53.                 ++visSpace; //Count all the visible space
  54.                             //I would have used <algorithm>, but it's double nested; too complex.
  55.  
  56.     if((visSpace+numMines) == (boardSize_x*boardSize_y)) { //victory condition..
  57.         //If the visible space plus mines equals the total size, you have won.
  58.         gameWon = true;
  59.     }
  60. }
  61.  
  62. void SweeperBoard::PrintBoard()
  63. {
  64.     // The characters used, and their codes:
  65.     const char
  66.         HORIZONTAL_LINE = -60,
  67.         VERTICAL_LINE = -77,    //All the characters used here are windows standard
  68.         TOPLEFT_CORNER = -38,   //Recompiling on mac+linux, you'd have to change 'em to work
  69.         TOPRIGHT_CORNER = -65,  //These are also used in the 'Help' code - but aren't constants
  70.         BOTTOMLEFT_CORNER = -64,
  71.         BOTTOMRIGHT_CORNER = -39,
  72.         FLAG = 16,
  73.         EMPTY = -6,
  74.         MINE = 15,
  75.         UNKNOWN = -80;
  76.  
  77.     // Iterate through the board vector - a character is also incremented for the position borders
  78.     // The random 'cout's are just for formatting mostly; the victory condition is computed here as well
  79.     char ch = 65;
  80.  
  81.     cout << TOPLEFT_CORNER << string(boardSize_x, HORIZONTAL_LINE)
  82.         << TOPRIGHT_CORNER << endl; //top of box
  83.  
  84.     for( BoardType_iter iter = (*boardVector).begin(); iter != (*boardVector).end(); ++iter, ++ch ) {
  85.  
  86.         cout << VERTICAL_LINE; // Left side of board
  87.  
  88.         for( SubBoardType_iter iter2 = iter->begin(); iter2 != iter->end(); ++iter2 ) {
  89.  
  90.             // Output all the squares + their codes
  91.             if(iter2->isFlagged) {
  92.                 cout << FLAG;
  93.             } else if(iter2->isVisible || gameLost || gameWon) { // only print the stuff that's visible, unless it's endgame
  94.                 if(iter2->isMine) {
  95.                     cout << MINE;
  96.                 } else {
  97.                     if(iter2->numMinesAround == 0)
  98.                         cout << EMPTY;
  99.                     else
  100.                         cout << iter2->numMinesAround;
  101.                 }
  102.             } else {
  103.                 cout << UNKNOWN;
  104.             }
  105.  
  106.         }
  107.  
  108.         cout << VERTICAL_LINE << ch << endl; // Right side and coordinate
  109.     }
  110.     cout << BOTTOMLEFT_CORNER << string(boardSize_x, HORIZONTAL_LINE)
  111.         << BOTTOMRIGHT_CORNER << endl << " "; // bottom of box
  112.  
  113.     for(int i =  0; i != boardSize_x; ++i) cout << static_cast<char>(i+65); // bottom coordinates
  114.  
  115.     CheckVictoryCondition();
  116.  
  117.     cout << endl;
  118. }
  119.  
  120. bool SweeperBoard::IsValidPosition(int x, int y)
  121. {
  122.     // Checks the position actually exists
  123.     if(x < boardSize_y && y < boardSize_x
  124.         && x >=0 && y >= 0 ) {
  125.             return true;
  126.     }
  127.     return false;
  128. }
  129.  
  130. void SweeperBoard::IncrementPosition(int x, int y)
  131. {
  132.     // If the position is valid, increment the 'number of mines around' value
  133.     if(IsValidPosition(x, y))
  134.         ++(SquareAt(x, y).numMinesAround);
  135. }
  136.  
  137. bool SweeperBoard::Pop(int x, int y)
  138. {
  139.     //returns true if the pop succeeded - checks to make sure it isn't flagged
  140.     if(IsValidPosition(x, y) && !SquareAt(x, y).isFlagged) {
  141.         LeakPositions(x, y);
  142.         return true;
  143.     }
  144.     return false;
  145. }
  146.  
  147. bool SweeperBoard::Flag(int x, int y)
  148. {
  149.     //returns true if the flag succeeded
  150.     if(IsValidPosition(x, y)) {
  151.         SquareAt(x, y).isFlagged = true;
  152.         return true;
  153.     }
  154.     return false;
  155. }
  156.  
  157. bool SweeperBoard::Unflag(int x, int y)
  158. {
  159.     //returns true if the unflag succeeded - checks whether there is actually a flag there to unflag
  160.     if(IsValidPosition(x, y) && SquareAt(x, y).isFlagged) {
  161.         SquareAt(x, y).isFlagged = false;
  162.         return true;
  163.     }
  164.     return false;
  165. }
  166.  
  167. bool SweeperBoard::CreateMine(int x, int y)
  168. {
  169.     // If there's already a mine there we can't put another in that spot
  170.     if( SquareAt(x, y).isMine )
  171.         return false;
  172.  
  173.     // otherwise, make it a mine
  174.     SquareAt(x, y).isMine = true;
  175.  
  176.     // Increment all the squares around
  177.     IncrementPosition(x+1, y);
  178.     IncrementPosition(x-1, y);
  179.     IncrementPosition(x, y+1);
  180.     IncrementPosition(x, y-1);
  181.     IncrementPosition(x+1, y+1);
  182.     IncrementPosition(x+1, y-1);
  183.     IncrementPosition(x-1, y-1);
  184.     IncrementPosition(x-1, y+1);
  185.  
  186.     return true;
  187. }
  188.  
  189. void SweeperBoard::ValidateFill(int x, int y)
  190. {
  191.     if(IsValidPosition(x, y)) {
  192.         //create a synonym for the current square
  193.         BoardSquare &me = SquareAt(x, y);
  194.  
  195.         if(me.numMinesAround == 0 && !me.isVisible) // If it's a zero square, recurse.
  196.             LeakPositions(x, y);
  197.         else if(!me.isMine && !me.isVisible) //Otherwise it's an ordinary number square (not a mine) - make it visible.
  198.             me.isVisible = true;
  199.     }
  200. }
  201.  
  202. void SweeperBoard::LeakPositions(int x, int y)
  203. {
  204.     //This function is semi-recursive, works alongside the 'ValidateFill' function
  205.  
  206.     // create a synonym for the current square
  207.     BoardSquare &me = SquareAt(x, y);
  208.     // If the user popped a mine
  209.     if( me.isMine ) {
  210.         gameLost = true; //lose the game
  211.         return;
  212.     }
  213.     // make the current square visible
  214.     me.isVisible = true;
  215.     // if it's a zero square, fill in the others as well.
  216.     if(me.numMinesAround == 0) {
  217.         ValidateFill(x+1, y);
  218.         ValidateFill(x-1, y);
  219.         ValidateFill(x, y+1);
  220.         ValidateFill(x, y-1);
  221.         ValidateFill(x+1, y+1);
  222.         ValidateFill(x+1, y-1);
  223.         ValidateFill(x-1, y-1);
  224.         ValidateFill(x-1, y+1);
  225.     }
  226. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement