0

好的,这是独家新闻:我正在为我的 c++ 类构建一个扫雷风格的程序,我正在使用 2D 数组来创建板,并使用第二个 2d 数组来存储猜测。对于 board 数组中的每个值,我运行一个随机数 gen 并为其分配一个介于 0 和 99 之间的值。如果数组中的每个值大于 85,则将其视为炸弹。程序接受用户输入并确定它是否是炸弹。如果不是对应的bool数组(isGuessed)位置则改为true。然后将此 bool 数组发送到 reDraw 函数以进行重绘。所有虚假布尔值都显示为“?” 并且所有 true 都显示为“X”。但是,当我重新绘制时,它会将数组中的多个位置更改为 X,只需要一次猜测。我的想法是,板的绘制与阵列位置无关。有人可以帮忙吗。为了清楚起见,我试图理解为什么函数 reDraw 不能正常工作。这是我的所有代码。

#include <iostream>
#include <ctime>
#include <cstdlib>

using namespace std;

//Function Prototypes 

void reDraw (bool guessed [] [10], int rows, int columns);
void newBoard (int rows, int columns);


int main(int argc, const char * argv[])
{
 //Declare Variables
  const int ROWS = 10;
  const int COLUMNS = 10;
int board [ROWS][COLUMNS];
bool wasGuessed [10] [10];
bool playAgain = true;
char newGame; 
int rowGuess, columnGuess, numOfBombs = 0, score = 0; 
bool bomb = false;
srand((unsigned) time(0));


// Welcome User, Give Direction

cout<<"\n\n\t\tWelcome To Matt's Minesweeper\n\n";

while (playAgain) {



 //function to randomly populate array elements
    for (int row = 0; row < ROWS; row++) {
        for (int column = 0; column < COLUMNS; column++) {
            board [row] [column] = rand() % 100; 
            if (board [row] [column] >= 85) {  //counter for bombs
                numOfBombs++;
        }
    }
}

// Create a new Display Board
newBoard(10, 10);

//Begin Game
cout<<"\nTotal Bombs In This Game: "<<numOfBombs;


// Process Guesses
do {
    cout<<"\nPlease Input your ROW & COLUMN Guess coordinate (i.e. 3 2): ";
    cin>>rowGuess>>columnGuess;

    if (board [rowGuess] [columnGuess] >= 85) {
        bomb = true;
        cout<<"\n\n\t\tXXXXXX BOMB HIT XXXXXXX\n\t\t\tGame Over.\n\n";
        cout<<"Your Score Score: "<<score;
        cout<<"\n\n Play Again (y/n):";
        cin>>newGame;
        switch (newGame) {
            case 'y':
                cout<<"\n\n";
                playAgain = true;
                break;
            default:
                playAgain = false;
                break;

        }
    } else {
        wasGuessed [rowGuess] [columnGuess] = true;
        score++; 
        reDraw(wasGuessed, 10, 10);
    }
} while (!bomb);

}


return 0;
}

   void reDraw (bool guessed [] [10], int rows, int columns)
{
    // Format row and column headers
    cout<<"  0   1   2   3   4   5   6   7   8  9\n";
    cout<<"0";
for (int i = 0; i < rows; i++) {
    for (int j = 0; j < columns; j++) {

        if ((j+1) % 10 == 0) 
            if ((i+1) == 10) {
                if (guessed [i] [j]) 
                    cout<<"X "<<" \n";
                else 
                    cout<<"? "<<" \n";
            }else{
                if (guessed [i] [j]) 
                    cout<<"X "<<" \n"<<i+1;
                else                
                    cout<<"? "<<" \n"<<i+1;
            }
        if ((j+1) % 10 != 0)
            if (guessed [j] [i]) 
                cout<<" X"<<"  ";
            else
                cout<<" ?"<<"  "; 

    }
}

}
void newBoard (int rows, int columns)
{

cout<<"  0   1   2   3   4   5   6   7   8  9\n";
cout<<"0";
for (int i = 0; i < rows; i++) {
    for (int j = 0; j < columns; j++) {

        if ((j+1) % 10 == 0) 
            if ((i+1) == 10) {
                cout<<"? "<<" \n";
            }else
                cout<<"? "<<" \n"<<i+1;
        if ((j+1) % 10 != 0)
            cout<<" ?"<<"  ";
    }

}


}

感谢您的帮助!

4

2 回答 2

3

