0

所以这是我的问题。在下面的程序中,在函数“SetBoardStartingConfig”的底部,我尝试通过随机生成数字来填充数组的前 4 行,检查我试图将它们放置到的正方形是否为空(0) ,并且如果添加一块会使其超过数组“MaxPieces”中指定的最大值。如果它不会,理论上应该添加它 - 但它没有按我的预期工作,并给我带来有趣的价值。总的来说,我继续重复这个函数 10 次,但它似乎总是产生不同的错误 - 下面我也粘贴了一些结果。

注意:我已经注释掉了这两种算法来尝试这个,它们被一些空格隔开。

旁注:我第一次运行程序时似乎总是得到 FlagSide = 1 (右侧) - 关于如何解决这个问题的任何想法?

非常感谢大家的帮助:)。

#include <iostream>
#include <stdlib.h>
#include <string>

using namespace std;

int board[10][10];

int AIPieces[11];
int PlayerPieces[11];
int MaxPieces[11];
string PieceNames[11];

//insert stuff for maximum number of things

#define NullSpace -1  // Spaces that pieces can not move to
#define Flag -5
#define Bomb 1
#define EmptySpace 0 //Empty board spaces

void SetMaxPieces()
{
    MaxPieces[0] = 1;
    MaxPieces[Bomb] = 6;
    MaxPieces[2] = 8;
    MaxPieces[3] = 5;
    MaxPieces[4] = 4;
    MaxPieces[5] = 4;
    MaxPieces[6] = 4;
    MaxPieces[7] = 3;
    MaxPieces[8] = 2;
    MaxPieces[9] = 1;
    MaxPieces[10] = 1;
    MaxPieces[11] = 1; //Spy
}

void ResetAIPieces()
{
        for (int i = 0; i < 11; i++)
        AIPieces[i] = 0;
}

void SetPieceNames()
{
    PieceNames[0] = "Flags:";
    PieceNames[1] = "Bombs:";
    PieceNames[2] = "Twos:";
    PieceNames[3] = "Threes:";
    PieceNames[4] = "Fours:";
    PieceNames[5] = "Fives:";
    PieceNames[6] = "Sixes:";
    PieceNames[7] = "Sevens:";
    PieceNames[8] = "Eights:";
    PieceNames[9] = "Nines:";
    PieceNames[10] = "Tens:";
    PieceNames[11] = "Spies:";
}

void PrintBoard()
{   
    for (int i=0; i<10; i++)
    {
        for (int j=0; j<10; j++)
        {
            cout << board[i][j] << " ";
            if (board[i][j] >= 0)
            {
                cout << " ";
            }
        }
        cout << endl;
    }
}

void SetBoardStartingConfig()
{
    for (int i=0; i<10; i++)
    {
        for (int j=0; j<10; j++)
        {   
            board[i][j] = EmptySpace;
        }
    }
    //arrays work in [row] and [column].

    //below defines areas that the pieces can not move to.
    board[4][2] = NullSpace;
    board[4][3] = NullSpace;
    board[5][2] = NullSpace;
    board[5][3] = NullSpace;
    board[4][6] = NullSpace;
    board[4][7] = NullSpace;
    board[5][6] = NullSpace;
    board[5][7] = NullSpace;

    int FlagSide = rand() % 2;

    if (FlagSide == 0)
    {       
        board[0][0] = Flag;
        AIPieces[0]++;
        AIPieces[board[2][0] = Bomb]++;
        AIPieces[board[1][1] = Bomb]++;
        AIPieces[board[0][2] = Bomb]++;
        AIPieces[board[1][0] = rand() % 3 + 4]++;
        AIPieces[board[0][1] = rand() % 3 + 4]++;       
    }

    else if (FlagSide == 1)
    {
        board[0][9-0] = Flag;
        AIPieces[0]++;
        AIPieces[board[2][9-0] = Bomb]++;
        AIPieces[board[1][9-1] = Bomb]++;
        AIPieces[board[0][9-2] = Bomb]++;
        AIPieces[board[1][9-0] = rand() % 3 + 4]++;
        AIPieces[board[0][9-1] = rand() % 3 + 4]++; 
    }

    //for (int i =0; i < 4; i++)
    //      for (int j = 0; j < 10; j++)
    //      {
    //          if (board[i][j] == 0)
    //          {
    //              int Chosen = rand() % 10+1;
    //              if (AIPieces[Chosen] < MaxPieces[Chosen])
    //                  {
    //                  board[i][j] = Chosen;
    //                  AIPieces[Chosen]++;
    //              }
    //              else
    //                  break;
    //          }
    //          else
    //              break;


    //          //      if (AIPieces[0] < MaxPieces[0] || AIPieces[1] < MaxPieces[1] || AIPieces[2] < MaxPieces[2] || AIPieces[3] < MaxPieces[3] || AIPieces[4] < MaxPieces[4] || AIPieces[5] < MaxPieces[5] || AIPieces[5] < MaxPieces[5] || AIPieces[6] < MaxPieces[6] || AIPieces[7] < MaxPieces[7] || AIPieces[8] < MaxPieces[8] || AIPieces[9] < MaxPieces[9] || AIPieces[10] < MaxPieces[10] || AIPieces[11] < MaxPieces[11]) 
    //          //{
    //          //  AIPieces[board[i][j] = rand() % 10+1]++;        
    //          //}
    //      }
}

