扯蛋

做了两年的Nodejs全栈开发,不知道为什么跑来做游戏呢(大概是厦门nodejs不好找工作吧)。用的是网易的pomelo的游戏框架。现接手了一个棋牌游戏:二十一点,不懂的规则的可以自行百度。

二十一点游戏流程图

现状

接手了平台其他相关游戏的代码,流程控制相互交错,不易理解、难以维护。(可能是刚做游戏的原因,如果你们有什么更简单的流程控制方法,欢迎分享)。我下意识的就想到了Generator函数的特性,感觉用着这里非常方便(以前一直觉得这是个异步流程控制中过度性质的方法,并且需要配合co才能自动执行,所以基本没实际用过,koa不算...)

Js Generator函数实现流程控制的优点

1、易于理解、便于开发、容易维护(看到Generator函数犹如看到了流程图)
2、开发思路清晰(每个阶段(函数)只需要关注自己的业务逻辑,完成直接下一步,而不用管下一步要做什么操作)
3、不存在会忘记清除定时器的问题

简单说下Generator的执行流程

1、Generator函数执行后会生成一个Iterator。(注意不要加new)(简单说就是个有next方法的对象,执行一次返回一个值)
2、每次next的调用,执行yield后面的语句并返回该语句执行的结果
3、每次只执行一个yield,后面的语句不会再执行、只有在执行下次next函数时才执行。(可以利用这点做定时器的清理工作,而且可以说基本不会忘记)
4、yield* 可以将后面的变量(可迭代的变量,字符串、数组等)中的值一个一个的返回。执行一次返回其中的一个值

Js Generator函数完美实现流程图代码(部分)


class EsydProcess { constructor(room) {
/**
* ...其他变量
*/
this.flow = this.flowGenerator();
} *['flowGenerator']() { yield this.betStage(); // 下注
this.betStageTimer && clearTimeout(this.betStageTimer);// 下注阶段完成后直接清除定时器。完全不用担心定时器没有被清理的情况 yield this.assignStage(); // 分牌 if (this.esydCard.getCardPoint(this.bankerCards[0]) === 1) { yield this.ensureStage(); // 保险
this.ensureStageTimer && clearTimeout(this.ensureStageTimer); if (this.esydCard.getCardType(this.bankerCards) !== CardTypes.BLACK_JACK) {
yield* this.operateStage(); // 操作
} } else {
yield* this.operateStage(); // 操作
} yield this.settleStage(); // 结算
} *['operateStage']() {
// 通知进入玩家操作阶段
this.noticeChangeStage(esydConsts.gameStage.OPERATE_STAGE);
let players = this.players;
for (let uid in players) {
let player = players[uid]; // 操作第一副牌
yield this.changeOperatingPlayer(player);
player.getCurCardInfo().isStop = true;
this.operateTimer && clearTimeout(this.operateTimer); if (player.isSperated) {
// 如果有一副牌,操作第二副牌
player.curCardsIndex = 1;
yield this.changeOperatingPlayer(player);
player.getCurCardInfo().isStop = true;
this.operateTimer && clearTimeout(this.operateTimer);
}
}
yield this.bankerOperate(); // 庄家操作
} // 转到下个阶段
nextStage() {
process.nextTick(() => {
this.flow.next();
});
} // 开始游戏
start(seats) {
/**
* ...
*
*/
// 第一次next,直接进入下注阶段。整个流程走完游戏结束
this.nextStage();
} betStage(){
// 进入下注阶段
this.noticeChangeStage(esydConsts.gameStage.BET_STAGE);
/**
* 其他操作
*/
this.betStageTimer = setTimeout(() => {
this.betStageTimer = null;
// 超时,直接进入下一步。没有下注的玩家使用默认底注
this.nextStage();
}, esydConsts.stageTime.BET_STAGE);
} assignStage(){
/**
* ...
* 分牌操作,完成直接下一步
*/
this.nextStage();
} ensureStage(){
/**
* ...
* 各种操作,如通知客户端、开始超时定时器等。操作完后直接下一步就Ok了。只需要专注当前函数的功能,完成直接下一步
*/
this.nextStage();
} // 监听用户下注操作
userBetOperateListener(uid){ /**
* ...
* 检查是否在下注阶段,不是不能下注、记录每个玩家下注等
*/ // 记录已下注的玩家
this.betedPlayers[uid] = true;
if (Object.keys(this.betedPlayers).length === this.seatCount) {
// 如果所有玩家都押注完毕,
this.nextStage();
}
} /**
* 其他函数...
*/ }

来源:https://segmentfault.com/a/1190000017195986

