| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2707 人关注过本帖, 5 人收藏
标题:牛刀小试 之 猜数字
只看楼主 加入收藏
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
结帖率:100%
收藏(5)
已结贴  问题点数:100 回复次数:23 
牛刀小试 之 猜数字
GuessNumber.rar (50.51 KB)
这两天看到有朋友做猜数字游戏,勾起我很多美好的回忆。我做的第一个自我感觉良好的程序就是猜数字游戏(不是猜大小的那个猜数字),以前用过文曲星的朋友应该玩过,我就是玩了朋友的文曲星后决定翻版这个游戏。最早是在小霸王学习机上用BASIC实现的(呵呵,还有人知道小霸王吗?),后来学习C语言,用C又翻版了一遍。之后每学一门新语言都会拿这个小游戏来练手。再后来,猜电脑出的数字玩腻了,又写了段代码,我出数字让电脑猜。

呵呵,都是很久以前的事了。这个游戏很适合大家作为编程练习来试一下。

哪位有兴趣也翻版一下?

作为奖励,周日(9月25日)前,第一位实现这个游戏的送80分,其他实现的平分20分。如果只有一位实现,则100分全送他。没有人实现,那分数就平分给捧场的朋友了。

介绍一下游戏规则:

首先计算机生成一个随机的4位数字,这个4位数每一位互不相同,首位可以为0。

玩家猜这个4位数是多少。计算机跟据玩家每次提交的数字给出相应的提示,提示的格式为xAyB。

A表示玩家的4位数中某一位数字与计算机出的4位数中的一位,数字相同,位置也相同。
B表示玩家的4位数中某一位数字与计算机出的4位数中的一位,数字相同,但位置不同。
x表示这次玩家猜的数中有几个得A。
y表示这次玩家猜的数中有几个得B。

如果在7次之内玩家猜到了计算机的数字(也就是4A)则获胜,超过7次则失败。可以证明,任何这样的4位数都可以在7次之内猜到。

玩这个游戏需要一定的推理能力。为了更直观一些,我做了一个简单的示例,大家可以下载玩玩,了解一下游戏的过程。由于程序是用C#写的,win7系统可以直接玩,xp需要有2.0以上版本的.net的支持。

不限语言,不要求界面,只要能实现游戏的逻辑就可以。
搜索更多相关主题的帖子: 文曲星 朋友 游戏 小霸王 学习机 
2011-09-19 09:37
tisyang
Rank: 8Rank: 8
等 级:蝙蝠侠
帖 子:132
专家分:737
注 册:2011-5-7
收藏
得分:80 
程序代码:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int number[4];

void init()
{
  int i = 0;
  int temp;

  int flag[10]={0};

  while( i < 4)
    {
      temp = rand()%10;
      if( flag[temp] != 0)
        continue;
      number[i] = temp;
      flag[temp] = 1;
      i++;
    }
  
}
void output(const int *buf, int n)
{
  int i;
  for(i = 0; i < n;  i++)
    printf("%d", buf[i]);
}

int unique(const int *num, int n)
{
  int i = 0;
  int j;
  while(i<n)
    {
      for(j=i+1;j<n;j++)
        {
          if(num[i] == num[j])
            return 0;
          else
            continue;
        }   
      i++;
    }
  return 1;
}
int get_number(const char * input, int * buf)
{
  if(sscanf(input, "%1d%1d%1d%1d", buf, buf+1, buf+2, buf+3) != 4)
    return 0;
  else
    {
      return unique(buf, 4);
    }
}

int verify(const int * num, int *xA, int *yB)
{
  int x = 0;
  int y = 0;
  int i;
  int j;
  /** xA **/
  for(i=0; i<4; i++)
    {
      if(num[i] == number[i])
        x++;
      else
        continue;
    }
  /** yB **/
  for(i=0; i<4; i++)
    for(j=0; j < 4; j++)
      {
        if(num[i] == number[j])
          y++;
      }
  *xA = x;
  *yB = y-x;
  
  return x;      
}

int main()
{  
  char buf[256];
  int num[4];
  int xa;
  int yb;
  int times;
  srand(time(NULL));
  init();
  puts("Game beginned. Please input your number");

 
  
  times = 0;
  while(times < 7)
    {
      if(times != 0)
        puts("Continue guess!");
      scanf("%4s", buf);
      fflush(stdin);
      if(get_number(buf, num) == 0)
        {
          puts("Input Error! The number you input must be unique in 4 index");          
        }
      else
        {
          if(verify(num, &xa, &yb) == 4)
            break;
          printf("%2d A%2d B\n", xa, yb);
        }
      times++;    
    }
  if(times = 7)
    {
      puts("====== Game Over ======");
      printf("The number is:\t");
      output(number, 4);
      puts("\n====== Thanks for playing it ======");
    }
  else
    {
      puts("****** Good Job ******");
      printf("The number is just:\t");
      output(number, 4);
      puts("\n****** Thanks for playing it ******");
     }

   return 0;
}


附带一个截图吧,这游戏我不会玩。。。。
图片附件: 游客没有浏览图片的权限,请 登录注册

C++ 用无参数构造函数生成对象时候请勿在构造函数后添加无用的那一对括号,否则有可能会被当成函数声明而忽略,嗯,栈上构建的时候就是这样。
2011-09-19 10:44
tisyang
Rank: 8Rank: 8
等 级:蝙蝠侠
帖 子:132
专家分:737
注 册:2011-5-7
收藏
得分:0 
上面代码有个地方有个小错误
if(times = 7)
    {
      puts("====== Game Over ======");
      printf("The number is:\t");
      output(number, 4);
      puts("\n====== Thanks for playing it ======");
    }

应该是
if(times == 7)

注意一下即可。
不想编辑贴过的帖子。。。。。

C++ 用无参数构造函数生成对象时候请勿在构造函数后添加无用的那一对括号,否则有可能会被当成函数声明而忽略,嗯,栈上构建的时候就是这样。
2011-09-19 10:50
tisyang
Rank: 8Rank: 8
等 级:蝙蝠侠
帖 子:132
专家分:737
注 册:2011-5-7
收藏
得分:0 
给一个修正过并小修改逻辑的代码吧
1 给用户还有多少次机会的提示
2 输入错误不再减少机会


程序代码:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int number[4];

void init()
{
  int i = 0;
  int temp;

  int flag[10]={0};

  while( i < 4)
    {
      temp = rand()%10;
      if( flag[temp] != 0)
        continue;
      number[i] = temp;
      flag[temp] = 1;
      i++;
    }
  
}
void output(const int *buf, int n)
{
  int i;
  for(i = 0; i < n;  i++)
    printf("%d", buf[i]);
}

int unique(const int *num, int n)
{
  int i = 0;
  int j;
  while(i<n)
    {
      for(j=i+1;j<n;j++)
        {
          if(num[i] == num[j])
            return 0;
          else
            continue;
        }   
      i++;
    }
  return 1;
}
int get_number(const char * input, int * buf)
{
  if(sscanf(input, "%1d%1d%1d%1d", buf, buf+1, buf+2, buf+3) != 4)
    return 0;
  else
    {
      return unique(buf, 4);
    }
}

int verify(const int * num, int *xA, int *yB)
{
  int x = 0;
  int y = 0;
  int i;
  int j;
  /** xA **/
  for(i=0; i<4; i++)
    {
      if(num[i] == number[i])
        x++;
      else
        continue;
    }
  /** yB **/
  for(i=0; i<4; i++)
    for(j=0; j < 4; j++)
      {
        if(num[i] == number[j])
          y++;
      }
  *xA = x;
  *yB = y-x;
  
  return x;      
}

int main()
{  
  char buf[256];
  int num[4];
  int xa;
  int yb;
  int times;
  srand(time(NULL));
  init();
  /* for test
   number[0] = 1;
   number[1] = 2;
   number[2] = 3;
   number[3] = 4;
*/
  puts("Game beginned. Please input your number");

 
  
  times = 0;
  while(times < 7)
    {
      printf("You have %d chance left.\n", 7 - times);
      if(times != 0)
        puts("Continue guess!");
      scanf("%4s", buf);
      fflush(stdin);
      if(get_number(buf, num) == 0)
        {
          puts("Input Error! The number you input must be unique in 4 index");     
          continue;
        }
      else
        {
          if(verify(num, &xa, &yb) == 4)
            break;
          printf("%2d A%2d B\n", xa, yb);
        }
      times++;    
    }
  if(times == 7)
    {
      puts("====== Game Over ======");
      printf("The number is:\t");
      output(number, 4);
      puts("\n====== Thanks for playing it ======");
    }
  else
    {
      puts("****** Good Job ******");
      printf("The number is just:\t");
      output(number, 4);
      puts("\n****** Thanks for playing it ******");
     }

   return 0;
}


C++ 用无参数构造函数生成对象时候请勿在构造函数后添加无用的那一对括号,否则有可能会被当成函数声明而忽略,嗯,栈上构建的时候就是这样。
2011-09-19 10:59
czsbc
Rank: 10Rank: 10Rank: 10
等 级:青峰侠
帖 子:469
专家分:1700
注 册:2008-12-13
收藏
得分:10 
路过,贴代码,写得很烂:
程序代码:
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
int main()
{
    int a[4]={0},b[4]={0},k=7,i,j,x,y;
    char input[5];
    char c;
    srand((unsigned)time(0));
restart:
    for(i=0;i<4;i++)
    {
        a[i]=rand()%10;
        for(j=0;j<i;j++)
        {
            if(a[i]==a[j])
            {
                i--;
                break;
            }
        }
    }
    while(k>0)
    {
        x=0;y=0;
        while(1)
        {
reInput:    printf("请输入4个数字:");
            input[4]=1;
            scanf("%s",input);
            for(i=0;i<4;i++)
            {
                for(j=i+1;j<4;j++)
                {
                    if(input[j]==input[i]||input[4])
                    {
                        printf("数字重复或不是4个数\n");
                        goto reInput;
                    }
                }
            }
            if(i==4)
                break;
        }
        for(i=0;i<4;i++)
            b[i]=input[i]-'0';
        if(a[0]==b[0]&&a[1]==b[1]&&a[2]==b[2]&&a[3]==b[3])
        {
            printf("你赢了,用了%d次\n",7-k+1);
            break;
        }
        for(i=0;i<4;i++)
            if(a[i]==b[i])
                x++;
        for(i=0;i<4;i++)
        {
            for(j=0;j<4;j++)
            {
                if(j!=i)
                {
                    if(b[j]==a[i])
                        y++;
                }
            }
        }
        printf("%s    %dA%dB\n",input,x,y);
        k--;
    }
    if(k==0)
    {
        printf("你输了,正确的数字为: ");
        for(i=0;i<4;i++)
            printf("%d",a[i]);
        printf("\n");
    }
    flushall();
    printf("是否继续?(Y/N):");
    scanf("%c",&c);
    if(c=='Y'||c=='y')
    {
        k=7;
        goto restart;
    }
    return 0;
}



[ 本帖最后由 czsbc 于 2011-9-19 15:14 编辑 ]
2011-09-19 12:37
lz1091914999
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:四川
等 级:贵宾
威 望:37
帖 子:2011
专家分:5959
注 册:2010-11-1
收藏
得分:10 
程序代码:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>

int test(char* r)
{
    return r[0] != r[1] && r[0] != r[2] && r[0] != r[3] &&
           r[1] != r[2] && r[1] != r[3] &&
           r[2] != r[3];
}

char* random(char* r)
{
    int tmp;
   
    srand((unsigned)time(NULL));
    do {
        tmp = rand() % 10000;
        r[0] = tmp / 1000 % 10 + '0';
        r[1] = tmp / 100 % 10 + '0';
        r[2] = tmp / 10 % 10 + '0';
        r[3] = tmp % 10 + '0';
        r[4] = '\0';
    } while (!test(r));
    return r;
}

int equals(char* r, char* n)
{
    int x = 0, y = 0;
    int i, j;
   
    for (i = 0; i < 4; i++)
        if (r[i] == n[i])
            x++;
   
    for (i = 0; i < 4; i++)
        for (j = 0; j < 4; j++)
            if (n[i] == r[j])
                if (n[j] != r[j])
                    y++;
   
    printf("%d%c%d%c\n", x, 'A', y, 'B');
    if (x == 4)
        printf("Congratulations!\nThe number is: %s\n", r);
    else
        printf("Try again!\n");
    return x == 4;
}

int guess(char* r, char* n)
{
    int number;
   
    printf("Enter a 4-digits number to guess: \n");
    scanf("%d", &number);
    n[0] = number / 1000 % 10 + '0';
    n[1] = number / 100 % 10 + '0';
    n[2] = number / 10 % 10 + '0';
    n[3] = number % 10 + '0';
    n[4] = '\0';
    return equals(r, n);
}

int main(void)
{
    char r[5];
    char n[5];
   
    random(r);
    while (!guess(r, n))
        ;
}

My life is brilliant
2011-09-19 12:37
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
首先感谢三位的热心参与,大家的代码都实现了这个游戏。我的初衷原本的只有两点,一是4位不同数字随机数的生成,二是按照游戏规则生成提示。各位的代码不仅完成了以上两点,而且都加入了对输入数据的容错处理,而且手段各不相同,呵呵,读大家的代码非常有意思。

不介意的话,我想点评一下各位的代码,有失偏颇之处还请见谅。

tisyang
代码风格很好,功能模块的划分很清晰,模块间的耦合度很低,这是一个好习惯,对将来实施大型项目很有帮助。
随机数的生成通过标志位来保证各位互不相同。

czsbc
君成功的实现了这个游戏,其中对输入数据的容错处理很有意思,用字符串的结束标志兼作输入格式判断的条件,很别出心裁。不过这也同样带来了数组越界的风险,建议实际开发中别这种方法。
君让我再次见到久违的goto跳转,不知是喜是惊。这个游戏很小,这么跳转问题不大。代码再长点,跳转点再多点,就要被你绕进去了。微软VS附带的一个工具可以重新整理程序指令,以实现防止软件被逆向破解。它用的方法其实就是插入大量的跳转来把破解者的脑子绕成一团浆糊。各种教科书都极力反对使用goto语句,是有它的道理的。也建议君日后尽量不要再用。

lz109194999
李志同学的书邮到了么?这几天好像没看到你的贴子。
代码很清爽。没有做输入数据的容错处理,这无所谓,这不是我贴子的考察重点。在我所做的那个示例中输入数据格式的判断也是直接放在事件响应函数里的,毕竟这是个很小的程序。
一点小小的不足是君将输出放在了功能模块里。其实就这一贴的要求来说也没什么,但不利于将来的修改扩展。比如有一天你想重构成一个视窗界面时。目前软件开发的一个成熟的模型是三层架构,君的代码就是将表示层与业务逻辑层混在了一起。


以上仅是个人的观点,评析比较主观,各位有不同意见我们一起交流,不影响我承诺的送分原则。
一个有趣的现象我也想问一下,各位都不约而同的将x和y值分开计算,是大家一开始就这么想的么?
这个很有意思,我在想这是不是思维习惯的问题。
这本身没有什么性能差异,大家不要介意。只是我从来没这么想过,这倒是也为我打开了思路。
我一直是合在一起算的
for(i = 0; i < 4; i++)
for(j = 0; j < 4; j++)
  if(rndNum[i] == inputNum[j])
    if(i == j) x++; else y++;

最后想问一下大家对这个游戏的感觉如何?有没有玩一玩自己写的游戏?
当年经常在上我不喜欢的课时整节整地拿着朋友的文曲星玩这个游戏,呵呵。

重剑无锋,大巧不工
2011-09-19 18:05
a5952036
Rank: 2
等 级:论坛游民
帖 子:65
专家分:94
注 册:2011-9-7
收藏
得分:0 
好高深哦!
2011-09-19 18:27
lz1091914999
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:四川
等 级:贵宾
威 望:37
帖 子:2011
专家分:5959
注 册:2010-11-1
收藏
得分:0 
程序代码:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>

#define DIG    4

typedef struct ResultTag {
    unsigned x;
    unsigned y;
} Result;

int test(char* r)
{
    return r[0] != r[1] && r[0] != r[2] && r[0] != r[3] &&
           r[1] != r[2] && r[1] != r[3] &&
           r[2] != r[3];
}

char* random(char* r)
{
    const char* const cp1 = r + DIG;
    char*             cp2 = r;
  
    srand((unsigned)time(NULL));
    do
        while (cp2 < cp1)
            *cp2++ = rand() % 10 + '0';
    while (!test(cp2 = r));
    r[DIG] = '\0';
    return r;
}

Result* guess(Result* res, const char* r, const char* g)
{
    int  i, j;
   
    for (i = 0; i < DIG; i++)
        for (j = 0; j < DIG; j++)
            if (g[i] == r[j])
                if (i == j)
                    res->x++;
                else
                    res->y++;
   
    return res;
}

char* input(char* g)
{
    unsigned tmp;
   
    do {
        printf("Please Enter a 4-digits number:\n");
        scanf("%u", &tmp);
    } while (tmp >= 10000);
   
    sprintf(g, "%u", tmp);
    return g;
}

Result* init(Result* res)
{
    res->x = 0;
    res->y = 0;
    return res;
}

int main(void)
{
    char   r[DIG + 1];
    char   g[DIG + 1];
    Result res;
   
    random(r);

    while (guess(init(&res), r, input(g))->x < 4) {
        printf("%d%c%d%c\n", res.x, 'A', res.y, 'B');
        printf("Try again!\n\n");
    }
    printf("Congratulations!\nThe number is: %s\n", r);
}
/*
    那本书拿到手之后才发现我完全看不懂,而且只适合于教学初等数学的老师或有高等数学基础的人看,现在才发现自己学初等数是多么难,
    难在不好找书啊,现在把代码改了一下,不知道是否要比刚才发的要好一点,现在正在看Thinking in C++呢,而且学校上网不容易,所以
    很少来论坛了,不知大侠能否告知,自学数学应该怎样起步?
*/


[ 本帖最后由 lz1091914999 于 2011-9-20 17:41 编辑 ]

My life is brilliant
2011-09-19 21:10
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
回复 9楼 lz1091914999
呵呵,你原来那段就很不错,我只是提个以后编码的建议。
数学这一块,没法跳着学的。我倒觉得你先不妨再复习一遍初中的数学课本,然后看看高中的数学课本,挑着做做课后习题。
一步一步来吧。既然你在学校,那就多和老师交流。反正你是付了学费的,回答你的问题是他的责任。

重剑无锋,大巧不工
2011-09-19 21:20
快速回复:牛刀小试 之 猜数字
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.036424 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved