专栏电商日志财经减肥爱情
投稿投诉
爱情常识
搭配分娩
减肥两性
孕期塑形
财经教案
论文美文
日志体育
养生学堂
电商科学
头戴业界
专栏星座
用品音乐

程序员用12小时复刻羊了个羊,代码已开源

  编者按:前段时间,超休闲三消游戏《羊了个羊》爆火,不少网友表示游戏第二关难度过高,甚至猜测根本没有通关的解法。而本文作者开发游戏的老王在尝试复刻游戏之后,提出了一个猜想:过高的难度,也许源于代码层面的瑕疵。
  以下为正文:
  昨天有朋友和我说:最近有个叫《羊了个羊》的游戏爆火,就是太难玩了,你能复刻一个不?
  话说上次玩休闲游戏还是在几年前,但是朋友之托必须赴汤蹈火啊,二话不说,开整!然而,冲动是魔鬼,直到此时此刻,老王也没能亲手玩一局原版游戏,不知道是游戏入口设计得太隐蔽还是网络加载太慢,无论手机端还是PC端,游戏都停留在如下界面。
  所以本次游戏的复刻,完全是基于各视频网站云观摩的结果,好在游戏的玩法不是特别难理解。复刻使用的开发工具是GodotEngine(使用其它工具开发原理也是相似的),目前项目已经开源到了GitCode:Godot版《羊了个羊》:
  https:gitcode。nethellotuteSheepASheep
  接下来我将通过临摹游戏的方式推测一下这个小游戏的实现原理,本文主要面向对游戏开发有兴趣的朋友,欢迎大家多提宝贵意见。
  01玩法第一眼看到《羊了个羊》,老王首先想到当年的《连连看》,不过有网友爆料,该游戏借鉴了《3tiles》。瞄了眼《3tiles》,是比较相似。说心里话,这个游戏的玩法并没有什么过于出众的地方,算是个中规中矩的低卡路里休闲游戏。
  之所以成为话题作品,主要就是因为它的第2关极其低的通关率,一下子激起了众多玩家的挑战欲望。
  而时至今日这个低通关率也被网络上的众多玩家揭秘,第2关其实大概率上本身就是个死局。是程序员故意挖坑设了死局么?先卖个关子,我们先聊聊游戏的开发,然后您自己就会有答案了。
  02实现概要游戏的整体很简单,但其中有几个实现的重点需要注意:
  牌堆数据结构的实现
  如何检测和更新可拾取的牌
  先做个小定义,一个牌堆中可被拾取的牌以下将简称其为:窗口牌。
  01牌堆的结构
  最初,我还真被这复杂的牌堆结构蒙住了,但仔细研究一番发现,无论多么复杂的牌堆,其实都是由如下三种牌堆模式组合拼凑而成的:
  蓝圈圈出的牌堆模式A:上面1张牌只挡住下面1张牌;同时下面的牌仅被上面1张牌挡住。只要上面的1张牌被取走,下面的牌就成为窗口牌;
  红圈圈出的牌堆模式C:上面1张牌可以挡住下面4张牌;同时下面的牌可能被上面4张牌挡住,一张牌只有它上面的4张牌都被取走,它自己才成为窗口牌。
  虽然上图中体现不是很明显,但不难猜想出,第三种牌堆模式B的存在,那就是:
  上面1张牌可以挡住下面2张牌;同时下面的牌可能被上面2张牌挡住,一张牌只有它上面的2张牌都被取走,它自己才成为窗口牌。
  对于牌堆模式A,有些朋友会迫不及待地用队列或栈实现它,这样做有两个缺点:
  逻辑上牌堆模式A的窗口牌也可能是2维的,如果用队列实现就限制了它的灵活性;
  牌堆模式B和C都不好用队列实现,所以想追求数据结构的统一,还要另求他法。
  实际上无论牌堆模式A、B还是C,都不过是3维数组结构,上图中模式A看起来特殊,无非是它的x,y维度都为1罢了。而三种牌堆的区别也无非就是当一张窗口牌被取走,检查牌堆是否出现新的窗口牌的方法罢了。
  牌堆模式A
  牌堆模式B
  牌堆模式C
  02牌堆的数据结构
  我将其定义为MContainerBase基类MContainerBaseextendsNode2DclassnameMContainerBasefuncready:addtogroup(name)addtogroup(game)varMaskFileReader。read(maskfile,null)box。resize(sizex)foriinrange(sizex):box〔i〕box〔i〕。resize(sizey)forjinrange(sizey):box〔i〕〔j〕box〔i〕〔j〕。resize(sizez)forkinrange(sizez):ifMasknullorMask〔i〕〔j〕1:box〔i〕〔j〕〔k〕addtile(i,j,k,getparent。distributeface)else:box〔i〕〔j〕〔k〕nullforxinrange(sizex):foryinrange(sizey):forzinrange(sizez):checkisontop(x,y,z)
  最基础的牌堆就是一个xyz的三维数组,我们可以使用一切方法构造想要的排队形状:柱形、条形、甚至金字塔形。这都不会影响后面程序的实现。
  项目中为了增加这个大方块的多样性,我还给它设置了如下的遮罩,这就是游戏中CSDN文字的由来。当然我们还可以通过遮罩来自由定义窗口牌,这部分就请大家自由发挥了。S形遮罩〔〔0,0,0,0,0〕,〔0,0,0,0,0〕,〔1,1,1,0,1〕,〔1,0,1,0,1〕,〔1,0,1,1,1〕,〕
  03如何检测和更新可拾取的牌
  三种牌堆模式分别派生自MContainerBase,并对应着如下三种检测方式:
  牌堆模式A:仅检测自己正上方是否有牌1Cover1extendsMContainerBasefunccheckisontop(x,y,z):ifhastile(x,y,z):ifnothastile(x,y,z1):(box〔x〕〔y〕〔z〕asMTile)。setisontop(true)
  牌堆模式B:检测自己上方两方位是否有牌1Cover2extendsMContainerBasefunccheckisontop(x,y,z):ifhastile(x,y,z):ifz20:ifnothastile(x,y,z1)andnothastile(x1,y,z1):(box〔x〕〔y〕〔z〕asMTile)。setisontop(true)else:ifnothastile(x,y,z1)andnothastile(x1,y,z1):(box〔x〕〔y〕〔z〕asMTile)。setisontop(true)
  牌堆模式C:检测自己上方四方位是否有牌1Cover4extendsMContainerBasefunccheckisontop(x,y,z):ifhastile(x,y,z):ifz20:
  ifnothastile(x,y,z1)andnothastile(x1,y,z1)
  andnothastile(x,y1,z1)andnothastile(x1,y1,z1):(box〔x〕〔y〕〔z〕asMTile)。setisontop(true)else:
  ifnothastile(x,y,z1)andnothastile(x1,y,z1)
  andnothastile(x,y1,z1)andnothastile(x1,y1,z1):(box〔x〕〔y〕〔z〕asMTile)。setisontop(true)
  在Godot中,这三种牌堆模式还可以通过场景节点制作成预制体,这样关卡设计师就可以轻松地制作出美观的关卡了。
  03如何生成新关卡
  简单了解游戏规则后,我们就不难推导出,每个关卡能被通过的一个必要条件就是每一种图案的总数,必须能被3整除。实现方法如下:vartilesexportvarinitialtiles{0:10,1:10,2:10,3:10,4:10,5:10,6:10,7:10,8:10,9:10,10:10,11:10,12:10,13:10,14:10,15:10}funcinit:forkeyininitialtiles:varnuminitialtiles〔key〕3foriinrange(0,num):tiles。append(key)tiles。shuffle
  其中字典initialtiles的key对应着每一种图案,后面的value对应着这一关该图案出现的对数(此处1对等于3个)。按照value乘以3的数量存入数组tiles(下文称之为:待发牌池),然后把待发牌池中的元素打乱顺序,等待发牌。
  01关于游戏中的坑
  很多朋友抱怨:程序员故意挖坑制作死关卡。其实不然,他无须故意挖坑,因为这个游戏本身就有很多天然的坑,如果不使劲填坑,它们自然而然就属于你了。而这里就隐藏了几个可致命的坑:乍一看,待发牌池中所有的图案都可以被3整除那么一定可以通关?那可不一定:
  只有桌面牌堆中牌的数量和待发牌池牌数一致,所有的牌才能落地,而游戏中桌面牌堆到底有多少(层)本身就是个迷。并且如果没猜错的话,在每一局设计者先要确保牌堆形状好看,然后再使堆牌数和待发池的牌数一致。二者哪怕差1个,也会造成死局。
  上文说了,桌面牌数和待发牌池的牌数一致只是过关的必要而非充分条件。即使该条件满足,如果相对于牌桌上的牌数以及图案数量,窗口牌数太少,也会造成死局。比如下面这个极端的例子:假设游戏共有15种花色,而牌桌上只有这个模式A牌堆,它有90张牌。那么玩家只要在连续7次拾牌时没有遇到3个相同图案的牌,就必死无疑了。
  其实这个游戏,一方面要控制关卡的难度,另一方面又要保证能通关本身就是一个相当困难的问题(至少老王没有想出办法)。
  而设计者反其道而行之,(可能)没有花力气去设计算法,把坑留给玩家,得到了极低的通关率,反而制造了话题并形成爆款。
  如此说来,这确实是个抖机灵的设计。但老王认为这种设计在游戏策划中是不宜被借鉴的,就像现在市面上泛滥的悬疑剧,开始埋坑无数,吊足观众胃口,最后烂尾不了了之一样,长此以往观众(玩家)对于悬疑剧(游戏)的信任感就被消费殆尽了。
  02洗牌道具的实现
  洗牌的实现原理很简单,把当前桌面的牌记录在一个数组tiles中,当需要洗牌时,先打乱一下数组中牌的顺序,然后让桌面上每一张牌到tiles中重新取一个值。再来个眼花缭乱点的动画,还真挺像那么回事儿。funcshuffletiles:tiles。shuffletilesindex1funcredistributefaceint:tilesindex1returntiles〔tilesindex〕
  03遮罩文件的读取
  这里要夸一下GodotEngine,它的很多功能真是方便,比如下面这个str2var它可以简单粗暴地直接把字符串转换成对象类型。classnameFileReaderstaticfuncread(path,defaultdata):vardatadefaultdatavarfileFile。newfile。open(path,File。READ)varcontent:Stringfile。getastextifnotcontent。empty:datastr2var(content)file。closereturndata
  04对象间的通信
  这个小游戏中存在大量的对象间的通信需求:牌和牌之间、牌和牌堆之间、牌和关卡之间、牌堆和关卡之间。为了快速实现游戏,我大量使用了GodotEngine的Group机制,不得不说Group是GodotEngine最赞的设计之一。
  04总结
  小游戏《羊了个羊》,从策划和开发的角度来看并不困难,然而瑕疵竟然能够成为噱头,也让人不得不感慨游戏世界真的一切皆有可能啊。
  作者简介:开发游戏的老王,高校教师、技术专栏作者、独立游戏开发者。

什么是尿路结石?它是如何形成的?尿路结石,又称泌尿系结石,是一种常见的泌尿系统疾病。尿路结石指的是在泌尿系统中形成的固体物质,可以存在于肾脏输尿管膀胱和尿道等部位。这些结石通常由某些物质在尿液中过度沉积而形成,如牙疼难忍,是胃火烧到了牙龈,止痛药只能治标不治本我有个患者,平常工作繁忙,而且经常陪老板参加应酬,有一次晚上应酬回来,牙痛得不行了。当时天色很晚了,牙科诊所也关门了,只好临时在家找了点布洛芬止痛。没想到最近牙疼得更厉害了,赶紧赶5连败!排名下滑十位,恐无缘CBA季后赛,32岁菜鸟教练为网红买单面对着排名靠后的广州队,同曦队在最后时候掉链子,以100113输给了广州队13分。如此一来,同曦队送给了广州队2连胜,而自己却遭到了5连败,同曦队输掉这场比赛之后,CBA积分榜排名英超阿森纳完胜曼联战平新华社伦敦3月12日电(记者张薇)阿森纳12日客场30完胜富勒姆,继续以5分优势领跑英超积分榜。在大将卡塞米罗上半场即被红牌罚下的情况下,曼联主场00战平联赛副班长南安普敦。阿森纳意甲罗马不敌萨索洛3月12日,罗马队球员迪巴拉(左二)在比赛中突破。新华社发(阿尔贝托林格利亚摄)当日,在20222023赛季意大利足球甲级联赛第26轮比赛中,罗马队主场以3比4不敌萨索洛队。3月1安东尼奥U20国足全是真正的战士!给中国足球带来了希望U20亚洲杯14决赛,U20国足在加时赛连丢点球,被韩国队31淘汰,主教练安东尼奥在加时赛上半场被罚下,赛后未能出席新闻发布会。不过在接受记者马德兴采访时,安东尼奥表示,U20国足津媒100多名球员通过体检ampampamp完善保险,津门虎6级梯队组建完成直播吧3月13日讯据天津日报报道,为通过新赛季准入,目前天津津门虎俱乐部的6级梯队已经组建完成。上赛季从北京国安俱乐部租借的杨帆,由于与国安俱乐部还有一个赛季的合同,在中超各队陆续莫兰特我不想活在集锦里面,乔丹从未证明过自己离开公牛能夺冠莫兰特一直把詹姆斯视为自己学习的偶像,可以说无论在任何场合都要夸赞詹姆斯一番,莫兰特在接受灰熊当地一家媒体采访表示,总有些人说乔丹什么什么的,对不起我没看过乔丹那时期比赛,我最多也WCBA决战终章李梦韩旭率四川1分险胜内蒙古,夺得队史首冠3月12日晚上的四川省体育馆人声鼎沸,一声声远达,必胜的口号震耳欲聋。当计时器归零,四川女篮的全体成员,包括助教训练师在内都抑制不住激动的心情冲进场内,相互拥抱。这一刻,WCBA新刘翔葛天闪离7年后一个和初恋复合,一个手撕情敌至今单身阅读此文前,诚邀您点击一下关注,方便您随时查阅一系列优质文章,同时便于进行讨论与分享,感谢您的支持2008年,在北京的鸟巢体育馆中,大家都十分期待那个像风一样的男人再次突破世界纪录天津室内赛,谁能创造新纪录?8分02秒03!3月1日,在四川成都进行的全国室内田径邀请赛(第四站)男子3000米决赛中,西藏名将扎西次仁跑出中国男子室内3000米历史第二好成绩,距离内蒙古名将张云山保持了21
两会时评丨两头发力,扩大有效需求华声在线全媒体评论员朱永华多渠道增加城乡居民收入,稳定大宗消费推动生活服务消费恢复今年的政府工作报告将着力扩大国内需求作为2023年工作重点,提出要把恢复和扩大消费摆在优先位置。客沉痛哀悼,著名表演艺术家刘三姐扮演者黄婉秋女士逝世3月4日凌晨3时16分,我国著名的表演艺术家,曾在电影刘三姐中饰演主角刘三姐的黄婉秋女士,在重症监护室因抢救无效逝世,享年80岁。黄婉秋女士于1943年1月出生于广西桂林市,十三岁祝贺!城大学生荣获第五届全国大学生旅游设计大赛全国三等奖中国旅游协会旅游教育分会厦门大学厦门市文化和旅游局联合主办,以世界瓷都自在德化为主题的2022年第五届全国大学生旅游设计大赛于日前圆满举行。由澳门城市大学国际旅游与管理学院袁晨阳吴普洛药业2022年净利润同比增长3。52拟10派2。97元中证智能财讯普洛药业(000739)3月10日披露2022年年度报告。公司全年实现营业总收入105。45亿元,同比增长17。92归母净利润9。89亿元,同比增长3。52扣非净利润8浙江多地气温直冲30专家回应今夏是否会遭遇极端高温浙江在线3月9日讯(记者李心怡)衣服穿多了!我也是,真没想到这么热,我里面还穿了一件保暖背心今天(3月9日)下午,浙江在线记者观察到西湖边游玩的行人都在讨论最近气温突然飙升的事儿。唐朝的饼花样多,又以胡饼为其中一绝,流传至今阅读此文前,麻烦您点击一下关注,既方便您进行讨论与分享,又给您带来不一样的参与感,感谢您的支持。引言众所周知,唐代以博大的胸怀和包容的心态对待外来文化,吸收颇多异域元素,从而呈现出叶秀新接待来访群众,释法明理解民忧3月6日下午,茂名滨海新区党工委副书记管委会主任叶秀新带队开展接访工作,耐心倾听详细记录来访群众提出的问题和诉求。区领导陈伟强毛继军及相关单位负责同志陪同接访。接访中,叶秀新与信访下水道堵塞用热水冲?错!教你正确做法,快速疏通无异味我们都希望过上高品质的生活,但想要达到这个目标真的很困难,我认为大家要做到的就是家居环境干净整洁,只有这样你的生活才会越来越顺心。每次大扫除的时候,我们只是光清洁明面上的污垢,从而中国秘鲁自贸协定实施13周年助深企减免关税约13亿元南都讯记者张一鎏通讯员甘梦竹罗维李欣近日,彩迅工业(深圳)有限公司出口秘鲁的一批电视机在深圳海关完成通关。我们公司主要生产液晶电视机,2022年出口秘鲁的货值达到2647万元人民币嗅到危险信号,英媒称数百名中国客户改变想法,已放弃在瑞士开户瑞士一直是以永久中立国身份,游走在国际舞台上,因其严格的银行保密制度,以及中立的政治立场,吸引了全世界大量私人财富。全球数以万计的富豪,都喜欢在瑞士开设私密账号,并将资金转入瑞士。新增技能人才200万人!河南2023年人人持证技能河南建设工作方案出炉大河网讯人才是一切发展的动力源泉。近日,省人力资源和社会保障厅印发2023年高质量推进人人持证技能河南建设工作方案(以下简称方案),明确了2023年目标任务及精准实施十大培训专项工
友情链接:快好知快生活快百科快传网中准网文好找聚热点快软网