。NetCore用SignalR撸个游戏
之前开内部培训,说到实时web应用这一块讲到了SignalR,我说找时间用它做个游戏玩玩,后面时间紧张就一直没安排。这两天闲了又想起这个事,考虑后决定用2天时间写个斗D主,安排了前端同学写客户端,我写游戏逻辑和服务。
这个项目难度并不高,但是游戏逻辑还是挺绕的,联调过程中也发现解决了很多小问题。来园子里整理一篇文章,记录一下。
基础的介绍就免了,毕竟官网跟着走两圈啥都懂了。没基础的可以戳这里,是我之前写的一篇SignalR基础介绍,带有一个极简聊天室。
tips:文章结尾有开源地址,游戏数据都是本地的,改下IP运行起来就可以玩了。
直接上干货,首先是数据模型: /// /// 用户信息 /// public class Customer { /// /// 唯一ID /// public string? ID { get; set; } /// /// 昵称 /// public string? NickName { get; set; } /// /// 卡片 /// public List Card { get; set; } } /// /// 房间 /// public class Room { /// /// 房间名 /// public string Name { get; set; } /// /// 房主id /// public string Masterid { get; set; } /// /// 当前出牌人 /// public int Curr { get; set; } /// /// 当前卡片 /// public List CurrCard { get; set; } = new List(); /// /// 当前卡片打出人 /// public string ExistingCardClient { get; set; } /// /// 房间成员列表 /// public List Customers { get; set; } = new List(); }
tips:只是单纯为了斗D主设计的,商用版肯定不能这么搞,参考请慎用。
有了数据模型,自然少不了CRUD: /// /// 用户信息 /// public class Customer { /// /// 唯一ID /// public string? ID { get; set; } /// /// 昵称 /// public string? NickName { get; set; } /// /// 卡片 /// public List Card { get; set; } } /// /// 房间 /// public class Room { /// /// 房间名 /// public string Name { get; set; } /// /// 房主id /// public string Masterid { get; set; } /// /// 当前出牌人 /// public int Curr { get; set; } /// /// 当前卡片 /// public List CurrCard { get; set; } = new List(); /// /// 当前卡片打出人 /// public string ExistingCardClient { get; set; } /// /// 房间成员列表 /// public List Customers { get; set; } = new List(); }
因为所有数据都是通过静态属性保存的,所以大部分都是linq操作(原谅我linq水平有限)。
接下来是游戏逻辑: /// /// 卡片相关 /// public class WithCard { /// /// 黑桃-S、红桃-H、梅花-C、方块-D /// BG大王,SG小王,14-A,15-2 /// readonly List Cards = new List() { "S-14","S-15","S-3","S-4","S-5","S-6","S-7","S-8","S-9","S-10","S-11","S-12","S-13", "H-14","H-15","H-3","H-4","H-5","H-6","H-7","H-8","H-9","H-10","H-11","H-12","H-13", "C-14","C-15","C-3","C-4","C-5","C-6","C-7","C-8","C-9","C-10","C-11","C-12","C-13", "D-14","D-15","D-3","D-4","D-5","D-6","D-7","D-8","D-9","D-10","D-11","D-12","D-13", "BG-99","SG-88" }; /// /// 发牌 /// public List> DrawCard() { List a = new List(); List b = new List(); List c = new List(); Random ran = new Random(); //剩3张底牌 for (int i = 0; i < 51; i++) { //随机抽取一张牌 string item = Cards[ran.Next(Cards.Count)]; switch (i % 3) { case 0: a.Add(item); break; case 1: b.Add(item); break; case 2: c.Add(item); break; } Cards.Remove(item); } return new List>() { a,b,c,Cards }; } /// /// 规则 /// /// /// /// /// public bool Rule(List existingCard, List newCard, bool isSelf) { //现有牌号 List existingCardNo = existingCard.Select(x => Convert.ToInt32(x.Split("-")[1])).ToList().OrderBy(x => x).ToList(); //新出牌号 List newCardNo = newCard.Select(x => Convert.ToInt32(x.Split("-")[1])).ToList().OrderBy(x => x).ToList(); //上一手是王炸,禁止其他人出牌 if (existingCardNo.All(x => x > 50) && existingCardNo.Count == 2) { if (isSelf) return true; else return false; } //王炸最大 if (newCardNo.All(x => x > 50) && newCard.Count == 2) return true; //单张 if (newCardNo.Count == 1) { if (existingCardNo.Count == 0) return true; if ((existingCardNo.Count == 1 && newCardNo[0] > existingCardNo[0]) || isSelf) return true; } //对子/三只 if (newCardNo.Count == 2 || newCardNo.Count == 3) { if (existingCardNo.Count == 0 && newCardNo.All(x => x == newCardNo[0])) return true; if (newCardNo.All(x => x == newCardNo[0]) && (isSelf || newCardNo.Count == existingCardNo.Count && newCardNo[0] > existingCardNo[0])) return true; } if (newCard.Count == 4) { //炸 if (newCardNo.All(x => x == newCardNo[0])) { if (existingCardNo.Count == 0 || isSelf) return true; if (existingCardNo.All(x => x == existingCardNo[0]) && existingCardNo.Count == 4) { if (newCardNo[0] > existingCardNo[0]) return true; } return true; } //三带一 { List flagA = newCardNo.Distinct().ToList(); //超过2种牌直接失败 if (flagA.Count > 2) return false; //没有上一手牌,或者上一手是自己出的牌 if (existingCardNo.Count == 0 || isSelf) return true; int newCardFlag = 0; if (newCardNo.Where(x => x == flagA[0]).ToList().Count() > 1) { newCardFlag = flagA[0]; } else newCardFlag = flagA[1]; List flagB = existingCardNo.Distinct().ToList(); //上一手牌不是三带一 if (flagB.Count > 2) return false; int existingCardFlag = 0; if (existingCardNo.Where(x => x == flagB[0]).ToList().Count() > 1) { existingCardFlag = flagB[0]; } else existingCardFlag = flagB[1]; if (newCardFlag > existingCardFlag) return true; } } if (newCard.Count >= 5) { bool flag = true; for (int i = 0; i < newCardNo.Count - 1; i++) { if (newCardNo[i] + 1 != newCardNo[i + 1]) { flag = false; break; } } //顺子 if (flag) { if (existingCardNo.Count == 0 || (newCardNo[0] > existingCardNo[0] && newCardNo.Count == existingCardNo.Count) || isSelf) return true; } } return false; } }
单张规则和普通斗D主一样(除了王以外2最大,其次是A),多张规则目前支持:王炸、对子、三只、顺子、三带一。目前只做到这里,各位同学可以拿回去自行扩展。
上一些运行图。房主建房并加入:
新玩家加入:
房间人满以后房主开始游戏,随机分配地主:
出牌特效:
游戏结算:
最后附上开源地址(客户端在web分支):https://gitee.com/muchengqingxin/card-game
tips:前端同学在没有UI配合的情况下做到现在这样,必须给个赞。最后提醒大家,不要拿去商用。
原文链接:https://www.cnblogs.com/muchengqingxin/p/15612678.html
小米8青春版于9月19日在成都发布你期待吗?小米今天上午小米官方微博爆出9月19日要在成都举办秋季新品发布会。根据此前的曝光小米8青春版,6。26英寸22801080的TFT屏骁龙710,4G6G8G内存都有费解32G64G
5G的频谱效率,到底有多高?无线频谱,是运营商最宝贵的资源。如果把无线网络比作一片稻田的话,无线频谱就是种植这些水稻的土地。如果土地本来就少,还想要高产的话,只能从培育良种上下功夫。移动通信的每一代发展,都相
美国力挺的OpenRAN,真的能成功吗?2020是5G元年,也是OpenRAN发展的关键之年。从今年下半年起,关于OpenRAN的新闻不绝于耳。这种全新的网络架构在打开我们视野的同时,也带来了很多的困惑。本期,蜉蝣君将和
GPS再牛,我们还是要有北斗我在哪?现在是什么时间?要达到目的地该怎么走?说到GPS,大多数人的第一反应就是定位和导航,这是GPS设计的初衷,也是其最典型的应用。并且,由于GPS免费公开,并且性能可靠,全球的
什么是5G?速度就是能力5G这么火,它到底是什么?为什么那么牛?看完就知道了!引子从2020年初开始,5G好像一下子变得和新冠一样出名了今年是5G商用的元年从国家战略到百姓茶余饭后,5G被广泛谈及,而且被
5G,该上天了伴随着刺耳的轰鸣,一个形如巨鸟的庞然大物,风驰电掣般地在跑道疾驰,旋即腾空而起,扶摇直上九万里。每天,都有无数这样的庞然大物,运载着宇宙的精华,万物的灵长,翱翔在云霄之上的万米高空
广电的700M为什么被称为黄金频段?在中国,任何一个频段都不及700M这样引人瞩目。它被称作移动通信的黄金频段,在4G时代就曾引爆过无数的话题。700M,到底何德何能,有如此之美誉,承载如此多的期望?到了5G时代,中
5G能实现远程手术吗?在5G的启蒙阶段,我们经常看到各种科技感十足的应用,远程手术正是其中之一。随着5G的广泛部署,这些应用的宣传都渐渐消歇。那么,很多人就要问了,5G到底能不能实现远程手术?用光纤不是
离开华为的荣耀,是否会活得更好?2020年11月17日,荣耀的归宿终于尘埃落定。这个事情,在数月前其实已经讨论地沸沸扬扬。荣耀要卖是毫无疑问的,只是接盘者不是盛传的神州数码。从下图这张联合声明中可以看出,收购华为
载波聚合,让5G下载速度飙升话说随着智能手机的普及和移动互联网的发展,各种各样的手机和平板对网速和流量的需求是越来越强烈,甚至到了如饥似渴的地步。那么怎样才能满足人民日益增长的网速需求和网络容量有限之间的矛盾
从1G到5G,波澜壮阔的通信发展史一个人的气质里有走过的路读过的书爱过的人5G又经历了哪些故事呢?引子在上一期的5G科普图解什么是5G?中详细分析了5G为什么那么厉害一部高清电影秒秒钟就能下载下来远程游戏再也不会有