24点游戏7节课--第4节-引入扑克牌发牌出数

前三节:

 

第1节-游戏介绍与基本算法   http://student.csdn.net/space.php?uid=112600&do=blog&id=34066

第2节-24点计算处理 http://student.csdn.net/space.php?uid=112600&do=blog&id=34327

第3节-格式化结果表达式 http://student.csdn.net/space.php?uid=112600&do=blog&id=35873

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

第4节-引入扑克牌发牌出数

 24点游戏中,扑克只是用作提供数值的道具,其中花色用不上,大小鬼也不需要。数值限在1~13范围内。

我们用一个int数组来表达52张牌。内部存值为0~51. 要转成牌值时,公式是: N % 13 + 1。 %是求余数操作符。

比如 :0 -> 0 %13 + 1 = 1。所以在程序中,0表示牌值为1的牌。0 除以 13,余数是0,这个是小学算术。

再如: 2 -> 2 % 13 + 1 = 3。所以2表示牌值为3的牌。

再如: 15-> 15 % 13 + 1 = 3。 所15也表示牌值是3的牌。(只是花色不同,花色可以用N/13表示,但在此无意义)

 

有这些知识,就可以写扑克牌的类了,新建poker.h 和 poer.cpp加入项目。

poker.h 

Code:
  1. #ifndef POKER_H_INCLUDED  
  2. #define POKER_H_INCLUDED  
  3.   
  4. struct Poker  
  5. {  
  6. public:  
  7.     Poker();  
  8.       
  9.     void Shuffle(); //洗牌  
  10.     bool Deal(int card[4]); //发牌,如果不够4张,返回false  
  11.       
  12. private:  
  13.     int _cards[52];  
  14.     int _index;  
  15. };  
  16.  
  17. #endif // POKER_H_INCLUDED  

_cards[52]用来存放0~51的值,表示扑克牌。_index是发牌时需要的,表示当前发到第几张牌。

主要操作就两:一个洗牌,一个发牌。

poker.cpp

Code:
  1. #include "poker.h"  
  2.  
  3. #include <cstdlib>  
  4. #include <ctime>  
  5. #include <iostream>  
  6.   
  7. using namespace std;  
  8.   
  9. Poker::Poker()  
  10.     : _index(0)  
  11. {  
  12.     for (int i=0; i<52; _cards[i] = i, ++i);  
  13. }  
  14.   
  15. void Poker::Shuffle() //洗牌  
  16. {  
  17.     _index = 0;  
  18.     srand(time(0));  
  19.  
  20.     #define SIMPLE_SWAP_int(a,b) do {int t = a; a=b; b=t;} while(0)  
  21.        
  22.     for (int i=52, c=1; i>0; --i,++c)  
  23.     {  
  24.         int ri = rand() % i;  
  25.         SIMPLE_SWAP_int(_cards[52-c], _cards[ri]);  
  26.     }  
  27. }  
  28.   
  29. bool Poker::Deal(int card[4]) //发牌  
  30. {  
  31.     if (_index + 4 > 52)  
  32.         return false;  
  33.           
  34.     for (int i=0; i<4; ++i, ++_index)  
  35.     {  
  36.         card[i] = _cards[_index];  
  37.     }  
  38.       
  39.     return true;  
  40. }  

构造函数中,让牌值是顺的,其实是为了确保_pokers[]里放的都是正确的值。

洗牌算法很简单 ,简单说下:

step1 :从前面51张牌中,随机取一张,和第52张牌交换。

step2: 从前面50张牌中,再随机取一张,和第51张牌交换。

重复,即:从前面1~N牌中,随机取出一张,和第N+1张牌交换。直到第1张。

 

发牌就没有什么算法了:从第_index张开始,取出4张。同时_index前进4。

接下来我们改改一main函数。

main.cpp

Code:
  1. #include <iostream>  
  2. #include <sstream> //for stringstream  
  3.  
  4. #include "calc_24.h"  
  5. #include "exp_getter.h"  
  6.  
  7. #include "poker.h"  
  8.   
  9. using namespace std;  
  10.   
  11. int main()  
  12. {         
  13.     int num[4];  
  14.       
  15.     Poker poker;  
  16.     poker.Shuffle();  
  17.       
  18.     while(poker.Deal(num))  
  19.     {  
  20.         cout << "/n当前牌为: ";  
  21.           
  22.         for (int i=0; i<4; ++i)  
  23.         {  
  24.             num[i] = num[i] % 13 +1;  
  25.             cout << num[i] << ", ";              
  26.         }  
  27.               
  28.         cout << "请思考!" << std::endl;  
  29.         cout << "按任意键查看本轮答案." << std::endl;  
  30.         cin.get();  
  31.               
  32.         if (!calc_24(num))  
  33.         {  
  34.             cout << "查无答案" << endl;  
  35.         }  
  36.     }  
  37.       
  38.     return 0;  
  39. }  

它会先出4个数,然后等待我们按下任意键,后给出答案,在此期间,我们可以思考那4个数如何计算成24了。还不能接受我们录入答案(并判断正误),更没有提供人机对抗……那是后两节课的内容了。

不管怎样,它看起还是挺智能的,我们完全可以拿来复习及锻炼一下小学所学的四则运算能力了……嗯,我这就叫来我女儿,然后出题让她想。

这是运行中的一个输出示例:

 

当前牌为: 12, 6, 1, 13, 请思考!

按任意键查看本轮答案.


(13-1)*12/6


当前牌为: 5, 3, 9, 2, 请思考!

按任键查看本轮答案.


(5*9+3)/2


当前牌为: 8, 7, 8, 13, 请思考!

按任键查看本轮答案.

-------------------------------------------------------------------------------

 如果您想与我交流,请点击如下链接成为我的好友:
 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南郁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值