A poker game based on browser, only using basic algorithms
这里我主要用中文来讲述poker game的完成细节,一些注意点和坑,以及单人web项目开发过程中的体会
I'll mainly express in Chinese, including details, not-to-dos and how should I develop small projects.
偶然一个论坛的帖子,讨论扑克牌残局。事实上我以前也经常看这类帖子,包括下面引发的一众讨论,但其实很多残局用穷举的方法就能知道获胜方法,让某些讨论完全可以用程序来替代。
I've read some posts on BBS discussing poker matches, in fact, some are not quite meaningful because a simple program could do it all.
事实上这个思路很简单,用不着多高深的算法,首先枚举所有对局情况,生成决策树。再把结果从底至上保存
The idea is to enumerate all the possible choices and generate a decision tree. Then save the results from bottom to top.
An algorithm to get a decision tree, params are cards and isFirst flag
getDecisionTree(cardsA, cardsB, isAfirst)
在Gatsby中引入这个算法,并组件化构建相关的页面
import this algorithm in gatsby and build related components
构建的过程中发现,如果完全使用React Hooks来写逻辑,会变得非常复杂。因为对于游戏而言,组件间的交互是非常重的,所以最后删除了几乎所有Component的Hook,使用一个全局变量来保存所有游戏数据,这样也方便使用本地存储进行自动保存
I discovered that there will be heavy interaction between components while using hooks, so I use a "global variable" instead.
通过一个状态机(DFA)使用该全局变量,当然也可以用Redux的概念去理解,即每个处理action的函数, 接受一个action和相关的参数,找到当前的游戏状态,然后去执行相应的操作,返回新的状态
This global variable works with a DFA,or you can understand it using concepts from Redux, like there is a function which receives an action and some parameters, and then, get the new state from previous state.
最后定义一系列的游戏状态,和相关的参数,我发现确实可以用一个比较复杂的状态机来描述整个游戏过程。唯一美中不足的是,游戏需要暂停,也就是说停止响应任何除了接触暂停操作之外的动作,那么这时候需要写一个额外的逻辑。
Finally, I defined several game states and found my DFA did perfectly implement the game except for some extra logic handling the pause-resume action.
//definition
const act = (prevState, action, params, forced)=>{
if (prevState.paused && action!=ACTION.RESUME) return prevState
...
return newState
}
//usage
state = act(state, ACTION.DO_SOME_THING, [1,2], false)
对于游戏来说UI很重要,但我直接凭多年看卢姥爷直播录像的经验画了,吐槽一下,用CSS画界面真的非常复杂而且耗时,因为一开始想的是组件式的开发,后来就没改,如果重来的话我会用canvas
UI is important for a game, but I just draw it according to my personal experience. It was an exhausting work and if I can redo it, I will use canvas.
开发的过程中我发现,使用一整个DFA来定义游戏状态真的是非常方便的做法,方便增删功能,也几乎不用与展示层做任何交互
It's really convenient to use a whole DFA to define game state if you want to add or delete some features without changing components for present.
最后,我使用了workerize-loader来实现异步计算的功能,毕竟JS是单线程的,在WebWorker技术出现之前这种重计算的场景简直是天方异谈,重则浏览器奔溃,轻则网站卡死,感谢WebWorker!
At last, I used workerize-loader to add support for asynchronized computing, thanks for webworker!
首先从一个想法到想法的完全实现用了接近一个月的时间,当然这里的实际编码时间只有10天左右(估计每天5小时左右)。主要的瓶颈在于首先这是个临时起意的想法,也就是我之前从来没有接触过任何相关或类似的项目,那么就很有可能出现进行到一半需要重构整个项目的情况,事实上的确,当我发现用另一种办法(使用全局游戏变量)可以加快开发时,我果断重构了整个项目。次要的瓶颈在于UI,事实上,用CSS画UI的功夫足够我写十个算法了,还是使用canvas比较自由和方便。
解决了这两个问题,我相信项目的进度会大大加快,因为纯粹的技术问题通过stackoverflow或者google,几乎不会超过10分钟就可以得到解决。
所以,今后的web个人项目,我会做的是:
另外,考虑到Chrome即将取消对Flash的支持,某些轻量级的游戏,实际上就失去了生存的空间,使用一些基于Html5的游戏框架(甚至不需要复杂的引擎,只需要UI库的支持),加上PWA,有没有可能快速完成一些好玩有趣又轻松的游戏呢?