QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 4014|回复: 1
打印 上一主题 下一主题

[推荐]利用C++编写猜字游戏

[复制链接]
字体大小: 正常 放大
sxqiang        

9

主题

2

听众

75

积分

与你共勉

升级  73.68%

该用户从未签到

新人进步奖

跳转到指定楼层
1#
发表于 2005-5-22 00:33 |只看该作者 |倒序浏览
|招呼Ta 关注Ta
现在,我们要用C++来写一个猜字母的游戏。其实做起来并不是那么难的。首先,我们必须了解一下游戏规则。<BR><BR>  一:玩家每次只能猜一个字母;<BR><BR>  二:玩家只能猜错有限次,否则游戏失败;<BR><BR>  三:猜错的字母将被记录下来;<BR><BR>  四:每次猜测后,游戏应显示出当前猜出的残缺单词,以及当前猜错的所有字母,和剩下的猜错的机会;<BR><BR>  五:假设玩家猜的字母在单词中,单词中所有的该字母将被视为已猜出,例如:如果原单词是apple,我们猜出了p,则程序应显示当前猜出的残缺单词为-pp--。<BR><BR>  六:不得多次猜测同一个字母,因为这样是浪费时间。<BR><BR></FONT><STRONG>  一:准备工作:</STRONG>
8 G' @. {# @! A2 A+ Y) h- r" L- f9 P<><STRONG>    </STRONG></FONT>规则就是这么多,我们应该用C++代码来实现它。首先,我们应考虑怎样记录单词,其中包括原单词、猜错的字母、当前猜出的残缺单词。如果用传统的C风格数组,这是很麻烦的,这用C风格字符串实现很困难。但C++为我们预先想到了这一切,C++中带有一个功能强大的string类,它的声明在头文件string中。注意,cstring或string.h中只是包含了一些处理字符串的函数,不包括string类。要使用这个类,我们首先要知道它的构造函数,这样才能创建string类对象。<BR></FONT><FONT size=2>    </FONT><BR></P>
6 B. ^0 [1 J8 W<TABLE>7 j0 u6 k6 @6 m3 E" F8 j

7 D5 U, h; T# _( F0 i0 S+ e0 p; _<TR>
; _% H3 f: r' N( T5 P" ~<TD width="54%">构造函数</TD>
* f+ Q* A7 \" }, h3 y8 C<TD width="46%">说明</TD></TR>% K. s/ |8 c2 g6 C! R' I
<TR>4 I, L3 r% p/ |! V! v9 N2 l( W4 B
<TD>string(const char* s)</TD>
5 o$ ~  N% K1 |3 _9 r* H0 }<TD>将string对象初始化为字符串s</TD></TR>& {* A, w' r1 T4 U5 ~
<TR>
: j9 V$ N. }7 S- r& t# E7 M  T<TD>string(size_type n,char c)</TD>
: ~% c. Z. L! R& J<TD>将对象初始化为有n个元素的对象,它们都是字符c</TD></TR>. N9 x" v3 Z3 ]" c' t
<TR>
6 B5 V8 w: }' G" Y7 f. ~<TD>string(const string&amp; str,size_type pos=0,size_type n=npos)</TD>0 i9 C& [& |. D) \9 U
<TD>将对象初始化为str中,从第pos个元素开始的n个元素。</TD></TR></TABLE><BR>   </FONT>其实,这个类的构造函数远不止这些,但我们开发这个游戏只用得到这些(也许还用不上这么多)。我们还要了解一些关于string类的知识。它重载了所有的关系操作符、可以用+=操作符把字符串、string类对象、字符加到对象的末尾。比如,我们可以写出这样的代码:string a="butter"; string b="fly"; a+=b;这是十分方便的。它还重载了[]操作符,使我们完全可以像常规数组一样用它。对于string类,我们还要初步了解一下它的输入选项。它有operator&gt;&gt;,所以我们可以用cin进行输入,并且它与istream中的cin的使用规则是一样的。值得注意的一点是,string类是一个比较智能的类,它能够自动调整字符串的长度,这样,我们就不用担心浪费空间或者输入字符串超出对象末尾了。而我们常用的getline()函数呢?这是一个成员函数,所以不能进行重载。解决的旆ㄊ牵瑂tring类带有一个getline()的非成员函数,它接受两个参数,第一个是istream类对象,第二个是string类对象,并且去掉了长度参数,原因已经说了。所以,假设temp是一个string类对象,我们应这样对它使用getline():getline(cin,string);看起来有点不好看,但实用。<BR><BR>  最后,要实现这个拼字游戏,我们必须在对象中查找字符。string类已经提供了这方面的函数了,请看下表(未完全列出)。<FONT size=2><BR> </FONT><BR>6 n0 w- Z2 T/ e  s
<TABLE>/ G7 u+ H. P' ^8 {8 _
& C4 O! }+ G5 |/ B. x4 Z
<TR>
2 \. u" e& {+ m5 z<TD>方法原型</TD>
  g1 p6 J' ]4 r+ b<TD>说明</TD></TR>
