基本流程:
a.初始化4个不重复的数字
b.玩家有8次机会进行猜测。数字正确位置不正确记为b,数字正确且位置正确记为a
如:要猜测的数字为1234,则1563的结果是1A1B,1数字正确且位置正确,3数字正确位置不正确
8次机会内猜测出数字,即得出4A0B为胜利,否则失败
概述:
这个游戏实在不复杂,要点无非一:产生不重复的随机数;二:如何验证玩家输入的数字,进行比较。第一点另写一文描述。
验证数字的最笨的方法是,做一个双重循环,最多比较4*4次就搞定了。不过太笨的方法写了没什么意思,就琢磨了一个稍微聪明点的方法,只要4次便搞定:
原始数据为source[4],产生一个数comSource,二进制表示形式利用10位,其中最左边表示9,最右边表示0,则comSource的二进制形式中就含有4个1,分处不同位置,表示含有哪一个数字,如1234就表示为...0000011110。玩家输入的数字为input[4],也转换为类似的东西,为2就表示为....100,省略的均为0。这样,进行比较时,comSource&input[i]>0就表示玩家猜测的数字存在于原始数字中,然后比较source[i]与input[i]是否相等,就得出了位置是否正确的结果。
进行转换的方法是对1做移位操作,即:comSource|= (1<<source[i])
本程序实际就是为此算法而作~~
程序结构与源码:
分为3个文件:main.cpp, guess.h, guess.cpp。设想是做一个封装好的与界面无关的类,但可惜考虑界面问题太麻烦,简单起见就直接写成consle形式的东西了。若更改的话则需要把guess类中的input和display函数重写。
a)main.cpp:
#include <iostream>
#include <stdlib.h>
#include "guess.h"
int main()
{
Guess guess;
guess.Run();
system("PAUSE");
return 0;
}
这个没什么好说的,在dev-cpp下调试通过。有个想法是把Guess写成个静态类,似乎更合理些,但没什么必要就算了。
b)guess.h
// Class automatically generated by Dev-C++ New Class wizard
#ifndef GUESS_H
#define GUESS_H
// No description
class Guess
{
public:
// class constructor
Guess();
// class destructor
~Guess();
// game runner
void Run();
// initialize the game
void Initialize();
// No description
bool WannaPlay();
// in game
void InGame();
// get player's input
void GetInput();
// display guess result
void Display(int t=-1);
// game result
void DisplayResult();
private:
// the source data that generated for each game
int source[4];
// the data that player input for each turn.
int input[8][4];
// the guess result for each turn.first indecates A,the other for B
int result[8][2];
// bit type if souce , for comparition
int comSource;
// bit type of input , for comparition
int comInput[4];
// current turn of the game
int turn;
// stay in game or not
bool quit;
};
#endif // GUESS_H
每一个变量的注释都写得比较清楚了,函数的诠释放在后面
c)guess.cpp
先解释每个函数,然后帖全部的代码。
Run:游戏控制循环,这控制玩家是否进行下一个游戏,而非游戏的内部流程
Initialize:初始化程序。初始化原始数字,以及其他类成员的数据
wannaPlay:询问玩家是否继续游戏,基于console的
InGame:游戏内部控制,即控制一个游戏的内部流程
GetInput:获取玩家的输入的猜测数字,基于console
Display:输出指定轮次的猜测结果
DisplayResult:输出游戏结果
构造和析构函数都是空的,因为游戏可以重复进行,所以数据初始化代码放在Initialize中,而非构造函数中。
void Guess::Run()
{
quit = false;
//game loop
while(!quit)
{
Initialize();//initialize game;
if(!WannaPlay())
{
//player exists:
cout<<"Thank you for playing!"<<endl;
quit = true;
}
else
InGame();//play in game
}
}
没什么好说的。
void Guess::Initialize()
{
int i,j;
srand((unsigned int)time(NULL)); //初始化随机数产生器
for(i=0;i<4;i++) //初始化游戏中需要的数据
comInput[i]=0;
for(j=0;j<8;j++)
{
for(i=0;i<4;i++)
input[j][i] = 0;
result[j][0] = 0;
result[j][1] = 0;
}
comSource = 0;
turn = -1;
//init source
int numbers[10]; //存放0-9十个数字
for(i=0;i<10;i++)
numbers[i] = i+1;
for(i=0;i<4;i++) //随机抽取4个不重复的数字放在source里
{
int rander = rand()%(10-i);
source[i] = numbers[rander];
numbers[rander] = numbers[10-i-1];
}
}
结束初始化
bool Guess::WannaPlay()
{
while(true)
{
cout<<"Do you wanna start a game? (Y//N)"<<endl;
char answer;
try
{
cin>>answer;
switch(answer)
{
case 'Y':
case 'y':
return true;
case 'N':
case 'n':
return false;
default:
cout<<"Please answer 'y' or 'n'!"<<endl;
break;
}
}
catch(...)
{
cout<<"Unknown error..."<<endl;
cout<<"Please answer 'y' or 'n'!"<<endl;
}
}
}
没什么好说的
void Guess::InGame() //游戏中
{
int i,j;
for(i=0;i<4;i++) //建立comSource
comSource = comSource|(1<<source[i]);
while(turn<7) //循环
{
turn++;
GetInput(); //得到玩家输入的数据
if(quit)
return;
for(i=0;i<4;i++)//init comInput to bit value for comparition
{
comInput[i] = 1<<input[turn][i];
}
for(i=0;i<4;i++)
{
if((comInput[i]& comSource) >0)//the input[i] exists in source
{
if(input[turn][i] == source[i])//the location is right
result[turn][0]++;
else//only the value is right;
result[turn][1]++;
}
}
if(result[turn][0]>=4) //若猜测成功,则游戏结束
break;
Display(turn); //输出本轮的猜测情况
}
DisplayResult(); //输出游戏情况
}
结束
void Guess::GetInput()
{
string inString;
int check,temp,comTemp,i;
char c;
while(true)
{
cout<<"Current turn:"<<turn+1<<endl;
cout<<"please input your guess number:"<<endl;
cout<<"(D to display your guess history, Q to quit game)"<<endl;
cin>>inString;
c = inString[0];
switch(c)
{
case 'D':
case 'd':
Display();
break;
case 'Q':
case 'q':
cout<<"Thank you for playing this game!"<<endl;
quit = true;
return;
default:
if((c-'0')<0 || (c-'9')>0)
{
cout<<"Undefined input..."<<endl;
break;
}
/*
if(inString.Length != 4)
{
cout<<"Please input 4 numbers"<<endl;
break;
}*/
check = 0;
for(i=0;i<4;i++)
{
temp = inString[i] - '0';
comTemp = 1<<temp;
if(check&comTemp>0)//check if there are same guess
{
cout<<"The input numbers should be different to each other!"<<endl;
break;
}
check &= comTemp;
input[turn][i] = temp;
}
if(i>=4)
return;
}
}
}
没什么说的,有些异常没处理
void Guess::Display(int t)
{
if(t>=0)
{
cout<<result[turn][0]<<"A"<<result[turn][1]<<"B"<<endl;
return;
}
for(int i=0;i<turn;i++)
{
cout<<input[i][0]<<input[i][1]<<input[i][2]<<input[i][3]<<"/t"
<<result[i][0]<<"A"<<result[i][1]<<"B"<<endl;
}
}
参数为+输出本轮的结果,否则输出目前为止的历史记录
void Guess::DisplayResult()
{
if(turn<8)
{
cout<<"You Win!"<<endl;
cout<<"you take "<<++turn<<" turns"<<endl;
}
else
cout<<"You lose..."<<endl;
cout<<"Result:"<<source[0]<<source[1]<<source[2]<<source[3]<<endl;
cout<<"Your guess history:"<<endl;
Display();
}
游戏结果
文件头再加上
#include "guess.h" // class's header file
#include <iostream>
#include <stdlib.h>
#include <string>
就搞定了
结论:
写文档确实比写程序累哇~~~~
程序里所有的中文注释都是后来加的。
一个不成熟的程序,不过可以玩了~~呵呵