- 在线时间
- 0 小时
- 最后登录
- 2010-9-8
- 注册时间
- 2004-11-16
- 听众数
- 2
- 收听数
- 0
- 能力
- 0 分
- 体力
- 160 点
- 威望
- 0 点
- 阅读权限
- 20
- 积分
- 75
- 相册
- 0
- 日志
- 0
- 记录
- 0
- 帖子
- 53
- 主题
- 9
- 精华
- 0
- 分享
- 0
- 好友
- 0

与你共勉
升级   73.68% 该用户从未签到
 |
现在,我们要用C++来写一个猜字母的游戏。其实做起来并不是那么难的。首先,我们必须了解一下游戏规则。<BR><BR> 一:玩家每次只能猜一个字母;<BR><BR> 二:玩家只能猜错有限次,否则游戏失败;<BR><BR> 三:猜错的字母将被记录下来;<BR><BR> 四:每次猜测后,游戏应显示出当前猜出的残缺单词,以及当前猜错的所有字母,和剩下的猜错的机会;<BR><BR> 五:假设玩家猜的字母在单词中,单词中所有的该字母将被视为已猜出,例如:如果原单词是apple,我们猜出了p,则程序应显示当前猜出的残缺单词为-pp--。<BR><BR> 六:不得多次猜测同一个字母,因为这样是浪费时间。<BR><BR></FONT><STRONG> 一:准备工作:</STRONG>
5 B% c k2 L- t< ><STRONG> </STRONG></FONT>规则就是这么多,我们应该用C++代码来实现它。首先,我们应考虑怎样记录单词,其中包括原单词、猜错的字母、当前猜出的残缺单词。如果用传统的C风格数组,这是很麻烦的,这用C风格字符串实现很困难。但C++为我们预先想到了这一切,C++中带有一个功能强大的string类,它的声明在头文件string中。注意,cstring或string.h中只是包含了一些处理字符串的函数,不包括string类。要使用这个类,我们首先要知道它的构造函数,这样才能创建string类对象。<BR></FONT><FONT size=2> </FONT><BR></P>
& ?; ^" g0 \0 ]<TABLE>
9 P- \/ Z m9 m) p7 `
* s; @% _ r$ B<TR>
" l, R( {/ [& Q/ h$ a9 t ]+ H* X4 o<TD width="54%">构造函数</TD>5 K8 i% W' U' y) {5 y9 B5 ~
<TD width="46%">说明</TD></TR>8 s4 I6 Z1 @9 \: D% `
<TR>
2 ~0 _- V3 d2 W<TD>string(const char* s)</TD>* F/ e" A z2 _, v! j
<TD>将string对象初始化为字符串s</TD></TR>' h1 o- _5 U% B6 f9 |7 O. R" g: N
<TR>( ]. G) _9 Q9 U: ]
<TD>string(size_type n,char c)</TD>2 G7 ~# M M7 M, r2 s4 H5 w7 X2 T
<TD>将对象初始化为有n个元素的对象,它们都是字符c</TD></TR>
8 b. F5 t ?% }+ N, @7 H# o# w8 t<TR>
& Q! I R3 i* g1 f6 y<TD>string(const string& str,size_type pos=0,size_type n=npos)</TD>
$ g4 E+ f* V2 {5 K# K$ i8 j<TD>将对象初始化为str中,从第pos个元素开始的n个元素。</TD></TR></TABLE><BR> </FONT>其实,这个类的构造函数远不止这些,但我们开发这个游戏只用得到这些(也许还用不上这么多)。我们还要了解一些关于string类的知识。它重载了所有的关系操作符、可以用+=操作符把字符串、string类对象、字符加到对象的末尾。比如,我们可以写出这样的代码:string a="butter"; string b="fly"; a+=b;这是十分方便的。它还重载了[]操作符,使我们完全可以像常规数组一样用它。对于string类,我们还要初步了解一下它的输入选项。它有operator>>,所以我们可以用cin进行输入,并且它与istream中的cin的使用规则是一样的。值得注意的一点是,string类是一个比较智能的类,它能够自动调整字符串的长度,这样,我们就不用担心浪费空间或者输入字符串超出对象末尾了。而我们常用的getline()函数呢?这是一个成员函数,所以不能进行重载。解决的旆ㄊ牵瑂tring类带有一个getline()的非成员函数,它接受两个参数,第一个是istream类对象,第二个是string类对象,并且去掉了长度参数,原因已经说了。所以,假设temp是一个string类对象,我们应这样对它使用getline():getline(cin,string);看起来有点不好看,但实用。<BR><BR> 最后,要实现这个拼字游戏,我们必须在对象中查找字符。string类已经提供了这方面的函数了,请看下表(未完全列出)。<FONT size=2><BR> </FONT><BR>
# X# }& b' a8 ]1 f. d<TABLE>6 o5 O* ~' Q+ k6 f! e
& k4 [2 n) S W3 m" D
<TR>
9 ?% k- n8 ^; w8 ~/ Y" W<TD>方法原型</TD>
1 j# n e' f- F4 N) A<TD>说明</TD></TR>
) l ^ d; Z* d/ V) }<TR>
& w! A; N" H. I4 M9 x<TD>size_type find(char ch,size_type pos=0)const;</TD>6 h2 S. p- V9 y' d
<TD>从字符串的pos位置开始,查找字符ch,若找到,返回第一个ch所在的索引,<BR>否则,返回string::npos。</TD></TR>* f X9 j! u- {% F8 S% p! Y
<TR>
8 l7 R5 X2 V/ a2 w1 y1 o. K2 E<TD>size_type find(const string& str,size_type pos=0)const;</TD>
5 X) U2 n3 o" R3 U, W0 w<TD>从字符串的pos位置开始,查找字符串str,若找到,返回str的首字母所在的索引,否则,返回string::npos。</TD></TR>
. B) X0 |2 i2 h3 T0 w<TR>
9 e9 r- `8 V- L6 F U% z" i) V<TD>size_type find (const char* s,size_type pos=0)const;</TD>
" j4 ~4 p2 P. j& S3 B" f) G6 P<TD>从字符串的pos位置开始,查找字符串s,若找到,返回s的首字母所在的索引,否则,返回string::npos。</TD></TR></TABLE>( T, Q1 C( m, l* s) Y) I9 N
< ><BR><FONT size=2> </FONT>举例说明,若temp是一个string对象,内容为"apple",则temp.find('p')将返回1,即第一个字符p对应的索引。<FONT size=2><BR><STRONG></STRONG></FONT></P>- x& d T+ o8 @& A4 o+ m+ U; P" w
< ><FONT size=2><STRONG> 二:游戏源代码:</STRONG></FONT></P>
w n3 ^% @ _$ f' R' [" n< >, A9 ]# \! i8 i, a2 A. N
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#e6e4dd border=1>
3 T/ a& J$ {3 |' D9 s! w' F; I
4 S3 A: a6 S1 w* p<TR>
2 d9 ]( M Y/ A/ S2 x<TD>#include <IOSTREAM><BR>#include <STRING><BR>#include <CSTDLIB><BR>#include <CTIME><BR>#include <CCTYPE><BR>using namespace std;<BR>const int NUM = 26;<BR>const string wordlist[NUM] = {"alabama", "choice", "usually",<BR>"dangerous", "deer", "panda", "love", "health", "exciting",<BR>"interesting", "administrator", "professional", "manage", "nonce", "onset",<BR>"typeid", "quarter", "remote", "lovely", "car", "keeper",<BR>"valid", "where", "mean", "important", "last"};//供游戏的单词库 <BR><BR>int main()<BR>{<BR> srand(time(0));<BR> char play;<BR> cout << "Will you play a word game? <Y n>";<BR> cin >> play;<BR> play = tolower(play);<BR> while(play=='y')<BR> {<BR> string first(wordlist[rand()%NUM]);//随机选择单词 <BR> int length=first.length();<BR> string player(length,'-');//玩家猜测的单词 <BR> string badguess;//猜错的字母集合 <BR> int guesses=10;//猜错的机会 <BR> char guess;<BR> cout<<"您有"<<guesses<<"次猜错的机会。 ";<BR> cout<<"您的单词:"<<player<<' ';<BR> while(guesses>0&&player!=first)<BR> {<BR> cout<<"请您猜吧!";<BR> cin>>guess;<BR> if(badguess.find(guess)!=string::npos||player.find(guess)!=string::npos)<BR> {<BR> cout<<"对不起,这个字母您已经猜过了。";<BR> continue;<BR> }//判断是否已经猜过 <BR> int temp=first.find(guess);<BR> if(temp==string::npos)<BR> {<BR> cout<<"啊!猜错了。 ";<BR> guesses--;<BR> badguess+=guess;<BR> }//猜错后的处理 <BR> else<BR> {<BR> player[temp]=guess;<BR> temp=first.find(guess,temp+1);<BR> while(temp!=string::npos)//继续搜索该字符,看是否单词中有多个该字符 <BR> {<BR> player[temp]=guess;<BR> temp=first.find(guess,temp+1);<BR> }<BR> }<BR> cout<<"您还剩下"<<guesses<<"次猜错的机会。 ";<BR> cout<<"您当前猜出的单词:"<<player<<' '; <BR> cout<<"您当前猜错的字母集合:"<<badguess<<' '; <BR> } <BR> if(guesses==0)<BR> cout<<"对不起,您失败了。 ";<BR> else<BR> cout<<"您真棒! ";<BR> cout<<"正确单词为:"<<first<<' ';<BR> cout << "Will you play again? <Y n>"; <BR> cin>>play;<BR> }<BR><BR> system(" AUSE");<BR> return 0;<BR>}</TD></TR></TABLE><STRONG></P>
* t2 k9 k! r& U< ><BR> 下面是运行结果:<BR><BR></STRONG> Will you play a word game? <Y n>y<BR> 您有10次猜错的机会。<BR> 您的单词:------------<BR> 请您猜吧!a<BR> 您还剩下10次猜错的机会。<BR> 您当前猜出的单词:----------a-<BR> 您当前猜错的字母集合:<BR> 请您猜吧!s<BR> 您还剩下10次猜错的机会。<BR> 您当前猜出的单词:-----ss---a-<BR> 您当前猜错的字母集合:<BR> 请您猜吧!p<BR> 您还剩下10次猜错的机会。<BR> 您当前猜出的单词:p----ss---a-<BR> 您当前猜错的字母集合:<BR> 请您猜吧!o<BR> 您还剩下10次猜错的机会。<BR> 您当前猜出的单词:p-o--ss-o-a-<BR> 您当前猜错的字母集合:<BR> 请您猜吧!r<BR> 您还剩下10次猜错的机会。<BR> 您当前猜出的单词:pro--ss-o-a-<BR> 您当前猜错的字母集合:<BR> 请您猜吧!f<BR> 您还剩下10次猜错的机会。<BR> 您当前猜出的单词:prof-ss-o-a-<BR> 您当前猜错的字母集合:<BR> 请您猜吧!e<BR> 您还剩下10次猜错的机会。<BR> 您当前猜出的单词:profess-o-a-<BR> 您当前猜错的字母集合:<BR> 请您猜吧!i<BR> 您还剩下10次猜错的机会。<BR> 您当前猜出的单词:professio-a-<BR> 您当前猜错的字母集合:<BR> 请您猜吧!n<BR> 您还剩下10次猜错的机会。<BR> 您当前猜出的单词:professiona-<BR> 您当前猜错的字母集合:<BR> 请您猜吧!l<BR> 您还剩下10次猜错的机会。<BR> 您当前猜出的单词:professional<BR> 您当前猜错的字母集合:<BR> 您真棒!<BR> 正确单词为:professional<BR> Will you play again? <Y n>n<BR> 请按任意键继续. . .</P>* Z# j' i9 D. C$ n1 R% g O
< ><BR> 三<STRONG>:程序分析<BR> <BR></STRONG> 程序的运行结果大家都看到了,符合该游戏的规则,随机性也较强,这就是C++的强大。<BR><BR> 我们判断字母是否已经被猜过,是这样做的:<STRONG><BR><BR></STRONG>
' c2 q2 R" T- E: c# e<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#e6e4dd border=1>
, o& f3 G/ O+ @
6 k8 o" ^6 ]/ N<TR>
7 u8 ] ^" Y& w: x; L5 e) u<TD>if(badguess.find(guess)!=string::npos||<BR>player.find(guess)!=string::npos)<BR>{<BR> cout<<"对不起,这个字母您已经猜过了。";<BR> continue;<BR>}//判断是否已经猜过 </TD></TR></TABLE><BR> 因为如果字母被猜过,那么它要么在玩家猜出的残缺单词中,要么处于错误字母集合中,我们用find函数在这两处分别进行了搜索。<BR><BR> 对于猜错后的处理,我们又是这样做的:<BR><BR> l' u! Q" z5 A0 Y
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#e6e4dd border=1>
0 a' s. q9 Y5 g
) ^: m5 g: d* x; |0 S- c<TR>) |) U- l: D/ L0 B5 q# |
<TD>int temp=first.find(guess);<BR>if(temp==string::npos)<BR>{<BR> cout<<"啊!猜错了。\n";<BR> guesses--;<BR> badguess+=guess;<BR>}//猜错后的处理 </TD></TR></TABLE><BR> 首先,我们查找这个字符是否在单词中出现。如果没有出现,find函数将返回string::npos。npos是一个常量,比string能存储的最大元素数多1。如果没有出现,我们先是将猜错的机会减去一次,再用了这个代码:badguess+=guess;将错误的字母加入badguess对象中。想想,这要用常规字符数组有多难?<BR><BR> 最后,如果temp不是string::npos,那么我们就说玩家猜对了。但可能这个单词中有多个这样的字母,所以,我们这样做了:<BR><BR>2 Y0 J7 I+ Z5 u0 ~8 ^' y. N+ e1 O; b
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#e6e4dd border=1>
1 _& f5 C! `0 n4 d7 b0 `8 Z
4 x6 E8 U+ S% S# m; X0 ^<TR>
; j6 M0 E- l# w& B. r<TD>temp=first.find(guess,temp+1);<BR>while(temp!=string::npos)//继续搜索该字符,看是否单词中有多个该字符 <BR>{<BR> player[temp]=guess;<BR> temp=first.find(guess,temp+1);<BR>}</TD></TR></TABLE><BR> 这样一来,逐步缩小区间,直到确认单词中再无这个字符为止。大家从运行结果中也可以看到这一点:<BR><BR> 您当前猜出的单词:----------a-<BR> 您当前猜错的字母集合:<BR> 请您猜吧!s<BR> 您还剩下10次猜错的机会。<BR> 您当前猜出的单词:-----ss---a-//将两个“s”都显示出来了<BR> 您当前猜错的字母集合:<BR> <BR> 大家若有兴趣,可以对这个程序进行扩充,比如加入难度选择、最后给出对玩家的评价等。最后,希望大家能通过这个范例,更加热爱C++!</P></FONT></TD></TR> |
zan
|