
我将之命名为 ratel,对,没错,平头哥,就是这么霸气(怂
在发这篇主题的时候,ratel 还在开发的最后阶段,已经完成了基本的交互和游戏环节,有待优化,这里放出技术栈:
项目地址:https://github.com/ainilili/ratel
整个流程不难,首先,我需要将客户端和服务端搭起来,netty 提供着简洁的 api,可以快速的部署服务端和客户端,所以这个环节没有任何难度!一个简单的结构图如下:
通讯这一块搞定,接下来要思考的问题就是如何进行互动,这个问题将会引发出更深层的问题?
作为一个正在开发的项目,更多的难以解决的疑难杂症还等待着我去发现,本帖也将持续更新至 ratel 完结。
针对于以上问题的思考之后,我决定将数据持久化在内存中(要考虑 jvm 会不会 gc 掉,所以这里使用 final 修饰 static ),服务端抽象出Room - 游戏房间,ClientSide - 客户端信息和Poker - 结构这三个最主要的数据结构,网路逐渐变得复杂起来
详细结构如下
Room{ Client{ Poker{ int 唯一标识 int 唯一标识 int 大小 int 状态 int 房间标识 int 花色 map 客户端字典 str 昵称 } list 客户端列表 list 手持牌 int 地主标识 int 状态 int 地主牌 int 类型(农民|地主) struct 上次出手的信息 client 下手 int 上次出手人 client 上手 } } 每当一个客户端连接时,将会构造一个 Client 对象,分配一个唯一的标识供服务端识别,Room 由客户端建立,并且在此基础之上,其他客户端可以加入已创建且状态未满的房间,当游戏开始后,将会为房间中的所有客户端派发 Poker。
这种流程看似可行,按照这种模式,ratel 由 0 走到了 1
但 ratel 的重点并不止于此,各种问题(网络,安全,用户体验等)还有待解决。
ratel 开发完毕之后,大家工作之余偷偷开心一下,命令行下划划水。
根据大家的建议,对ratel的出牌方式做了一些修改,以及新增客户端退出或者异常断开的应对方案。
新的出牌规则: 3 -> 3 4 -> 4 5 -> 5 6 -> 6 7 -> 7 8 -> 8 9 -> 9 10 -> T/t/0 J -> J/j Q -> Q/q K -> K/k A -> A/a/1 2 -> 2 S(小王)-> S/s X(大王)-> X/x
例如如下牌:
Poker: ┌──┐──┐──┐──┐──┐──┐──┐──┐──┐──┐──┐──┐──┐──┐──┐──┐──┐──┐──┐──┐ │3 |5 |6 |6 |7 |8 |8 |9 |9 |9 |10|J |Q |Q |K |K |2 |2 |2 |X | │ | | | | | | | | | | | | | | | | | | | | └──┘──┘──┘──┘──┘──┘──┘──┘──┘──┘──┘──┘──┘──┘──┘──┘──┘──┘──┘──┘ 出牌的输入是:
56789 t jqk 则输出是:
Poker: ┌──┐──┐──┐──┐──┐──┐──┐──┐──┐ │5 |6 |7 |8 |9 |10|J |Q |K | │ | | | | | | | | | └──┘──┘──┘──┘──┘──┘──┘──┘──┘ 56789 t jqk将会被解析成{'5','6','7','8','9','t','j','q','k'}并发往服务端进行命中判断及出牌
最后上图
1 cnit 2018-11-06 22:24:00 +08:00 牛皮,我就会 9*9 乘法表 |
2 liaojl 2018-11-06 22:55:23 +08:00 via iPhone 叫地主 |
3 iamniconico OP @liaojl 我抢 |
4 iamniconico OP 大佬低调了,斗地主都是 javase 的知识 |
5 Bigglesworth 2018-11-06 23:33:46 +08:00 要不起 |
6 hourann 2018-11-06 23:36:27 +08:00 via iPhone 牛啊 |
7 johnniang 2018-11-06 23:36:55 +08:00 via Android 厉害厉害 |
8 richangfan 2018-11-06 23:38:37 +08:00 via Android pass |
9 zaneenaz 2018-11-06 23:40:52 +08:00 via Android 快点啊等到花儿都谢了,,厉害。 |
10 iamniconico OP 四个二带俩王,我摊牌了 |
11 lovefantasy 2018-11-07 00:08:34 +08:00 via iPhone 大佬啊 |
12 syahd 2018-11-07 00:11:28 +08:00 via Android 声音有不 |
13 alakey1989 2018-11-07 00:30:43 +08:00 膜拜老哥 |
14 catinsides 2018-11-07 00:39:33 +08:00 自带 bgm 的主题 |
15 sinv 2018-11-07 01:07:06 +08:00 via iPhone 上次有一把,上家在要地主的过程超时了,应该是掉线了,根据规则他就托管了,我一看直接要了 3 分牌还不错,惊喜来了,下家一看直接放弃抵抗也托管了,然后就变成我斗俩机器人农民。 …… …… 干,我特么输了。 被轰了三个炸弹,然后我自己还放了 4 个 A,3 个 2 加一个小鬼憋手里了…… 干 |
16 May725 2018-11-07 02:14:44 +08:00 via iPhone 哈哈,前两年也有在终端斗地主的想法,用 c 写了一半,就没继续下去了。加油,以后 v2 滑水又多了一种方式 |
17 Cbdy 2018-11-07 07:10:55 +08:00 via Android o 家不是要把 jvm 序列化砍了吗? |
18 easylee 2018-11-07 07:44:40 +08:00 via Android 有才!看到标题我还在想怎么显示牌呢。戳 star 去咯。 |
19 iamniconico OP @Cbdy java10 不清楚,java8 还在 |
20 iamniconico OP @whwq2012 想法不错,准备试试 |
21 Cbdy 2018-11-07 09:02:02 +08:00 |
23 artandlol 2018-11-07 09:07:53 +08:00 什么时候出 releases |
24 hfc 2018-11-07 09:09:49 +08:00 请问,你是在考虑涉及完大部分数据结构、逻辑等之后才开始开发的嘛? |
25 iamniconico OP @artandlol 预计近两周内 |
26 simonguo 2018-11-07 09:12:26 +08:00 via iPhone |
27 iamniconico OP @hfc 不全是,有些逻辑和数据结构的缺陷是在开发过程中发现的! |
28 baicheng10 2018-11-07 09:13:57 +08:00 插眼 |
29 loongwang 2018-11-07 09:15:38 +08:00 牛皮牛皮 |
30 KgM4gLtF0shViDH3 2018-11-07 09:16:29 +08:00 via iPhone 花色怎么看啊 |
31 iamniconico OP @Cbdy 看样子是准备要砍了,同时也准备给出弥补? > To replace the current serialization technology, a small serialization framework would be placed in the platform once records, the Java version of data classes, are supported. The framework could support a graph of records, and developers could plug in a serialization engine of their choice, supporting formats such as JSON or XML, enabling serialization of records in a safe way. But Reinhold cannot yet say which release of Java will have the records capability. |
32 iamniconico OP @bestkayle 看下最后一张图 |
34 CodingDoge 2018-11-07 09:19:10 +08:00 划水新境界 |
35 zhang1215 2018-11-07 09:26:08 +08:00 via iPhone 花式划水 |
36 realkenshinji 2018-11-07 09:28:25 +08:00 没有 test ?我们除了 watch 和 star 你的项目,难道不能 contribute ?? |
37 Cbdy 2018-11-07 09:36:09 +08:00 @iamniconico 估计是 JDK 官方出一个 JSON 库吧,类似 GSON 或者 FastXML 转正的感觉 参考一下这个:JSR 374 Specification,https://javaee.github.io/jsonp/ |
38 Daveedo 2018-11-07 09:38:38 +08:00 加油鸭! |
39 iamniconico OP @realkenshinji 等 Beta 版本完毕 |
40 iamniconico OP @Daveedo 感谢支持 |
41 iamniconico OP @Cbdy json 固然好,我之前也考虑用之,不足的一点是 json 无法传递对象类型,接收方在不知道什么类型的情况下,只能转为 map 结构,数据处理起来不太方便,但是我之后还是会换一种编解码方式的,jvm serialization 局限性太高,影响 ratel client 向 python,shell 发展 |
42 qwe61655 2018-11-07 10:30:42 +08:00 via iPhone 收藏了, |
43 bullettrain1433 2018-11-07 10:45:15 +08:00 等消息 |
44 loveCoding 2018-11-07 10:47:54 +08:00 @iamniconico #41 pb 序列化吧 |
45 iamniconico OP ratel 不会让大家久等的 |
46 iamniconico OP @loveCoding pb 好麻烦的,回头试试,不知道适不适合当前模型 |
47 lrh3321 2018-11-07 10:59:03 +08:00 star 了 |
48 zclHIT 2018-11-07 11:09:18 +08:00 star 了,坐等 beta test 和 release:) |
49 iamniconico OP @zclHIT 感谢支持 |
50 tianlang1989 2018-11-07 11:44:58 +08:00 能不能不要有牌的样式 就纯数字就行了 划水利器 先 star 为敬 |
51 iamniconico OP @tianlang1989 好主意,我会提供主题的修改入口的 |
52 tigerZhang 2018-11-07 11:58:54 +08:00 输入 index ,有点蛋疼,能不能通过光标左右选牌 |
53 mason961125 2018-11-07 12:00:32 +08:00 工作量严重不饱和!(滑稽 |
54 leavan 2018-11-07 12:48:28 +08:00 我觉得可以增加选牌的动态效果。比如输入 2,第二张牌就弹出来...比较直观。 |
55 iamniconico OP @tigerZhang 命令行版的应该做不了,我会思考一下的 |
56 iamniconico OP @leavan 优化时会改进一下选牌方案,不过弹出来有点不现实,可能需要 gui 的支持 |
57 natforum 2018-11-07 13:30:26 +08:00 |
58 cstj0505 2018-11-07 13:32:11 +08:00 @iamniconico 对象类型作为属性放进去,反序列化先去拿到对象类型 |
59 iamniconico OP @cstj0505 我也这样想过,准备换一种跨平台的方式,优化一下数据传输结构 |
60 leavan 2018-11-07 13:45:54 +08:00 @iamniconico 没有不现实吧,你就在字符界面里牌的顶端留一个空白行,弹出来的就把这张牌空白行放到底端就行了 |
61 kulove 2018-11-07 13:48:47 +08:00 直接输牌数字也行吧?比如对 2,是 2 2,三带一是,9 9 9 6.。 |
62 iamniconico OP @leavan 命令行打印只能 append,不能 modify 之前已经输出的,所以做不到的 |
63 crab 2018-11-07 13:51:28 +08:00 给阿姨倒杯卡布奇诺 |
64 leavan 2018-11-07 13:52:05 +08:00 最好能做一个光标,不需要鼠标,用类似 Vim 的操作模式,然后空格弹出或弹回某张牌,回车出牌,操作模式会简单很多。对这种精致的小项目很喜欢,已 star,不过不太喜欢这种交互性比较少的出牌方式,期待改进哈~ |
65 iamniconico OP @kulove 主意不错,这样方便选取,感谢 |
67 leavan 2018-11-07 13:54:33 +08:00 @iamniconico 我记得是有方法的,你去搜一下某些进度条的实现方式... |
68 iamniconico OP @leavan 感谢,之后会扩展客户端至其他平台,可能 linux 的 shell 下就可以实现你说的 |
69 iamniconico OP @crab 作者是男的,只是爱好动漫 |
70 ID2333 2018-11-07 14:08:49 +08:00 脑洞真 6,想玩~ |
71 NotNil1 2018-11-07 14:11:12 +08:00 感觉做个下五子棋的会简单一点哈 |
72 1847bell 2018-11-07 14:14:58 +08:00 我的,看得出来你确实很闲…… |
73 NotNil1 2018-11-07 14:20:07 +08:00 客户端代码怎么分发呢 |
74 MicroPan 2018-11-07 14:35:32 +08:00 666,前排关注~ |
75 MrUser 2018-11-07 14:37:40 +08:00 出牌时直接输入要出的牌呗,程序给转成索引,输入 index 太难受了:1=3,3=5,5=6 ……快绕晕了都还怎么记牌 |
76 realpg PRO @iamniconico #65 其实直接输入牌字母也可以 定义一下两个王是什么符号,比如 A 和 B 然后 1(A)23456789XJQK 问你出啥牌 直接输 111JJ 有效避免图形界面摸鱼困难 另外 提供老板键 一键终端变为编译界面 |
77 iamniconico OP @MrUser 没问题,我也发现这个挺蛋疼的 |
78 iamniconico OP @realpg 我再考虑 10 用什么字母代替,还是说用 0 ? |
79 realpg PRO |
80 iamniconico OP 3 4 5 6 7 8 9 T J Q K A 2 S X 3 4 5 6 7 8 9 10 J Q K A 2 小王 大王 单字母取消空格 |
81 iamniconico OP @realpg 可以的,不过 X 我准备用来表示大王 |
82 MrUser 2018-11-07 15:43:46 +08:00 大王大写 W,小王小写 w |
83 abmin521 2018-11-07 16:02:01 +08:00 前排预定 |
84 Kirscheis 2018-11-07 16:10:24 +08:00 via Android nb,插个眼 |
85 wsstest 2018-11-07 16:44:49 +08:00 坐等,更新求艾特 |
86 q397064399 2018-11-07 17:07:36 +08:00 现在搞个 Java 依赖是真的多,一下子 springboot 全家桶 全来了 |
87 ginux 2018-11-07 17:15:30 +08:00 服务端的高并发考虑是怎么处理的 |
88 iamniconico OP @ginux 高并发危险点主要在于加入房间这一块,不过也简单,对 status 加 volatile 修饰,处理事件时判断一下,创建房间的 id 分配采用 AtomicInteger 生成 id,客户端的 id 则直接采用 channel 的 socketAddress 在服务端的应用端口。 当然还有一些未知的并发问题和安全问题,之后会加强优化 |
89 iamniconico OP |
90 q397064399 2018-11-07 17:30:27 +08:00 @iamniconico #89 还有目前我都没跑起来你那个程序. 把打包上传到 maven 的跟使用的 隔离开来吧 或者写个打包运行的描述也好. |
91 susucoolsama 2018-11-07 18:07:34 +08:00 lei 了,想法不错啊,有木有智障对手的设定。 |
92 iamniconico OP |
93 iamniconico OP @wsstest 已更新,看附言<(_ _)> |
94 dinjufen 2018-11-07 19:02:40 +08:00 看完了我想写一个 GUI 的斗地主,但感觉好难 |
95 iamniconico OP @susucoolsama 说出你的想法 |
96 waruqi 2018-11-07 19:36:59 +08:00 via Android 纯字符?还是用 tui? |
97 iamniconico OP @waruqi 纯文字 |
98 mseasons 2018-11-07 19:49:28 +08:00 有意思,我去用 Python3 弄一个 |
99 lexuskingxx 2018-11-07 20:16:26 +08:00 牛 13 了 |
100 iamniconico OP @mseasons 我准备将服务端做成通用的,以后你可以考虑用 py 写客户端<(_ _)> |