题目要求:
人和计算机做猜数游戏。人默想一个四位数,由计算机来猜。计算机将所猜的数显示到屏幕上,并问两个问题:一、有几个数字猜对了;二、猜对的数字中有几个位置也对了。人通过键盘来回答这两个问题。计算机一次又一次地猜,直到猜对为止。
为了简化输入输出,计算机每次输出一个四位数,然后人输入两个用空格分开的数,分别表示有几个数字猜对,有几个数字位置也对。右图是某次猜数过程:人默想的数是3422,奇数行是计算机猜的数,偶数行是人输入的信息。在这个例子中,计算机第五次猜中了数,在人输入4 4后程序结束退出。
请你写一个这样的猜数程序,看看你所想的数能在几次后被程序猜中。如果在猜数过程中,计算机发现人故意欺骗,输入了不正确的信息,那么程序将输出0然后直接退出。
#include #include #include#include #include #includeusing namespace std; listnumList; void Initialize(); string RanddomNum(); int CountN(const string &guess, const string &str); int CountP(const string &guess, const string &str); string GetNextGuess(); int main() { Initialize(); // 初始化 string guess = "6789";//RanddomNum(); // 第1回合随机猜数 int n, p; // 分别表示有几个数字猜对,有几个数字位置也对 while (1) { cout << guess << endl; cin >> n >> p; if (n == 4 && p == 4) // 猜中 break; for (list::iterator 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::max(); string guess; // 猜这个数 for (list::iterator it = numList.begin(); it != numList.end(); ++it) { int a[5][5] = {0}; for (list::iterator 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; }