论坛交流
首页办公自动化| 网页制作| 平面设计| 动画制作| 数据库开发| 程序设计| 全部视频教程
应用视频: Windows | Word2007 | Excel2007 | PowerPoint2007 | Dreamweaver 8 | Fireworks 8 | Flash 8 | Photoshop cs | CorelDraw 12
编程视频: C语言视频教程 | HTML | Div+Css布局 | Javascript | Access数据库 | Asp | Sql Server数据库Asp.net  | Flash AS
当前位置 > 文字教程 > C语言程序设计教程
Tag:新手,函数,指针,数据类型,对象,Turbo,入门,运算符,数组,结构,二级,,tc,游戏,试题,问答,编译,视频教程

C趣味编程百例(30)

文章类别:C语言程序设计 | 发表日期:2008-9-24 14:44:41

91.人机猜数游戏
92.人机猜数游戏(2)


91.人机猜数游戏
   由计算机“想”一个四位数,请人猜这个四位数是多少。人输入四位数字后,计算机首先判定这四位数字中有几位是猜对了,并且在对的数字中又有几位位置也是对的,将结果显示出来,给人以提示,请人再猜,直到人猜出计算机所想的四位数是多少为止。
   例如:计算机“想”了一个“1234”请人猜,可能的提示如下:
      人猜的整数         计算机判定有几个数字正确         有几个位置正确
         1122                        2                           1
         3344                        2                           1
         3312                        3                           0
         4123                        4                           0
         1243                        4                           2
         1234                        4                           4
                                                              游戏结束
   请编程实现该游戏。游戏结束时,显示人猜一个数用了几次。
*问题分析与算法设计
   问题本身清楚明了。判定相同位置上的数字是否相同不需要非凡的算法。只要截取相同位置上的数字进行比较即可。但在判定几位数字正确时,则应当注重:计算机所想的是“1123”,而人所猜的是“1576”,则正确的数字只有1位。
   程序中截取计算机所想的数的每位数字与人所猜的数字按位比较。若有两位数字相同,则要记信所猜中数字的位置,使该位数字只能与一位对应的数字“相同”。当截取下一位数字进行比较时,就不应再与上述位置上的数字进行比较,以避免所猜的数中的一位与对应数中多位数字“相同”的错误情况。
*程序与程序注释
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
void main()
{
   int stime,a,z,t,i,c,m,g,s,j,k,l[4];    /*j:数字正确的位数  k:位置正确的位数*/
   long ltime;
   ltime=time(NULL);       /*l:数字相同时,人所猜中数字的正确位置*/
   stime=(unsigned int)ltime/2;
   srand(stime);
   z=random(9999);        /*计算机想一个随机数*/
   printf("I have a number with 4 digits in mind,please guess.\n");
   for(c=1;;c++)         /*c: 猜数次数计数器*/
   {
      printf("Enter a number with 4 digits:");
      scanf("%d",&g);           /*请人猜*/    
      a=z;j=0;k=0;l[0]=l[1]=l[2]=l[3]=0;
      for(i=1;i<5;i++)      /*i:原数中的第i位数。个位为第一位,千位为第4位*/
      {
         s=g;m=1;
         for(t=1;t<5;t++)     /*人所猜想的数*/
         {
            if(a%10==s%10)     /*若第i位与人猜的第t位相同*/
            {
               if(m&&t!=l[0]&&t!=l[1]&&t!=l[2]&&t!=l[3])
               {
                  j++;m=0;l[j-1]=t;    /*若该位置上的数字尚未与其它数字“相同”*/
               }                       /*记录相同数字时,该数字在所猜数字中的位置*/
            
            if(i==t) k++;         /*若位置也相同,则计数器k加1*/
         }
         s/=10;
      }
      a/=10;
   }
   printf("You hane correctly guessed %d digits,\n",j);
   printf("and correctly guessed %d digits in exact position.\n",k);
   if(k==4) break;         /*若位置全部正确,则人猜对了,退出*/
   }
   printf("Now you have correctly guessed the whole number after %d times.\n",c);
}

*运行示例


    Now you have correctly guessed the whole number after 7 times.

*思考题
   猜数游戏。由计算机“想”一个数请人猜,人输入猜的数,假如猜对了,则结束游戏,否则计算机会给出提示,指出人猜的数是太大,还是太小。当一个数猜了20次还未猜中时,应停止猜数者继续游戏的权力,从程序中退出。



92.人机猜数游戏(2)
   将以上游戏双方倒一下,请人想一个四位的整数,计算机来猜,人给计算机提示信息,最终看计算机用几次猜出一个人“想”的数。请编程实现。
*问题分析与算法设计
   解决这类问题时,计算机的思考过程不可能象人一样具完备的推理能力,要害在于要将推理和判定的过程变成一种机械的过程,找出相应的规则,否则计算机难以完成推理工作。
   基于对问题的分析和理解,将问题进行简化,求解分为两个步聚来完成:首先确定四位数字的组成,然后再确定四位数字的排列顺序。可以列出如下规则:
   1)分别显示四个1,四个2,......,四个0,确定四位数字的组成。
   2)依次产生四位数字的全部排列(依次两两交换全部数字的位置)。
   3)根据人输入的正确数字及正确位置的数目,进行分别处理:
      (注重此时不出现输入的情况,因为在四个数字已经确定的情况下,若有3个位置正确,则第四个数字的位置必然也是正确的)
   若输入4:游戏结束。
   判定本次输入与上次输入的差值
   若差为2:说明前一次输入的一定为0,本次输入的为2,本次交换的两个数字的位置是正确的,只要交换另外两个没有交换过的数字即可结束游戏。
   若差为-2:说明前一次输入的一定为2,本次的一定为0。说明刚交换过的两个数字的位置是错误的,只要将交换的两个数字位置还原,并交换另外两个没有交换过的数字即可结束游戏。
   否则:若本次输入的正确位置数<=上次的正确位置数
      则恢复上次四位数字的排列,控制转3)
      否则:将本次输入的正确位置数作为“上次输入的正确位置数”,控制转3)。
*程序与程序注释
#include<stdio.h>
#include<stdlib.h>
void bhdy(int s,int b);
void prt();
int a[4],flag,count;
void main()
{
   int b1,b2,i,j,k=0,p,c;
   printf("Game guess your number in mind is # # # #.\n");
   for(i=1;i<10&&k<4;i++)    /*分别显示四个1~9确定四个数字的组成*/
   {
      printf("No.%d:your number may be:%d%d%d%d\n",++count,i,i,i,i);
      printf("How many digits have bad correctly guessed:");
      scanf("%d",&p);          /*人输入包含几位数字*/ 
      for(j=0;j<p;j++)
         a[k+j]=i;          /*a[]:存放已确定数字的数组*/
      k+=p;             /*k:已确定的数字个数*/
   }
   if(k<4)           /*自动算出四位中包的个数*/
      for(j=k;j<4;j++)
         a[j]=0;
      i=0;
   printf("No.%d:your number may be:%d%d%d%d\n",++count,a[0],a[1],a[2],a[3]);
   printf("How many are in exact positions:");    /*顺序显示四位数字*/
   scanf("%d",&b1);             /*人输入有几位位置是正确的*/
   if(b1==4){prt();exit(0);}     /*四位正确,打印结果。结束游戏*/
   for(flag=1,j=0;j<3&&flag;j++)   /*实现四个数字的两两(a[j],a[k]交换*/
      for(k=j+1;k<4&&flag;k++)
         if(a[j]!=a[k])
         {
            c=a[j];a[j]=a[k];a[k]=c;      /*交换a[j],a[k]*/
            printf("No.%d:Your number may be: %d%d%d%d\n",++count,a[0],a[1],a[2],a[3]);
            printf("How many are in exact positins:");
            scanf("%d",&b2);          /*输入有几个位置正确*/
            if(b2==4){prt();flag=0;}    /*若全部正确,结束游戏*/
            else if(b2-b1==2)bhdy(j,k);  /*若上次与本次的差为2,则交换两个元素即可结束*/
            else if(b2-b1==-2)   /*若上次与本次的差为-2,则说明已交换的(a[j],a[k])是错误的
                                   将(a[j],a[k]还原后,只要交换另外两个元素即可结束游戏*/
            {
               c=a[j];a[j]=a[k];a[k]=c;
               bhdy(j,k);
            }
            else if(b2<=b1)
            {
               c=a[j];a[j]=a[k];a[k]=c;     /*恢复交换的两个数字*/
            }
            else b1=b2;    /*其它情况则将新输入的位置信息作为上次的位置保存*/
         }
      if(flag) printf("You input error!\n");  /*交换结果仍没结果,只能是人输入的信息错误*/
}
void prt()         /*打印结果,结束游戏*/
{
   printf("Now your number must be %d%d%d%d.\n",a[0],a[1],a[2],a[3]);
   printf("Game Over\n");
}
void bhdy(int s,int b)
{
   int i,c=0,d[2];
   for(i=0;i<4;i++)             /*查找s和b以外的两个元素下标*/
      if(i!=s&&i!=b) d[c++]=i;
   i=a[d[1>;a[d[1>=a[d[0>;  a[d[0>=i;  /*交换除a[s]和a[b]以外的两个元素*/
   prt();        /*打印结果,结束游戏*/
   flag=0;
}

*运行示例假 设人想的四位数是:7215
Game Begin
Now guess your number in mind is # # # #.
No.1:your number may be:1111



*问题的进一步讨论
    本程序具有逻辑结构清析、算法简单正确的优点,但在接受人的输入信息时缺少必要的出错保护功能,同时在进行第三步推理过程中没有保留每次猜出的数字位置信息及人输入的回答,这样对于每次人输入的信息就无法进行合法性检查,即无法检查人的输入信息是否自相矛盾;同晨也无法充分利用前面的结果。
    这些缺陷是可以改进的,但最后一个问题改进难度较大,留给大家自己去完成。

*思考题
    “一条龙游戏”。在一个3×3的棋盘上,甲乙双方进行对弃,双方在棋盘上轮流放入棋子,假如一方的棋子成一直线(横、竖或斜线),则该方赢。请编写该游戏程序实现人与机器的比赛。比赛结果有三种:输、赢或平。
    在编程过程中请首先分析比赛中怎样才能获胜,找出第一步走在什么位置就最可能赢。          
上一篇:{实例}C趣味程序百例(29) 人气:5331
下一篇:{实例}C趣味编程百例(31) 人气:5968
视频教程列表
文章教程搜索
 
C语言程序设计推荐教程
C语言程序设计热门教程