我很无聊,所以我把你的程序做得更好。这一切都在一个文件中,但将其拆分为多个文件会很容易。只需将每个类的成员和类定义分开,并将它们放在自己的文件中,然后将 main 放在自己的文件中。
我做了一些可能会让你觉得很奇怪的事情。如果您看到某些内容,请在评论中询问,我会自己解释
// include all of the things
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <iomanip>
#include <string>
// use all of the things
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 << "Total Bombs In This Game: " << GetMineCount() << endl;
while (true)
{
string dummy;
int inputrow = -1, inputcol = -1;
cout << "Please Input Your ROW & COLUMN Guess Coordinate (i.e. 3 2): ";
cin >> inputrow >> inputcol;
if (!cin || IsUncovered(inputrow, inputcol) || !IsOnBoard(inputrow, inputcol))
{
cout << "Invalid Selection! ";
if (!cin)
{
cin.clear();
cin >> dummy;
}
continue;
}
int uncovered = UncoverSpace(inputrow, inputcol);
PrintBoard();
if (IsMine(inputrow, inputcol))
{
cout << endl << endl << "\t\tXXXXXX BOMB HIT XXXXXX" << endl << "\t\t\tGame Over." << endl << endl;
break;
}
else
{
score += uncovered;
cleared += uncovered;
if (WonGame())
{
cout << endl << endl << "\t\t------ ALL BOMBS CLEARED ------" << endl << "\t\t\tYou Win!" << endl << endl;
break;
}
}
}
cout << "your Score: " << score << endl;
}
bool MineSweeper::WonGame()
{
return (cleared == GetSafeCount());
}
// main.cpp
int main(int argc, char * argv[])
{
MineSweepBoard::Randomize();
cout << endl << endl << "\t\tWelcome To Wug's Minesweeper" << endl << endl;
while(true)
{
char again = 'n';
MineSweeper m;
m.Play();
cout << endl << "Play Again? (y/n) ";
cin >> again;
if (again == 'y')
{
cout << endl << endl;
continue;
}
else break;
}
return 0;
}
此代码具有原始版本所没有的以下特征:
- 你可以赢得比赛
- 和windows扫雷一样,在空旷的空间中间挑一块可以清理整个空间
- 输入验证
- 内存管理(你的只是在堆栈上使用了内存,它不需要 new 和 delete 任何东西
- 遗产
- 缩进一致(看缩进不一致的代码不好玩)