#include #include #include #include #include using std::rand; using std::srand; using std::time; using std::cout; using std::cin; using std::endl; using std::right; using std::left; using std::setw; using std::string; // MineSweepBoard.h class MineSweepBoard { public: MineSweepBoard(int rows, int cols, float per); MineSweepBoard(int rows, int cols); MineSweepBoard(); virtual ~MineSweepBoard(); static const int ROW_DEFAULT, COL_DEFAULT; static const float CHANCE_DEFAULT; static const unsigned char MINE_MASK, UNCOVERED_MASK; static void Randomize(); void RandomizeBoard(); bool IsMine(int r, int c); bool IsUncovered(int r, int c); int UncoverSpace(int r, int c); int GetAdjMineCount(int r, int c); bool IsOnBoard(int r, int c); char GetBoardSquare(int r, int c); int GetRows(); int GetCols(); float GetPercentage(); int GetMineCount(); int GetSafeCount(); private: int rowcount, colcount; int minecount, safecount; float percentage; char * board; bool safedummy; void Init(int rows, int cols, float per); }; // MineSweeper.h class MineSweeper : public MineSweepBoard { public: MineSweeper(); MineSweeper(int rows, int cols, float difficulty); MineSweeper(int rows, int cols, float difficulty, char mchar, char bchar, char uchar); static const char MINE_DEFAULT, BLANK_DEFAULT, UNKNOWN_DEFAULT; void PrintBoard(); char GetCharForSpace(int r, int c); void Play(); bool WonGame(); private: char minechar, blankchar, unknownchar; int cleared; void Init(char mchar, char bchar, char uchar); }; // MineSweepBoard.cpp const int MineSweepBoard::ROW_DEFAULT = 10, MineSweepBoard::COL_DEFAULT = 10; const float MineSweepBoard::CHANCE_DEFAULT = 0.85; const unsigned char MineSweepBoard::MINE_MASK = 0x1, MineSweepBoard::UNCOVERED_MASK = 0x2; void MineSweepBoard::Randomize() { srand(time(NULL)); } int MineSweepBoard::GetRows() { return rowcount; } int MineSweepBoard::GetCols() { return colcount; } float MineSweepBoard::GetPercentage() { return percentage; } int MineSweepBoard::GetMineCount() { return minecount; } int MineSweepBoard::GetSafeCount() { return safecount; } MineSweepBoard::MineSweepBoard() { Init(ROW_DEFAULT, COL_DEFAULT, CHANCE_DEFAULT); } MineSweepBoard::MineSweepBoard(int rows, int cols) { Init(rows, cols, CHANCE_DEFAULT); } MineSweepBoard::MineSweepBoard(int rows, int cols, float per) { Init(rows, cols, per); } MineSweepBoard::~MineSweepBoard() { delete[] board; } void MineSweepBoard::Init(int rows, int cols, float per) { minecount = 0; safecount = rows * cols; percentage = per; rowcount = rows; colcount = cols; board = new char [rows * cols]; RandomizeBoard(); } char MineSweepBoard::GetBoardSquare(int r, int c) { return board[r * colcount + c]; } void MineSweepBoard::RandomizeBoard() { for (int i = 0, j = rowcount * colcount; i != j; ++i) { float r = (((float) rand()) / ((float) RAND_MAX)); board[i] = (percentage < r); if (board[i]) ++minecount; } safecount -= minecount; } bool MineSweepBoard::IsOnBoard(int r, int c) { return ( (r >= 0 && r < rowcount) && (c >= 0 && c < colcount) ); } bool MineSweepBoard::IsMine(int r, int c) { return ( (IsOnBoard(r, c)) && (GetBoardSquare(r, c) & MINE_MASK) ); } bool MineSweepBoard::IsUncovered(int r, int c) { return ( (IsOnBoard(r, c)) && (GetBoardSquare(r, c) & UNCOVERED_MASK) ); } int MineSweepBoard::UncoverSpace(int r, int c) { int uncovered = 0; while (IsOnBoard(r, c) && !IsUncovered(r, c)) { board[r * colcount + c] |= UNCOVERED_MASK; if (!(GetBoardSquare(r, c) & MINE_MASK)) ++uncovered; else break; if (GetAdjMineCount(r, c) == 0) { uncovered += UncoverSpace(r + 0, c + 1); uncovered += UncoverSpace(r + 0, c - 1); uncovered += UncoverSpace(r + 1, c + 0); uncovered += UncoverSpace(r - 1, c + 0); } break; } return uncovered; } int MineSweepBoard::GetAdjMineCount(int r, int c) { return IsMine(r + 0, c + 1) + IsMine(r + 0, c - 1) + IsMine(r + 1, c + 0) + IsMine(r - 1, c + 0) + IsMine(r + 1, c + 1) + IsMine(r - 1, c - 1) + IsMine(r + 1, c - 1) + IsMine(r - 1, c + 1); } // MineSweeper.cpp const char MineSweeper::MINE_DEFAULT = 'X', MineSweeper::BLANK_DEFAULT = ' ', MineSweeper::UNKNOWN_DEFAULT = '?'; MineSweeper::MineSweeper() : MineSweepBoard() { Init(MINE_DEFAULT, BLANK_DEFAULT, UNKNOWN_DEFAULT); } MineSweeper::MineSweeper(int rows, int cols, float difficulty) : MineSweepBoard(rows, cols, difficulty) { Init(MINE_DEFAULT, BLANK_DEFAULT, UNKNOWN_DEFAULT); } MineSweeper::MineSweeper(int rows, int cols, float difficulty, char mchar, char bchar, char uchar) : MineSweepBoard(rows, cols, difficulty) { Init(mchar, bchar, uchar); } void MineSweeper::Init(char mchar, char bchar, char uchar) { minechar = mchar; blankchar = bchar; unknownchar = uchar; } void MineSweeper::PrintBoard() { for (int i = 0; i < GetCols(); ++i) cout << setw(4) << right << i; cout << left << endl << endl; for (int r = 0; r < GetCols(); ++r) { cout << setw(3) << r; for (int c = 0; c < GetRows(); ++c) { cout << setw(4) << GetCharForSpace(r, c); } cout << endl; } } char MineSweeper::GetCharForSpace(int r, int c) { if (IsUncovered(r, c)) { if (IsMine(r, c)) return minechar; int count = GetAdjMineCount(r, c); if (count == 0) return blankchar; else return '0' + count; } else return unknownchar; } void MineSweeper::Play() { int score = 0; PrintBoard(); cout << "Laczna ilosc bomb: " << GetMineCount() << endl; while (true) { string dummy; int inputrow = -1, inputcol = -1; cout << "Podaj rzad i kolumne (np. 3 2): "; cin >> inputrow >> inputcol; if (!cin || IsUncovered(inputrow, inputcol) || !IsOnBoard(inputrow, inputcol)) { cout << "Bledny wybor! "; if (!cin) { cin.clear(); cin >> dummy; } continue; } int uncovered = UncoverSpace(inputrow, inputcol); PrintBoard(); if (IsMine(inputrow, inputcol)) { cout << endl << endl << "\t\tXXXXXX Trafiles na bombe XXXXXX" << endl << "\t\t\tPrzegrales." << endl << endl; break; } else { score += uncovered; cleared += uncovered; if (WonGame()) { cout << endl << endl << "\t\t------ Wszystkie bomby znalezione ------" << endl << "\t\t\tWygrales!" << endl << endl; break; } } } cout << "Twoj wynik: " << score << endl; } bool MineSweeper::WonGame() { return (cleared == GetSafeCount()); } // main.cpp int main(int argc, char * argv[]) { MineSweepBoard::Randomize(); cout << endl << endl << "\t\tWitamy w grze Saper" << endl << endl; while(true) { char again = 'n'; MineSweeper m; m.Play(); cout << endl << "Jescze raz? (y/n) "; cin >> again; if (again == 'y') { cout << endl << endl; continue; } else break; } return 0; }