int main()
{
    SetMaxPieces();
    SetPieceNames();

    int loop = 0;

    do
    {
        SetBoardStartingConfig();
        PrintBoard();
        cout << endl; 

        for (int i = 0; i < 11; i++)
        {
                cout << PieceNames[i] << AIPieces[i] << endl;
        }
            cout << endl;

        ResetAIPieces();

        loop++;

    } while (loop <= 10);

    system("PAUSE");

}

我的结果(每次我使用第一个算法运行它时它们似乎都是一样的)

1  10  5  9  0  0  0  1  5  -5
3  5  6  6  2  8  2  2  1  6
6  3  8  7  2  5  3  4  3  1
3  2  7  0  0  0  0  0  0  0
0  0  -1 -1 0  0  -1 -1 0  0
0  0  -1 -1 0  0  -1 -1 0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0

Flags:1
Bombs:4
Twos:5
Threes:5
Fours:1
Fives:4
Sixes:4
Sevens:2
Eights:2
Nines:1
Tens:1

2  9  10  3  8  0  0  1  4  -5
6  5  4  2  3  4  4  5  1  6
2  2  0  0  0  0  0  0  0  1
0  0  0  0  0  0  0  0  0  0
0  0  -1 -1 0  0  -1 -1 0  0
0  0  -1 -1 0  0  -1 -1 0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0

Flags:1
Bombs:3
Twos:4
Threes:2
Fours:4
Fives:2
Sixes:2
Sevens:0
Eights:1
Nines:1
Tens:1

8  8  10  4  2  0  0  1  5  -5
9  7  6  1  3  0  0  0  1  6
7  1  3  5  0  0  0  0  0  1
7  6  1  0  0  0  0  0  0  0
0  0  -1 -1 0  0  -1 -1 0  0
0  0  -1 -1 0  0  -1 -1 0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0

Flags:1
Bombs:6
Twos:1
Threes:2
Fours:1
Fives:2
Sixes:3
Sevens:3
Eights:2
Nines:1
Tens:1

-5 4  1  0  0  0  0  0  0  0
6  1  0  0  0  0  0  0  0  0
1  0  0  0  0  0  0  0  0  0
2  4  9  10  4  5  5  7  1  7
0  0  -1 -1 0  0  -1 -1 0  0
0  0  -1 -1 0  0  -1 -1 0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0

Flags:1
Bombs:4
Twos:1
Threes:0
Fours:3
Fives:2
Sixes:1
Sevens:2
Eights:0
Nines:1
Tens:1

-5 5  1  0  0  0  0  0  0  0
6  1  0  0  0  0  0  0  0  0
1  0  0  0  0  0  0  0  0  0
5  10  7  4  8  9  0  0  0  0
0  0  -1 -1 0  0  -1 -1 0  0
0  0  -1 -1 0  0  -1 -1 0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0

Flags:1
Bombs:3
Twos:0
Threes:0
Fours:1
Fives:2
Sixes:1
Sevens:1
Eights:1
Nines:1
Tens:1

-5 6  1  0  0  0  0  0  0  0
4  1  0  0  0  0  0  0  0  0
1  0  0  0  0  0  0  0  0  0
4  6  10  9  5  1  8  7  4  7
0  0  -1 -1 0  0  -1 -1 0  0
0  0  -1 -1 0  0  -1 -1 0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0

Flags:1
Bombs:4
Twos:0
Threes:0
Fours:3
Fives:1
Sixes:2
Sevens:2
Eights:1
Nines:1
Tens:1

3  1  10  8  4  8  3  1  6  -5
7  1  2  7  6  0  0  0  1  6
6  5  2  3  1  0  0  0  0  1
2  5  7  0  0  0  0  0  0  0
0  0  -1 -1 0  0  -1 -1 0  0
0  0  -1 -1 0  0  -1 -1 0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0

Flags:1
Bombs:6
Twos:3
Threes:3
Fours:1
Fives:2
Sixes:4
Sevens:3
Eights:2
Nines:0
Tens:1

8  8  0  0  0  0  0  1  5  -5
4  4  6  10  0  0  0  0  1  6
9  2  0  0  0  0  0  0  0  1
3  7  7  1  4  0  0  0  0  0
0  0  -1 -1 0  0  -1 -1 0  0
0  0  -1 -1 0  0  -1 -1 0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0

