Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "SweeperBoard.h"
- #include <iostream>
- #include <vector>
- #include <string>
- #include <cstdlib>
- using namespace std;
- BoardSquare::BoardSquare() :
- isVisible(false), isFlagged(false), isMine(false), numMinesAround(0)
- {
- //Default initialisers for a board square - no function body needed.
- }
- SweeperBoard::SweeperBoard(int width_x, int height_y, int minePercent) :
- gameLost(false), gameWon(false), boardSize_x(width_x), boardSize_y(height_y)
- {
- // Create a temporary 'child' vector of dimension Y
- SubBoardType tempVector(width_x);
- // and assign it to a parent of dimension X
- boardVector = new BoardType(height_y, tempVector);
- // Compute the number of mines from the percentage given
- numMines = static_cast<int>(
- ( static_cast<float>( minePercent ) / 100 ) * static_cast<float>( width_x * height_y ) );
- cout << "Placing " << numMines << " mines..." << endl;
- // Place the mines
- for(int numberMines = numMines; numberMines != 0; --numberMines) {
- // Makes sure that a mine is created
- while( !CreateMine(rand() % height_y, rand() % width_x) );
- }
- }
- BoardSquare& SweeperBoard::SquareAt(int x, int y)
- {
- //Macro function, inline. Simplifies a couple of calculations...
- //Instead of '(*boardVector)[x][y]', you call 'SquareAt(x, y)'
- return (*boardVector)[x][y];
- }
- void SweeperBoard::CheckVictoryCondition()
- {
- visSpace = 0;
- for( BoardType_iter iter = (*boardVector).begin(); iter != (*boardVector).end(); ++iter)
- for( SubBoardType_iter iter2 = iter->begin(); iter2 != iter->end(); ++iter2 )
- if(iter2->isVisible)
- ++visSpace; //Count all the visible space
- //I would have used <algorithm>, but it's double nested; too complex.
- if((visSpace+numMines) == (boardSize_x*boardSize_y)) { //victory condition..
- //If the visible space plus mines equals the total size, you have won.
- gameWon = true;
- }
- }
- void SweeperBoard::PrintBoard()
- {
- // The characters used, and their codes:
- const char
- HORIZONTAL_LINE = -60,
- VERTICAL_LINE = -77, //All the characters used here are windows standard
- TOPLEFT_CORNER = -38, //Recompiling on mac+linux, you'd have to change 'em to work
- TOPRIGHT_CORNER = -65, //These are also used in the 'Help' code - but aren't constants
- BOTTOMLEFT_CORNER = -64,
- BOTTOMRIGHT_CORNER = -39,
- FLAG = 16,
- EMPTY = -6,
- MINE = 15,
- UNKNOWN = -80;
- // Iterate through the board vector - a character is also incremented for the position borders
- // The random 'cout's are just for formatting mostly; the victory condition is computed here as well
- char ch = 65;
- cout << TOPLEFT_CORNER << string(boardSize_x, HORIZONTAL_LINE)
- << TOPRIGHT_CORNER << endl; //top of box
- for( BoardType_iter iter = (*boardVector).begin(); iter != (*boardVector).end(); ++iter, ++ch ) {
- cout << VERTICAL_LINE; // Left side of board
- for( SubBoardType_iter iter2 = iter->begin(); iter2 != iter->end(); ++iter2 ) {
- // Output all the squares + their codes
- if(iter2->isFlagged) {
- cout << FLAG;
- } else if(iter2->isVisible || gameLost || gameWon) { // only print the stuff that's visible, unless it's endgame
- if(iter2->isMine) {
- cout << MINE;
- } else {
- if(iter2->numMinesAround == 0)
- cout << EMPTY;
- else
- cout << iter2->numMinesAround;
- }
- } else {
- cout << UNKNOWN;
- }
- }
- cout << VERTICAL_LINE << ch << endl; // Right side and coordinate
- }
- cout << BOTTOMLEFT_CORNER << string(boardSize_x, HORIZONTAL_LINE)
- << BOTTOMRIGHT_CORNER << endl << " "; // bottom of box
- for(int i = 0; i != boardSize_x; ++i) cout << static_cast<char>(i+65); // bottom coordinates
- CheckVictoryCondition();
- cout << endl;
- }
- bool SweeperBoard::IsValidPosition(int x, int y)
- {
- // Checks the position actually exists
- if(x < boardSize_y && y < boardSize_x
- && x >=0 && y >= 0 ) {
- return true;
- }
- return false;
- }
- void SweeperBoard::IncrementPosition(int x, int y)
- {
- // If the position is valid, increment the 'number of mines around' value
- if(IsValidPosition(x, y))
- ++(SquareAt(x, y).numMinesAround);
- }
- bool SweeperBoard::Pop(int x, int y)
- {
- //returns true if the pop succeeded - checks to make sure it isn't flagged
- if(IsValidPosition(x, y) && !SquareAt(x, y).isFlagged) {
- LeakPositions(x, y);
- return true;
- }
- return false;
- }
- bool SweeperBoard::Flag(int x, int y)
- {
- //returns true if the flag succeeded
- if(IsValidPosition(x, y)) {
- SquareAt(x, y).isFlagged = true;
- return true;
- }
- return false;
- }
- bool SweeperBoard::Unflag(int x, int y)
- {
- //returns true if the unflag succeeded - checks whether there is actually a flag there to unflag
- if(IsValidPosition(x, y) && SquareAt(x, y).isFlagged) {
- SquareAt(x, y).isFlagged = false;
- return true;
- }
- return false;
- }
- bool SweeperBoard::CreateMine(int x, int y)
- {
- // If there's already a mine there we can't put another in that spot
- if( SquareAt(x, y).isMine )
- return false;
- // otherwise, make it a mine
- SquareAt(x, y).isMine = true;
- // Increment all the squares around
- IncrementPosition(x+1, y);
- IncrementPosition(x-1, y);
- IncrementPosition(x, y+1);
- IncrementPosition(x, y-1);
- IncrementPosition(x+1, y+1);
- IncrementPosition(x+1, y-1);
- IncrementPosition(x-1, y-1);
- IncrementPosition(x-1, y+1);
- return true;
- }
- void SweeperBoard::ValidateFill(int x, int y)
- {
- if(IsValidPosition(x, y)) {
- //create a synonym for the current square
- BoardSquare &me = SquareAt(x, y);
- if(me.numMinesAround == 0 && !me.isVisible) // If it's a zero square, recurse.
- LeakPositions(x, y);
- else if(!me.isMine && !me.isVisible) //Otherwise it's an ordinary number square (not a mine) - make it visible.
- me.isVisible = true;
- }
- }
- void SweeperBoard::LeakPositions(int x, int y)
- {
- //This function is semi-recursive, works alongside the 'ValidateFill' function
- // create a synonym for the current square
- BoardSquare &me = SquareAt(x, y);
- // If the user popped a mine
- if( me.isMine ) {
- gameLost = true; //lose the game
- return;
- }
- // make the current square visible
- me.isVisible = true;
- // if it's a zero square, fill in the others as well.
- if(me.numMinesAround == 0) {
- ValidateFill(x+1, y);
- ValidateFill(x-1, y);
- ValidateFill(x, y+1);
- ValidateFill(x, y-1);
- ValidateFill(x+1, y+1);
- ValidateFill(x+1, y-1);
- ValidateFill(x-1, y-1);
- ValidateFill(x-1, y+1);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement