浪迹天涯

唯有努力...
努力....再努力...

人机猜数游戏

请人想一个四位的整数,计算机来猜,人给计算机提示信息,最终看计算机用几次猜出一个人“想”的数。请编程实现。

问题分析
解决这类问题时,计算机的思考过程不可能象人一样具完备的推理能力,关键在于要将推理和判断的过程变成一种机械的过程,找出相应的规则,否则计算机难以完成推理工作。
基于对问题的分析和理解,将问题进行简化,求解分为两个步聚来完成:首先确定四位数字的组成,然后再确定四位数字的排列顺序。可以列出如下规则:
1)产生四位数字的全部排列产生四位数字的全部排列。
2)生成随机数,根据,根据人输入的正确数字及正确位置的数目,进行刷选。
3)再剩下的结果中,生成随机数,重复步骤2,直至找到。

GetNextGuess()函数算法不知该如何理解?
我觉得这个函数算法不好,没有充分利用先前的猜数以及结果进行下一次的猜数。

程序代码:
#include <iostream>
#include <time.h>
#include <string>
#include <list>
#include <limits>

using namespace std;
list<string> numList;

void   Initialize();
string RanddomNum();
string GetNextGuess();
int    CountN(const string &guess, const string &str);
int    CountP(const string &guess, const string &str);


int main()
{
 Initialize();   // 初始化
 string guess = RanddomNum(); // 第1回合随机猜数
 int n, p;    // 分别表示有几个数字猜对,有几个数字位置也对
 
 while (1)
 {
  cout << guess << endl;
  cin >> n >> p;
  if (n == 4 && p == 4) // 猜中
   break;
  list<string>::iterator it;
  for (it = numList.begin();it != numList.end();)
  {
   if (CountN(guess, *it) != n) // 如果没有n个数字对
   {
    it = numList.erase(it);  // 不可能是被猜数,筛掉
    continue;
   }
   if (CountP(guess, *it) != p) // 如果没有p个数字位置对
   {
    it = numList.erase(it);  // 不可能是被猜数,筛掉
    continue;
   }
   ++it;
  }
  if (numList.empty()) // 没有候选数了,人欺骗计算机
  {
   cout << 0 << endl;
   break;
  }
  guess = GetNextGuess();
 }
 return 0;
}

void Initialize()
{
 char buf[5] = {0};
 for (int i = '1'; i <= '9'; i++)
  for (int j = '0'; j <= '9'; j++)
   for (int k = '0'; k <= '9'; k++)
    for (int l = '0'; l <= '9'; l++)
    {
     buf[0] = i;
     buf[1] = j;
     buf[2] = k;
     buf[3] = l;
     numList.push_back(buf);
    }
}

string RanddomNum()
{
 srand(time(NULL));
 int i = rand() % 9000 + 1000;
 char buf[5] = {0};
 sprintf(buf, "%d", i);
 return buf;
}

int CountN(const string &guess, const string &num)
{
 string s = num;  // 复制num,用于下面避免重复匹配的操作
 int count = 0;
 for (int i = 0; i < 4; i++) // 对guess中每一个数字
 {
  string::size_type pos = s.find(guess[i]);
  if (pos != string::npos)
  {
   count++;
   s[pos] = 'x';  // 为避免重复匹配,将它替换为字符’x’
  }
 }
 return count;
}


int CountP(const string &guess, const string &str)
{
 int count = 0;
 for (int i = 0; i < 4; i++)
  count += (guess[i] == str[i]);
 return count;
}

string GetNextGuess()
{
 int min = numeric_limits<int>::max();
 string guess;   // 猜这个数
 list<string>::iterator it,it2;
 for (it = numList.begin();it != numList.end(); ++it)
 {
  int a[5][5] = {0};
  for (it2 = numList.begin();it2 != numList.end(); ++it2)
  {
   int x = CountN(*it, *it2);
   if (x == 0)
    a[0][0]++;    // 如果n=0,p一定=0
   else
    a[x][CountP(*it, *it2)]++;
  }
  int sum = 0;
  for (int i = 0; i < 5; i++)
   for (int j = 0; j <=i; j++) // 位置对的数字个数不会超过猜对的数字个数
    sum += a[i][j] * a[i][j];
  if (sum < min)
  {
   sum = min;
   guess = *it;
  }
 }
 return guess;
}

posted on 2008-01-04 09:22 浪迹天涯 阅读(656) 评论(0)  编辑 收藏 引用 所属分类: C++


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2008年1月>
303112345
6789101112
13141516171819
20212223242526
272829303112
3456789

导航

统计

常用链接

留言簿(22)

随笔分类(30)

随笔档案(29)

文章分类

搜索

积分与排名

最新评论

阅读排行榜

评论排行榜