Generator函数在流程控制中的应用的更多相关文章

  1. MySQL--视图view、触发器trigger、事务(start transaction)、存储过程(特殊的数据逻辑处理函数)、流程控制(if,case....)

    mysql致力于项目开发及数据库管理之间解耦合(帮忙封装一些数据处理方法,使应用程序的开发者可以专注于应用程序的开发),但受限于不同部门沟通的成本问题,现阶段直接使用的价值不大. 一.视图(只能sel ...

  2. 14 MySQL--事务&函数与流程控制

    一.事务 事务用于将某些操作的多个SQL作为原子性操作,一旦有某一个出现错误,即可回滚到原来的状态,从而保证数据库数据完整性. 一堆sql语句:要么同时执行成功,要么同时失败 # 事务的原子性 场景: ...

  3. mysql:视图、触发器、事务、存储、函数、流程控制

    阅读目录 一 视图 二 触发器 三 事务 四 存储过程 五 函数 六 流程控制 回到顶部 一 视图 视图是一个虚拟表(非真实存在),其本质是[根据SQL语句获取动态的数据集,并为其命名],用户使用时只 ...

  4. php总结3——基本函数、流程控制中的循环

    3.1 php基本函数(数学.日期.字符串) 数学函数:max         mixed max(number $arg1,number $arg2,……)  求一组数据中的最大值        m ...

  5. [MySQL数据库之Navicat.pymysql模块、视图、触发器、存储过程、函数、流程控制]

    [MySQL数据库之Navicat.pymysql模块.视图.触发器.存储过程.函数.流程控制] Navicat Navicat是一套快速.可靠并价格相当便宜的数据库管理工具,专为简化数据库的管理及降 ...

  6. MySQL知识补充(表字段操作、视图、触发器、事物、存储过程、内置函数、流程控制、索引、慢查询)

    今日内容概要 表字段操作补充(掌握) 视图(了解) 触发器(了解) 事务(掌握) 存储过程(了解) 内置函数(了解) 流程控制(了解) 索引(熟悉) 内容详细 1.表字段操作补充 # 1.添加表字段 ...

  7. php总结2——php中的变量、数据类型及转换、运算符、流程控制中的分支结构

    2.1  php中的变量: 定义变量:$变量名称=值: 变量名称:$开头    $之后的第一位必须是字母    $第二位之后可以是字母.数字或者是下划线.习惯上变量名称有实际含义,第二个单词后首字母大 ...

  8. Mysql-自带的一些功能,基本用法(视图,触发器,事务,存储过程,函数,流程控制)

    一. 视图 二. 触发器 三. 事务 四. 存储过程 五. 函数 六. 流程控制 一 .视图 视图是一个虚拟表(非真实存在),其本质是[根据SQL语句获取动态的数据集,并为其命名],用户使用时只需使用 ...

  9. Go语言系列(三)- 基础函数和流程控制

    一.strings和strconv的使用 1. strings.HasPrefix(s string, prefix string) bool:判断字符串s是否以prefix开头 . 2. strin ...

随机推荐

  1. Java算法——回溯法

    回溯法一种选优搜索法,又称试探法.利用试探性的方法,在包含问题所有解的解空间树中,将可能的结果搜索一遍,从而获得满足条件的解.搜索过程采用深度遍历策略,并随时判定结点是否满足条件要求,满足要求就继续向 ...

  2. ASP.NET Core3.1使用IdentityServer4中间件系列随笔(四):创建使用[ResourceOwnerPassword-资源所有者密码凭证]授权模式的客户端

    配套源码:https://gitee.com/jardeng/IdentitySolution 本篇将创建使用[ResourceOwnerPassword-资源所有者密码凭证]授权模式的客户端,来对受 ...

  3. 模型层中QuerySet的学习

    创建对象 使用关键字参数实例化模型实例来创建一个对象,然后调用save()把它保存到数据库中 pub_obj = models.Publisher(title='奥利给出版社') pub_obj.sa ...

  4. 删除MBR分区如何使用光盘恢复

    1.备份MBR分区表 dd  if=/dev/sda  of=/data/mbr.bak  bs=1  count=64  skip=446 分区表前512字节分为三部分,第一部分446字节与启动相关 ...

  5. Resources.UnloadUnusedAssets

    2017.11.7更新: 其实这个函数就是顾名思义,关键是理解AssetBundle, Asset, GameObject, 资源等之间的关系,参考此文即可: http://www.cnblogs.c ...

  6. 分布式文件存储:FastDFS简单使用与原理分析

    引言 FastDFS 属于分布式存储范畴,分布式文件系统 FastDFS 非常适合中小型项目,在我接手维护公司图片服务的时候开始接触到它,本篇文章目的是总结一下 FastDFS 的知识点. 用了 2 ...

  7. 浅析LR.Net工作流引擎

    在当代信息化软件系统开发中,工作流引擎是其中非常重要的一环.所谓工作流引擎,是指工作流作为软件系统的一部分, 其中包括了流程的节点管理.流向管理.流程样例管理.审核管理等重要功能. 工作流引擎可根据角 ...

  8. 消息队列之-RocketMQ入门

    简介 RocketMQ是阿里开源的消息中间件,目前已经捐献个Apache基金会,它是由Java语言开发的,具备高吞吐量.高可用性.适合大规模分布式系统应用等特点,经历过双11的洗礼,实力不容小觑. 官 ...

  9. Agumaster 改善了pagination

    页面越来越完善了.

  10. tomcat-8.0.18 cluster 使用Redis共享Session 配置

    事实证明 这位作者提在https://jingyan.baidu.com/article/ac6a9a5e10415f2b653eace8.html 最底下的http://pan.baidu.com/ ...