Flags:1
Bombs:4
Twos:1
Threes:1
Fours:3
Fives:1
Sixes:2
Sevens:2
Eights:2
Nines:1
Tens:1

-5 4  1  0  0  0  0  0  0  0
6  1  0  0  0  0  0  0  0  0
1  0  0  0  0  0  0  0  0  0
6  1  10  5  8  9  4  6  2  3
0  0  -1 -1 0  0  -1 -1 0  0
0  0  -1 -1 0  0  -1 -1 0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0

Flags:1
Bombs:4
Twos:1
Threes:1
Fours:2
Fives:1
Sixes:3
Sevens:0
Eights:1
Nines:1
Tens:1

-5 6  1  0  0  0  0  0  0  0
5  1  0  0  0  0  0  0  0  0
1  0  0  0  0  0  0  0  0  0
5  1  7  2  9  10  0  0  0  0
0  0  -1 -1 0  0  -1 -1 0  0
0  0  -1 -1 0  0  -1 -1 0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0

Flags:1
Bombs:4
Twos:1
Threes:0
Fours:0
Fives:2
Sixes:1
Sevens:1
Eights:0
Nines:1
Tens:1

-5 4  1  0  0  0  0  0  0  0
5  1  0  0  0  0  0  0  0  0
1  0  0  0  0  0  0  0  0  0
4  10  9  0  0  0  0  0  0  0
0  0  -1 -1 0  0  -1 -1 0  0
0  0  -1 -1 0  0  -1 -1 0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0

Flags:1
Bombs:3
Twos:0
Threes:0
Fours:2
Fives:1
Sixes:0
Sevens:0
Eights:0
Nines:1
Tens:1

Press any key to continue . . .
4

2 回答 2

2

我不太清楚您期望发生什么或正在发生什么,您应该尝试解释您得到的错误的原因,这样人们就不必花费很长时间来分析代码和结果。第一个算法有效,第二个无效吗?还是两者都错了?无论如何,下面的更改将使程序更容易推理。

您的变量和函数命名有点不合常规。更常见的是变量和函数以小写字母开头,类以大写字母开头。您的程序看起来好像一切都很重要。

你为什么在这里使用宏?

#define NullSpace -1 // 碎片不能移动到的空间
#define 标志 -5
#define 炸弹 1
#define EmptySpace 0 //空板空间

一般来说,宏很糟糕,特别是如果您不命名它们以避免与其他名称发生冲突。C++ 的发明者建议对宏使用 ALL_CAPS。更好的是,不要使用它们:

常量 int NullSpace = -1; // 碎片不能移动到的空间
常量 int 标志 -5;
const int 炸弹 1;
常量 int EmptySpace 0; //空板空间

这是一种非常繁琐的设置数组的方法:

无效 SetMaxPieces()
{
    最大件数[0] = 1;
    MaxPieces[炸弹] = 6;
    最大件数[2] = 8;
...
    最大件数[10] = 1;
    最大件数[11] = 1;//间谍
}

定义数组时只需初始化它:

int MaxPieces[11] = {
    1, 6, 8, 5, 4, 4, 4, 3, 2, 1, 1, 1
};
字符串 PieceNames[11] = {
  “旗帜:”,“炸弹:​​”,“二:”,“三:”,“四:”,“五:”,“六:”,
  “七:”,“八:”,“九:”,“十:”,“间谍:”
};

可是等等!现在编译器拒绝编译程序:

game.cc:13:1:错误:“int [11]”的初始化程序太多
game.cc:17:1:错误:'std::string [11] {aka std::basic_string [11]}'的初始化程序太多

您正在设置 11 个数组中的 12 个值!当你这样做时编译器没有抱怨MaxPieces[11](但也许应该这样做),但它绝对不会让你初始化一个包含太多值的数组。你的数组应该有十二个元素吗?还是您只是填写错误?

正如评论者指出的那样,您必须播种rand()或伪随机数生成器始终以相同的初始状态开始,并产生完全相同的“随机”数序列。

你为什么使用do-whilein maindo-while仅在少数情况下有用,当条件最初无法测试时(或一些巧妙的技巧使其块范围充当邪恶宏中的单个语句)。在您的情况下,条件最初为真(loop小于 10),因此只需使用fororwhile循环。我更喜欢 afor因为你的循环变量不需要在之后存在for所以你可以在那里初始化它:

for (int loop = 0; loop <= 10; ++loop)
{
    SetBoardStartingConfig();
    PrintBoard();
    cout << '\n';

    for (int i = 0; i < 11; i++)
    {
            cout << PieceNames[i] << AIPieces[i] << '\n';
    }
    cout << '\n';

    ResetAIPieces();
}
cout << flush;

