0

我有一个我正在研究的程序,它类似于拼字游戏。下面这个程序是一个“小程序”,但是它应该能够打印出两个玩家的 7 个起始牌。这个小程序似乎应该可以完全运行,但它只是崩溃了。你们有一个想法,为什么它不运行。非常感谢您的宝贵时间!:D

#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
#include <ctime>
#include <cctype>
using namespace std;

void selectTiles(char (*lettArray)[53], char (*playPieces)[8], char (*compPieces)[8])
{
    int pP1, pP2, pP3, pP4, pP5, pP6, pP7;
    int cP1, cP2, cP3, cP4, cP5, cP6, cP7;
    //0000000

    srand(time(NULL)); 
    rand();

    pP1=rand()%53;
    (*playPieces)[0]=(*lettArray)[pP1];
    strcpy((lettArray)[pP1],"*");

    do{
        pP2=rand()%53;
        (*playPieces)[1]=(*lettArray)[pP2];

    }while(strcmp((lettArray)[pP2],"*")==0);

    do{
        pP3=rand()%53;
        (*playPieces)[2]=(*lettArray)[pP3];
    }while(strcmp((lettArray)[pP3],"*")==0);

    do{
         pP4=rand()%53;(*playPieces)[3]=(*lettArray)[pP4];
    }while(strcmp((lettArray)[pP4],"*")==0);

    do{
         pP5=rand()%53;(*playPieces)[4]=(*lettArray)[pP5];
    }while(strcmp((lettArray)[pP5],"*")==0);

    do{
         pP6=rand()%53;(*playPieces)[5]=(*lettArray)[pP6];
    }while(strcmp((lettArray)[pP6],"*")==0);

    do{
         pP7=rand()%53;(*playPieces)[6]=(*lettArray)[pP7];
    }while(strcmp((lettArray)[pP7],"*")==0);

    do{
         cP1=rand()%53;(*compPieces)[0]=(*lettArray)[cP1];
    }while(strcmp((lettArray)[cP1],"*")==0);

    do{
         cP2=rand()%53;(*compPieces)[1]=(*lettArray)[cP2];
    }while(strcmp((lettArray)[cP2],"*")==0);

    do{
         cP3=rand()%53;(*compPieces)[2]=(*lettArray)[cP3];
    }while(strcmp((lettArray)[cP3],"*")==0);

   do{
         cP4=rand()%53;(*compPieces)[3]=(*lettArray)[cP4];
   }while(strcmp((lettArray)[cP4],"*")==0);

   do{
         cP5=rand()%53;(*compPieces)[4]=(*lettArray)[cP5];
   }while(strcmp((lettArray)[cP5],"*")==0);

   do{
         cP6=rand()%53;(*compPieces)[5]=(*lettArray)[cP6];
   }while(strcmp((lettArray)[cP6],"*")==0);

   do{
         cP7=rand()%53;(*compPieces)[6]=(*lettArray)[cP7];
    }while(strcmp((lettArray)   [cP7],"*")==0);

    //0000000 

 }

int main()
{
    char lettArray[53]="AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXXYYZZ";
    char (*pLetters)[53]=&lettArray;

    char player[8];
    char (*pPlayer)[8]=&player;

    char computer[8];
    char (*pComputer)[8]=&computer;
    selectTiles(pLetters,pPlayer,pComputer); 

    for (int i=0;i<53;i++)
       cout<<"|"<<lettArray[i]<<"|";

     cout<<endl;

    for (int i=0;i<8;i++)
       cout<<"|"<<player[i]<<"|";

     cout<<endl;


     for (int i=0;i<8;i++)
        cout<<"|"<<computer[i]<<"|";

     cout<<endl;
     system("pause");
 }
4

2 回答 2

1

我认为问题出在这里:

void selectTiles(char (*lettArray)[53], ...)
{
  ...
  pP1=rand()%53;
  strcpy((lettArray)[pP1],"*");
  ...
}

strcpy不是在你认为它在做的事情。它(通常)写入越界并导致未定义的行为。使用std:string而不是char [],引用而不是指针,并在开发代码时对其进行测试,您将不会遇到这些问题。

编辑:

好的,首先让我们整理一下代码,这样我们就可以看到我们在做什么。所有这些复制粘贴的 do-while 循环selectTiles(...)看起来都很痛苦。第 1 步,我们引入了一个用于从 中抽取随机字符的新函数lettArray

char draw(char *lettArray)
{
  int pp;
  do{
    pp=rand()%53;
  }while(lettArray[pp]=='*');
  return(lettArray[pp]);
}

void selectTiles(char (*lettArray)[53], char (*playPieces)[8],
                 char (*compPieces)[8])
{
  int pP1;

  //0000000

  srand(time(NULL));
  rand();

  pP1=rand()%53;
  (*playPieces)[0]=(*lettArray)[pP1];
  strcpy((lettArray)[pP1],"*");

  (*playPieces)[1]=draw(*lettArray);
  (*playPieces)[2]=draw(*lettArray);
  (*playPieces)[3]=draw(*lettArray);
  (*playPieces)[4]=draw(*lettArray);
  (*playPieces)[5]=draw(*lettArray);
  (*playPieces)[6]=draw(*lettArray);

  (*compPieces)[0]=draw(*lettArray);
  (*compPieces)[1]=draw(*lettArray);
  (*compPieces)[2]=draw(*lettArray);
  (*compPieces)[3]=draw(*lettArray);
  (*compPieces)[4]=draw(*lettArray);
  (*compPieces)[5]=draw(*lettArray);
  (*compPieces)[6]=draw(*lettArray);

  //0000000

}

仅此一项就将代码长度减少了 30 行,并使其更易于阅读。它还强调了将指针传递给数组的愚蠢。在 C 中,数组作为指向第一个元素的指针传递,因此不需要进一步的间接寻址。由于 (in selectTiles)lettArray是指向 a 的指针char[],因此这一行:

strcpy((lettArray)[pP1],"*");

是致命的。如果pP1是,比如说,12,你没有在数组的第十二个(或第十三个)位置放一个星号,你正在将“*”复制到第十二个字符数组中。也就是说,你写的越界。让我们更正这条线(并放入一些for循环):

  pP1=rand()%53;
  (*playPieces)[0]=(*lettArray)[pP1];
  (*lettArray)[pP1]= '*';

  for(int k=1 ; k<7 ; ++k)
    (*playPieces)[k]=draw(*lettArray);

  for(int k=0 ; k<7 ; ++k)
    (*compPieces)[k]=draw(*lettArray);

并且代码停止崩溃。仍然有很多改进的可能,但现在它可以工作了。

于 2013-04-07T04:31:36.420 回答
1

我在 Cygwin 下的 g++ 版本 4.5.3 上编译了这个程序,并且在更改#include <string>#include <cstring>它之后编译并运行没有明显问题。

然而,当我查看输出时,很明显程序为每个玩家的拼字游戏字母写了 8 个字母而不是 7 个字母,并且每组中的最后一个字母来自之前未分配的内存块。

因此,我建议如下:

for (int i=0;i<8;i++)

... 应该:

for (int i=0;i<7;i++)

很可能还有其他我还没有发现的错误。

(编辑)

该行:

对于 (int i=0;i<53;i++)

... 还打印一个额外的字符。它应该是:

对于 (int i=0;i<52;i++)

此外,放大 Beta 关于使用 的点strcpy,会将两个strcpy(dest,"*")字符复制到 指向的地址,而不是一个字符。也就是说,它将复制“*”终止字符串的空值。这可能会覆盖不打算用 null 覆盖的数据。dest

于 2013-04-07T04:34:02.833 回答