' K6 n7 G1 d* o+ F/ {% |<TR>
# I. n1 T2 e* C8 x! M/ d& ^) n<TD>size_type find(char ch,size_type pos=0)const;</TD>- `9 N* ~. ]2 h* w5 G
<TD>从字符串的pos位置开始,查找字符ch,若找到,返回第一个ch所在的索引,<BR>否则,返回string::npos。</TD></TR>
! N2 ?7 O# p( {<TR>8 f* s# K2 ?- G5 ?% b0 l1 ?
<TD>size_type find(const string&amp; str,size_type pos=0)const;</TD>
& t1 [( H9 m* W5 [1 J5 G3 S6 a<TD>从字符串的pos位置开始,查找字符串str,若找到,返回str的首字母所在的索引,否则,返回string::npos。</TD></TR>  l0 g$ b; G% o
<TR>) u. O# `! i1 e8 @
<TD>size_type find (const char* s,size_type pos=0)const;</TD># N8 L% j- `4 t& C
<TD>从字符串的pos位置开始,查找字符串s,若找到,返回s的首字母所在的索引,否则,返回string::npos。</TD></TR></TABLE>
  A5 o- o; u9 i. J5 Q& X5 ]  C$ m<><BR><FONT size=2>    </FONT>举例说明,若temp是一个string对象,内容为"apple",则temp.find('p')将返回1,即第一个字符p对应的索引。<FONT size=2><BR><STRONG></STRONG></FONT></P>& S1 F$ J1 u5 a: B6 p' s, U- H7 c  r
<><FONT size=2><STRONG>  二:游戏源代码:</STRONG></FONT></P>
- V; A# L0 h7 }+ A5 x<>
) C/ \  w5 V. h8 o( C8 J3 W: z<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#e6e4dd border=1>
& I- x- }5 k* x7 j6 K3 O' Z* a3 b! K! s' c) g, n
<TR>
- z+ C4 o. V, L<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 &lt;&lt; "Will you play a word game? <Y n>";<BR> cin &gt;&gt; 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&lt;&lt;"您有"&lt;&lt;guesses&lt;&lt;"次猜错的机会。 ";<BR>  cout&lt;&lt;"您的单词:"&lt;&lt;player&lt;&lt;' ';<BR>  while(guesses&gt;0&amp;&amp;player!=first)<BR>  {<BR>   cout&lt;&lt;"请您猜吧!";<BR>   cin&gt;&gt;guess;<BR>   if(badguess.find(guess)!=string::npos||player.find(guess)!=string::npos)<BR>   {<BR>    cout&lt;&lt;"对不起,这个字母您已经猜过了。";<BR>    continue;<BR>   }//判断是否已经猜过 <BR>   int temp=first.find(guess);<BR>   if(temp==string::npos)<BR>   {<BR>    cout&lt;&lt;"啊!猜错了。 ";<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&lt;&lt;"您还剩下"&lt;&lt;guesses&lt;&lt;"次猜错的机会。 ";<BR>   cout&lt;&lt;"您当前猜出的单词:"&lt;&lt;player&lt;&lt;' '; <BR>   cout&lt;&lt;"您当前猜错的字母集合:"&lt;&lt;badguess&lt;&lt;' '; <BR>  } <BR>  if(guesses==0)<BR>   cout&lt;&lt;"对不起,您失败了。 ";<BR>  else<BR>   cout&lt;&lt;"您真棒! ";<BR>   cout&lt;&lt;"正确单词为:"&lt;&lt;first&lt;&lt;' ';<BR>   cout &lt;&lt; "Will you play again? <Y n>"; <BR>   cin&gt;&gt;play;<BR> }<BR><BR> system("AUSE");<BR> return 0;<BR>}</TD></TR></TABLE><STRONG></P>+ I& K& }# r5 [# W* A- H) T! S9 l
<><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>
' A* y5 ]( h& c1 p! H+ ?<><BR>  三<STRONG>:程序分析<BR>    <BR></STRONG>  程序的运行结果大家都看到了,符合该游戏的规则,随机性也较强,这就是C++的强大。<BR><BR>  我们判断字母是否已经被猜过,是这样做的:<STRONG><BR><BR></STRONG>
6 k; D* O' T0 }! |<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#e6e4dd border=1>- u- D6 d8 t4 I1 f! j
9 v5 v2 W$ d2 M
<TR>
* k, X& @1 @4 C  |7 @4 u/ v% a- I<TD>if(badguess.find(guess)!=string::npos||<BR>player.find(guess)!=string::npos)<BR>{<BR> cout&lt;&lt;"对不起,这个字母您已经猜过了。";<BR> continue;<BR>}//判断是否已经猜过 </TD></TR></TABLE><BR>  因为如果字母被猜过,那么它要么在玩家猜出的残缺单词中,要么处于错误字母集合中,我们用find函数在这两处分别进行了搜索。<BR><BR>  对于猜错后的处理,我们又是这样做的:<BR><BR>
! U" b1 o% q. [# v, o8 o# r<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#e6e4dd border=1>7 _" v* A* E* @1 L) I

" ]& K+ e+ V/ y, Y<TR>5 {3 [- e% t4 G# `$ `
<TD>int temp=first.find(guess);<BR>if(temp==string::npos)<BR>{<BR> cout&lt;&lt;"啊!猜错了。\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>; L" E$ b  G' O
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#e6e4dd border=1>
/ `; R; O; n% k! F# g! N( j. N% K* Z0 C+ ]
<TR>- [1 T; T  l  ?: `8 A1 M: F2 n
<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
转播转播0 分享淘帖0 分享分享0 收藏收藏0 支持支持0 反对反对0 微信微信
不在学习中进步,就在无聊中堕落

5

主题

5

听众

912

积分

升级  78%

  • TA的每日心情
    开心
    2016-10-15 15:49
  • 签到天数: 13 天

    [LV.3]偶尔看看II

    自我介绍
    本人较内向,但却有浓厚的趣味和好奇心.再之本人叫诚恳和朴实.缺点就是不多愿与他人交流.谢谢!

    群组江苏建模

    群组Coldplayers

    群组Matlab讨论组

    群组南京邮电大学数模协会

    群组西南大学建模组

    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 注册地址

    qq
    收缩
    • 电话咨询

    • 04714969085
    fastpost

    关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

    手机版|Archiver| |繁體中文 手机客户端  

    蒙公网安备 15010502000194号

    Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

    GMT+8, 2026-4-20 09:21 , Processed in 0.437090 second(s), 57 queries .

    回顶部