一、游戏介绍
猜数字(又称 Bulls and Cows )是一种古老的的密码破译类益智类小游戏,起源于20世纪中期,一般由两个人或多人玩,也可以由一个人和电脑玩。一方出数字,一方猜。出数字的人要想好一个没有重复数字的4个数,不能让猜的人知道。猜的人就可以开始猜。每猜一个数字,出数者就要根据这个数字给出几A几B,其中A前面的数字表示位置正确的数的个数,而B前的数字表示数字正确而位置不对的数的个数。如正确答案为 5234,而猜的人猜 5346,则是 1A2B,其中有一个5的位置对了,记为1A,而3和4这两个数字对了,而位置没对,因此记为 2B,合起来就是 1A2B。接着猜的人再根据出题者的几A几B继续猜,直到猜中(即 4A0B)为止。
二、算法
程序首先生成四个互不相同的位于0-9之间的随机数,根据输入的数据,将两者进行对比,给出A和B的值。
程序使用std::array<uchar,4>
来存储这四个数字,并且定义一个结构体Result
来存储A和B的值。将这些数据及相应的操作整合到GDigit
类中
三、程序代码
1、GDigit.h
该文件包含结构体Result
、GDigit
类及其它必要的数据结构的定义。
/* the definition of GDigit class
* writen by Liangjin Song on 20200122
*/
#ifndef GDIGIT_H
#define GDIGIT_H
#include <array>
using uchar=unsigned char;
using Digit=std::array<uchar,4>;
struct Result{
uchar A;
uchar B;
};
class GDigit
{
private:
Digit digit;
public:
GDigit()=default;
~GDigit()=default;
public:
// initial the digits
void initial();
// check if the four numbers are different from each other
bool different(Digit& guess) const;
// check the result
Result check(Digit& guess) const;
// get the digit
const Digit& get() const {return digit;}
bool finish(Digit& guess) const {return digit[0]==guess[0] && digit[1]==guess[1] && digit[2]==guess[2] && digit[3]==guess[3];}
};
#endif // GDIGIT_H
2、GDigit.cpp
该文件包含GDigit
类的具体实现。
/* the definition of GDigit class
* writen by Liangjin Song on 20200122
*/
#include "GDigit.h"
#include <random>
#include <ctime>
void GDigit::initial()
{
// initialize four numbers, and
// make the four numbers different from each other.
using engine=std::default_random_engine;
using uniform=std::uniform_int_distribution<int>;
// the first number
engine rnd((unsigned)time(NULL));
uniform dis(0,9);
engine rndp((unsigned)time(NULL));
uniform disp(10,20);
int i, loop=disp(rndp);
for(i=0;i<loop;++i){
dis(rnd);
}
digit[0]=dis(rnd);
// the second number
do{
digit[1]=dis(rnd);
}while(digit[1]==digit[0]);
// the third number
do{
digit[2]=dis(rnd);
}while(digit[2]==digit[0] || digit[2]==digit[1]);
// the forth number
do{
digit[3]=dis(rnd);
}while(digit[3]==digit[0] || digit[3]==digit[1] || digit[3]==digit[2]);
}
bool GDigit::different(Digit& guess) const
{
// check if the four numbers are different from each other
bool same;
same=guess[0]==guess[1] || guess[0]==guess[2] || guess[0]==guess[3];
same=same || guess[1]==guess[2] || guess[1]==guess[3];
same=same || guess[2]==guess[3];
return !same;
}
Result GDigit::check(Digit& guess) const
{
// check the result
Result res;
res.A=0;
res.B=0;
uchar i,j;
for(i=0; i<4; ++i){
for(j=0; j<4; ++j){
if(guess[j]==digit[i]){
if(i==j){
++res.A;
}
else{
++res.B;
}
}
}
}
return res;
}
3、main.cpp
C++控制台程序的main函数。
/* main function
* writen by Liangjin Song on 20200122
*/
#include "GDigit.h"
#include <iostream>
using namespace std;
int main()
{
GDigit gdigit;
gdigit.initial();
Digit guess;
Result res;
do{
do{
cout<<"Please input four unique digits:"<<endl;
cin>>guess[0]>>guess[1]>>guess[2]>>guess[3];
for(auto &i : guess){
i-=0x30;
}
}while(!gdigit.different(guess));
res=gdigit.check(guess);
cout<<static_cast<int>(res.A)<<"A"<<static_cast<int>(res.B)<<"B"<<endl;
}while(!gdigit.finish(guess));
cout<<endl;
return 0;
}
四、运行结果
控制台下的运行效果如下。
五、图形界面
使用MFC制作图形界面,代码链接为:猜数字游戏MFC源代码,其运行效果如下图。
六、注意
程序使用了C++11特性,编译器需支持C++11。