endl每次需要换行时都不需要使用,endl添加换行刷新流,这不需要在每一行上都执行。上面的代码在循环之后只执行一次。

现在对于第一个算法:

for (int i =0; i < 4; i++)
    for (int j = 0; j < 10; j++)
    {
        if (board[i][j] == 0)
        {
            int Chosen = rand() % 10+1;
            if (AIPieces[Chosen] < MaxPieces[Chosen])
                {
                board[i][j] = Chosen;
                AIPieces[Chosen]++;
            }
            else
                break;
        }
        else
            break;

将大括号中的第一个for括起来也有助于提高可读性。它也有助于编写rand()%10 + 1而不是上面的间距,以便运算符优先级更加明显,目前看起来你的意思是rand() % 11因为你已经对加法操作数进行了分组。

不应该是支票board[i][j] == 0board[i][j] == EmptySpace?否则,保持这个常数有什么意义?

你真的想去break那里吗?这是否意味着您一旦找到一个非空的正方形或用完某种特定类型的棋子就停止填充一排?如果break应该在那里,他们去哪里进行第二个算法?您的代码无法推理,部分原因是所有重要的逻辑都被注释掉了(这不是阅读代码的有用方法!)并且因为缩进不一致。

您的第二个算法完全不可读,您是否有足够宽的屏幕可以在不换行的情况下看到该行?即使您这样做,也更容易阅读分手。

第二个算法检查board[i][j] == EmptySpace吗?它似乎没有,但也许这只是你的格式。

此外,所有这些评论使得在实现之间切换以比较结果变得很尴尬。如果你这样做:

    for (int i =0; i < 4; i++)
    {
        for (int j = 0; j < 10; j++)
        {
            if (board[i][j] == EmptySpace)
            {
#if 0
                int Chosen = rand()%10 +1;

                if (AIPieces[Chosen] < MaxPieces[Chosen])
                {
                    board[i][j] = Chosen;
                    AIPieces[Chosen]++;
                }
                else
                    break;
#else
                if (AIPieces[0] < MaxPieces[0]
                        || AIPieces[1] < MaxPieces[1]
                        || AIPieces[2] < MaxPieces[2]
                        || AIPieces[3] < MaxPieces[3]
                        || AIPieces[4] < MaxPieces[4]
                        || AIPieces[5] < MaxPieces[5]
                        || AIPieces[5] < MaxPieces[5]
                        || AIPieces[6] < MaxPieces[6]
                        || AIPieces[7] < MaxPieces[7]
                        || AIPieces[8] < MaxPieces[8]
                        || AIPieces[9] < MaxPieces[9]
                        || AIPieces[10] < MaxPieces[10]
                        || AIPieces[11] < MaxPieces[11]) 
                {
                    AIPieces[board[i][j] = rand() % 10+1]++;        
                }
#endif
            }
            else
                break;
        }
    }

然后您只需要更改一个字符(更改#if 0#if 1)即可在它们之间切换。

现在我可以正确地看到第二个算法,很明显,如果还有任何碎片,您将放置一个碎片,但这可能会放置一个您已经用完的碎片。例如,如果AIPieces[1] < MaxPieces[1]AIPieces[2] == MaxPieces[2]条件为真,但如果rand()%10 + 1返回 2,则表示您放置了不允许放置的部分。这意味着你放置了太多的某些类型的棋子。

我认为 Scott 有一个更好的主意,将各个部分的放置分开到一个函数中,这将使该循环易于阅读:

for (int i =0; i < 4; i++)
    for (int j = 0; j < 10; j++)
        AddPiece(rand() % 3 + 4, 1, 0);

现在您可以编写AddPiece2并更改对它的调用以试验不同的实现。比较这两种算法可以帮助找出问题所在。

于 2012-06-23T09:42:23.300 回答
1

我不确定我是否很好地理解了这个问题。但是,试图回答它。像这样的东西似乎是你所要求的:

而不是增加 AIPieces,您需要首先检查板上没有任何东西,并且 MaxPieces 尚未使用。

  AIPieces[board[1][0] = rand() % 3 + 4]++;

所以尝试一个函数来做到这一点:

void AddPiece(int pieceType, int locationX, int locationY)
{
    if( board[locationX][locationY] != 0 )
         return; // board already has something here, so don't add.

    if( AIPieces[pieceType] >= MaxPieces[pieceType] )
        return; // Can't add as all of these pieces have already been used.

    board[locationX][locationY] = pieceType;
    AIPieces[pieceType]++;
}

代替原来的行,像这样调用函数:

AddPiece(rand() % 3 + 4, 1, 0);

您的第二个算法将不起作用,因为当您尝试添加一个片段时,if 语句会检查是否使用了任何类型的片段,而不仅仅是检查您尝试添加的片段的类型。

于 2012-06-23T08:14:08.173 回答