好的,它已修复。查看新代码:

更改 - 之后添加reset()并移至wasGuessed [rowGuess] [columnGuess] = true; 顶部cin<<

它的作用就像一个魅力,将 ' 画X?' 曾经站在猜测之前的位置。

#include <iostream>
#include <ctime>
#include <cstdlib>

using namespace std;


//Declare Variables
const int ROWS = 10;
const int COLUMNS = 10;
int board [ROWS][COLUMNS];
bool wasGuessed [ROWS] [COLUMNS];
bool playAgain = true;
char newGame; 
int rowGuess, columnGuess, numOfBombs = 0, score = 0; 
bool bomb = false;


//Function Prototypes 

void reDraw (bool guessed [] [10], int rows, int columns);
void newBoard (int rows, int columns);
void reset();

int main(int argc, const char * argv[])
{

srand((unsigned) time(0));

reset();

// Welcome User, Give Direction

cout<<"\n\n\t\tWelcome To Matt's Minesweeper\n\n";

while (playAgain) {



 //function to randomly populate array elements
    for (int row = 0; row < ROWS; row++) {
        for (int column = 0; column < COLUMNS; column++) {
            board [row] [column] = (rand() % 100) + 0; 
            if (board [row] [column] >= 85) {  //counter for bombs
                numOfBombs++;
        }
    }
}

// Create a new Display Board
newBoard(10, 10);

//Begin Game
cout<<"\nTotal Bombs In This Game: "<<numOfBombs;


// Process Guesses
do {
    cout<<"\nPlease Input your ROW & COLUMN Guess coordinate (i.e. 3 2): ";
    cin>>rowGuess>>columnGuess;
    wasGuessed [rowGuess] [columnGuess] = true;
    if (board [rowGuess] [columnGuess] >= 85) {
        bomb = true;
        cout<<"\n\n\t\tXXXXXX BOMB HIT XXXXXXX\n\t\t\tGame Over.\n\n";
        cout<<"Your Score Score: "<<score;
        cout<<"\n\n Play Again (y/n):";
        cin>>newGame;
        switch (newGame) {
            case 'y':
                cout<<"\n\n";
                playAgain = true;
                reset();
                break;
            default:
                playAgain = false;
                break;

        }
    } else {
        wasGuessed [rowGuess] [columnGuess] = true;
        score++; 
        reDraw(wasGuessed, 10, 10);
    }
} while (!bomb);

}


return 0;
}

   void reDraw (bool guessed [] [10], int rows, int columns)
{
    // Format row and column headers
    cout<<"  0   1   2   3   4   5   6   7   8  9\n";
    cout<<"0";
for (int i = 0; i < rows; i++) {
    for (int j = 0; j < columns; j++) {

        if ((j+1) % 10 == 0) 
            if ((i+1) == 10) {
                if (guessed [i] [j]) 
                    cout<<"X "<<" \n";
                else 
                    cout<<"? "<<" \n";
            }else{
                if (guessed [i] [j]) 
                    cout<<"X "<<" \n"<<i+1;
                else                
                    cout<<"? "<<" \n"<<i+1;
            }
        if ((j+1) % 10 != 0)
            if (guessed [j] [i]) 
                cout<<" X"<<"  ";
            else
                cout<<" ?"<<"  "; 

    }
}

}
void newBoard (int rows, int columns)
{

cout<<"  0   1   2   3   4   5   6   7   8  9\n";
cout<<"0";
for (int i = 0; i < rows; i++) {
    for (int j = 0; j < columns; j++) {

        if ((j+1) % 10 == 0) 
            if ((i+1) == 10) {
                cout<<"? "<<" \n";
            }else
                cout<<"? "<<" \n"<<i+1;
        if ((j+1) % 10 != 0)
            cout<<" ?"<<"  ";
    }

}


}

void reset()
{
    for (int row = 0; row < ROWS; row++) 
    {
            for (int column = 0; column < COLUMNS; column++) 
            {
                wasGuessed [row] [column] = false;

            }
        }
}
于 2012-09-13T20:40:01.277 回答
1

我很无聊,所以我把你的程序做得更好。这一切都在一个文件中,但将其拆分为多个文件会很容易。只需将每个类的成员和类定义分开,并将它们放在自己的文件中,然后将 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 任何东西
  • 遗产
  • 缩进一致(看缩进不一致的代码不好玩)
于 2012-09-13T22:49:05.583 回答