猜数字游戏的基本实现

基本流程:
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>
就搞定了

结论:
写文档确实比写程序累哇~~~~
程序里所有的中文注释都是后来加的。

一个不成熟的程序,不过可以玩了~~呵呵

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值