如何设计21点游戏

21点游戏的设计能够充分体现C语言结构化程序设计的思想,如果你是C语言的初学者,本文对你一定有帮助.

      21点游戏的规则如下:扑克牌A、2、3、4、、、、、、10、J、Q、K、大小鬼分别代表数字1、2、3、4、、、、、、10、11、12、13、21;人和电脑轮流坐庄,庄家先发牌。胜利条件:将所取牌点数相加凑成 "和"是21,谁先凑成21就胜出,如果没有人凑到"和"是21,就定"和"最接近21且小于21就胜出。每人至多可取5张扑克牌。要注意"和"超过21者谁先爆掉也就是输了,如果都爆了,点数小的胜;当点数相同时,庄家胜。

      首先,理清游戏的运行思路是非常关键的。面对众多杂乱的规则,可以先去除无关紧要的细节,这样细节与游戏总体的思路没有关系,只是影响某些过程的处理细节.比如: 每人至多可取5张扑克牌,注意"和"超过21者谁先爆掉也就是输了,如果都爆了,点数小的胜;当点数相同时,庄家胜。可以概括为”取牌规则和判定规则”,这样整个游戏其实就变成了轮流取牌并计分的过程.只是一次取牌结束后可以自行退出,只是不能取5次以上,然后最终用特定的规则来判定胜负.这样理解的游戏的整体思路后,即使加入再多的细节也能轻松应对.

      程序编码的第一步是什么?是先声明变量?写主函数?我个人喜欢的是先完成子函数模块的设计.把子模块完成之后,更高级的模块就变得容易了.就像盖楼房一样,先堆砌基础的模块总让我很放心,而一开始就从上层开始让我有一种悬于空中的感觉。我认为对于小型程序来说,自下而上的设计方式是高效的.

      分析的时候从分析主体开始,没想到设计的时候从细节开始,但是,我小手一抖,就写出了几个子模块:

      //根据牌点获取其数值

intvalue(int i)

{

      if(i <= 52)

           return i / 4 + 1;     //花牌

      return MAXNUM;            //鬼牌

}

 

//电脑取牌

introbot_fetch()

{

      if(robot_value >= AVG_POINT)    //如果取得平均点,不再取牌

           return AVG_POINT;

 

      int id;

      do{

           id = rand() % SUM + 1;     //随机选牌

      }while(map[id]);

 

      map[id] = 1;      //标记为选择状态

     

      return robot_value + value(id);

}

 

//玩家取牌

intplayer_fetch()

{

      int id;

      do{

           id = rand() % SUM + 1;     //随机选牌

      }while(map[id]);

 

      map[id] = 1;      //标记为选择状态

     

      int temp = value(id);

      printf("\t\t你获得了%d 点, 现在您有 %d 点了\n", temp, player_value + temp);

      return player_value + temp;

}

 

//判断胜负

voidjudge_win(int flag)

{

      int winer;

 

      if(robot_value > MAXNUM &&player_value > MAXNUM)

      {

           //同时大于21,少者取胜

           if(flag == 1)    //玩家是庄家

                 winer = (robot_value >=player_value);

           else

                 winer = (robot_value >player_value);

      }

      else     if(robot_value> MAXNUM)

           winer = 1; //玩家赢了

      else     if(player_value> MAXNUM)

           winer = 0; //电脑赢了

      else

      {

           //同时小于21,多着取胜

           if(flag == 1)    //玩家是庄家

                 winer = (robot_value <=player_value);

           else

                 winer = (robot_value <player_value);

      }

 

      printf("\n\t\t%s\n", winer ?"玩家赢了" : "电脑赢了");

}

在设计这些子模块的同时便决定了一些细节:

1.     用随机数模拟取牌过程

2.     用map数组记录牌的选中状态防止重选.

3.     扑克牌是按数字顺序排序的.

也在设计的过程中发现并使用了必要的变量和常量:

1.     玩家和电脑对于的点数

2.     对中间点数,总点数进行宏定义,增强程序通用性.

做出这些决定是非常自然了,你可以做出个性的不同的决定,比如用数组记录每张牌的点数,用局部变量的参数传递代替全局变量的使用等等.

子模块的设计是非常简单了,即使一个C语言的新手对这个游戏束手无策,仍然可以编出上面的程序,因为在设计的过程中不需要考虑其他的任何细节,只要在乎眼前的问题而已。这和面向对象的封装思想一样,C++的封装更优秀无非就是把子函数整理归类了.

      最后就是用已有的模块搭建函数主题了,也同样可以轻松写出来:

int main()

{

      srand((unsigned)time(NULL));    //随机种子

     

      int flag = FLAG;    //庄家标志

      do        

      {

           memset(map, 0,sizeof(map));      //初始所有的扑克牌没有被选中

           player_value = robot_value= 0;

 

           printf("\n\t\t游戏开始\n");

     

           int count = 1;

           do{

                 player_value =player_fetch();      //玩家取牌

                 robot_value =robot_fetch();  //电脑取牌

                

                 if(count >MAXFETVH || player_value > MAXNUM)

                      break;

                 count++;

 

                 printf("您要继续取牌吗?(Y / N)\n");

           }while(tolower(get_sign())!= 'n');

 

           printf("\n\t游戏结束, 您获得了 %d 点, 电脑获得了 %d 点\n",player_value, robot_value);

           judge_win(flag);

           flag = !flag;     //交换庄家

 

           printf("您要继续游戏吗?(Y / N)\n");

      }while(tolower(get_sign()) != 'n');

 

    return 0;

}

      上面也有很大默认的规则,不过我想读者应该能够看出来,我就不多解释了.

 

      程序仅用了150行,实现了基本的21点游戏功能,再此基础上继续增加新的功能非常简单.

如果电脑更加智能,可以根据对方的牌数和自己的点数来决定是否继续选牌,只要改变robot_fetch()函数的一部分就可以了.如果玩家是在赌博,加入金币制,只要再声明一个变量记录金币的流失与获得就可以了.就算从控制台界面转入windows窗体界面,也许全部的代码都要改动,但是流程和思路是不变的,只要懂得控件的使用就可以.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值