Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【参赛经验分享】腾讯极客挑战赛第四期俄罗斯方块比赛复盘

【参赛经验分享】腾讯极客挑战赛第四期俄罗斯方块比赛复盘

原创
作者头像
HellloWrold-Ian
修改于 2021-08-16 02:14:35
修改于 2021-08-16 02:14:35
1.6K1
举报
文章被收录于专栏:比赛复盘比赛复盘
1.比赛总结

  七月底的时候在网络上看到了这样一个赛事,赛题大概总结起来就是用代码玩一款十分经典的游戏俄罗斯方块,通过游戏得分来排名评比,觉得挺有意思,抱着随便试试的想法就参加了,结果最后获得了全国第49名,最终获得的最高分数是31万多一点,虽然和第一名的一百多万还是有不小的差距,需要改进反省的地方还有很多,但这一成绩还是基本达到了我的预期的,同时我也是成功获得了腾讯招聘的绿色通道,丰富了自己的履历。

最终比赛成绩
最终比赛成绩
2.比赛复盘

  在赛事官网可以找到俄罗斯方块游戏的比赛入口,进入游戏之后可以发现游戏的界面是一下这样的:

腾讯极客挑战赛游戏界面
腾讯极客挑战赛游戏界面

  光看这个游戏界面,这就是一个普通的俄罗斯方块游戏,但其实玄机藏在浏览器的控制台中,打开浏览器的控制台,很容易就可以找到这个游戏的源码,因为腾讯官方在控制台的代码资源中用注释告诉你了源码的网址。我们将整个游戏项目拉到本地之后,就可以“魔改代码”,大展身手了。

  在本地用IDE打开这个游戏项目,可以看到游戏使用JavaScript写的,而且是基于vue.js框架。虽然我的“主战场”是后端Java Web,但对前端JS还是比较熟悉的,特别是vue框架,“魔改代码”基本上还是绰绰有余的,所以我选择了直接在源码上进行代码添加,实现用算法跑俄罗斯方块。

  经过上网查询俄罗斯方块算法相关资料后,我了解到目前的主流俄罗斯方块AI算法是基于A*算法的启发式搜索。基本思路就是定义一个启发函数对当前局面进行评估,对于每一个当前即将下落的方块,遍历方块下落的所有情况——以各个形状在所有位置下落的情况,对于每一种情况,通过启发函数算出局面评估的评分,在所有情况中,评分最高的就是当前最优的下落情况,然后将当前方块旋转到该最优情况所对应的形状,再移动到对应最佳位置,下落即可。

  我的算法思路基本上就是以上所阐释的启发式搜索,确定了算法方向之后,接下来的关键就是这个启发函数该如何设计,这决定了如何定义方块该以怎样的形状,在哪个位置下落。通过网上资料我了解到,目前存在三种比较普遍的方案。

  第一种是最经典的Pierre Dellacherie算法,其对局面进行评估的启发函数包含以下6项指标:

1.landingHeight(下落高度): 指当前板块放置之后,板块重心距离游戏区域底部的距离

2.erodedPieceCellsMetric(消行评分): 代表的是消除的行数与当前摆放的板块中被消除的小方块的格数的乘积。

3.boardRowTransitions(行变换): 对于每一行小方格,从左往右看,从无小方格到有小方格是一种“变换”,从有小方格到无小方格也是一种“变换”,这个属性是各行中“变换”之和

4.boardColTransitions(列变换): 每一列的变换次数之和

5.boardBuriedHoles(空洞数): 各列中的空洞的小方格数之和

6.boardWells(井数): 各列中“井”的深度的连加和,井是指中间一列为高度低于左右两列的情况,整体呈现为凹字形

最后的启发函数定义为:

value = x1 × landingHeight + x2 × erodedPieceCellsMetric + x3 × boardRowTransitions + x4 × boardColTransitions + x5 × boardBuriedHoles) + x6 × boardWells

x1:-1 x2: 1 x3:-1 x4:-1 x5:-4 x6:-1

value的取值越高,说明当前下落情况越优。

  第二种是在Pierre Dellacherie算法的基础上进行提升的El-Tetris算法,该算法对原Pierre Dellacherie算法的第二项指标erodedPieceCellsMetric有略微调整,同时改进了各个评价指标的系数

1.landingHeight(下落高度): 指当前板块放置之后,板块重心距离游戏区域底部的距离

2.rowsEliminated(消行数): 代表的是消除的行数

3.boardRowTransitions(行变换): 对于每一行小方格,从左往右看,从无小方格到有小方格是一种“变换”,从有小方格到无小方格也是一种“变换”,这个属性是各行中“变换”之和

4.boardColTransitions(列变换): 每一列的变换次数之和

5.boardBuriedHoles(空洞数): 各列中的空洞的小方格数之和

6.boardWells(井数): 各列中“井”的深度的连加和,井是指中间一列为高度低于左右两列的情况,整体呈现为凹字形

启发函数定义为:

value = x1 × landingHeight + x2 × rowsEliminated + x3 × boardRowTransitions + x4 × boardColTransitions + x5 × boardBuriedHoles) + x6 × boardWells

x1: -4.500158825082766 x2: 3.4181268101392694 x3: -3.2178882868487753 x4: -9.348695305445199 x5: -7.899265427351652 x6: -3.3855972247263626

  第三种是我在相关论文——Improvements on Learning Tetris with Cross Entropy 中看到的又一种改进算法,这种算法在Pierre Dellacherie的基础上增加了两个评估指标:holeDepth和rowsWithHoles,同时对评估指标的系数进行了重新定义。

1.landingHeight(下落高度): 指当前板块放置之后,板块重心距离游戏区域底部的距离

2.erodedPieceCellsMetric(消行评分): 代表的是消除的行数与当前摆放的板块中被消除的小方块的格数的乘积。

3.boardRowTransitions(行变换): 对于每一行小方格,从左往右看,从无小方格到有小方格是一种“变换”,从有小方格到无小方格也是一种“变换”,这个属性是各行中“变换”之和

4.boardColTransitions(列变换): 每一列的变换次数之和

5.boardBuriedHoles(空洞数): 各列中的空洞的小方格数之和

6.boardWells(井数): 各列中“井”的深度的连加和,井是指中间一列为高度低于左右两列的情况,整体呈现为凹字形

7.holeDepth(空洞深度):各列所有的空洞的空洞深度之和

8.rowsWithHoles(存在空洞的行数):存在空洞的行的行数之和

启发函数定义为:

value = x1 × landingHeight + x2 × erodedPieceCellsMetric + x3 × boardRowTransitions + x4 × boardColTransitions + x5 × boardBuriedHoles) + x6 × boardWells + x7 × holeDepth + x8 × rowsWithHoles

x1: -12.63 x2: 6.60 x3: -9.22 x4: -19.77 x5: -13.08 x6: -10.49 x7: -1.61 x8: -24.04

  以上三种启发函数我都进行了尝试,呈现出的效果是第二种和第三种启发函数明显要比原始的Pierre Dellacherie算法的启发函数更加的优秀,但依旧会有不小的几率中途方块触顶死掉。我分析这其中的原因可能是比赛所有的方块序列都是既定的,而且各个方块的出现次数不一样,s型和z型方块的出现频率明显要高于其他I,L,J,T,O型方块。

  既然AI算法也有可能方块触顶 game over,那么该如何调整呢。我采取的方法是当游戏过程中方块堆叠过高超过设定阈值时,转为手动操作方块下落,AI做不到的事情我来手动完成。当通过我的手动操作,方块堆叠高度又下降到阈值以下后,又转换为AI算法进行操作。在这样做了反复尝试之后,分数最高可以达到23、24万左右的样子。

  随后,为了进一步提高分数,我又在算法中进行了小的调整——在使用AI算法进行自动方块下落的过程中,始终保证局面中最左边的一列中没有空洞,如果当前下落的位置会使最左边的一列出现空洞,即使局面评估分数再高也不选择这个位置进行下落。保证最左边一列没有空洞,这样会使得消去时一次消去多行的可能性有所增加,增加分数倍率,同时也使得局面中的方块堆叠高度维持在一个中等水平,不会太高也不会太低,也可以增加单次消去分数增加量,体现了“富贵险中求”的精神。

(项目源码中官方在注释里给玩家的建议:富贵险中求)

“富贵险中求”
“富贵险中求”

  但这样操作又使得AI算法触顶暴毙的概率进一步增大了,就算切换成手动操作模式我也无力回天,那么又该怎么办呢?我想到的方法是——再设置一个高度阈值,当局面中方块堆叠高度低于这个阈值时,AI算法采用激进模式——保证最左边一列没有空洞,但是当堆叠高度高于这一阈值时,AI算法采用常规模式——不必保证最左边一列没有空洞,这样来回转换AI算法模式,使方块堆叠高度在一个高度区间内反复横跳,分数的增速也比只采用常规模式来的更快。这样进行设置之后,也需要注意一个问题,就是当常规模式切换成激进模式时,需要保证切换的一瞬间局面中最左边一列是没有空洞的,不然就会导致激进模式下最左边一列一直不被填充。

  为了AI算法不死几率进一步提高,我依旧在此基础上设置了手动模式的开启阈值,以及一个激进模式和常规模式的转换触发按键。

  最终我的最高分数来到了31万多一点,排在全国第49名。

3.反思问题

  虽然我最后也是搭上了前50名的末班车。但其实在比赛过程中我还是可以总结出很多问题,首先就是在算法的选择上欠妥,这种启发式搜索算法仅仅只能最大程度的保证游戏的不死性,但对于如何尽量的去获得更高的分数还是无能为力的,即使我为了提高分数在该算法的基础上做出了一点点的改进,但分数提升幅度依然不大,相较于第一名的100多万还是有着很大很大的差距。其次是设计算法时对于如何更有效的提高分数考虑不足,错误的把关注重点放在了如何通过手动模式辅助AI算法去“凑”一个高分,也导致了最终的分数进步幅度一直很小。

  这些方面的问题在比赛后期一直阻挡着我冲刺更高的分数,引以为戒。

4.比赛源码

  比赛源码我放在了我的github中,地址:https://github.com/HelloWorld-Ian/tx_geekGame

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
1 条评论
热度
最新
感谢选手带来的参赛经验分享!云加社区欢迎有技术比赛获奖经历的竞赛爱好者,入驻赛事俱乐部,首批成员可直接领取「限量礼包」。复制链接在浏览器查看「活动详情」:https://cloud.tencent.com/developer/article/1860760
感谢选手带来的参赛经验分享!云加社区欢迎有技术比赛获奖经历的竞赛爱好者,入驻赛事俱乐部,首批成员可直接领取「限量礼包」。复制链接在浏览器查看「活动详情」:https://cloud.tencent.com/developer/article/1860760
回复回复点赞举报
推荐阅读
编辑精选文章
换一批
俄罗斯方块进阶--AI俄罗斯方块
所谓让机器自己去玩俄罗斯方块,就是让机器计算当前方块的所有形态可放置的所有位置,然后根据统一的评价标准,计算出最优的位置进行放置。这个评价的标准简单的来说就是:板块放置的位置越靠下越好,方块之间越紧密越好,自身对消除行的方块贡献数量越多越好,但是这里还要注意的是不可为了追求消除行数,而去造成过多的空洞,这样也是不合理的。
abs_zero
2019/03/06
1.7K0
俄罗斯方块进阶--AI俄罗斯方块
【参赛经验分享】鹅罗斯方块解题报告: 遗传算法+分段策略
月初看到TEG公众号推送的极客挑战赛, 主题居然是完成俄罗斯方块的游戏, 顿时来了精神. 想起当初编写各种QQ游戏大厅外挂的快乐时光, 已经快十年了吧.
UME
2021/08/14
2.3K1
【参赛经验分享】鹅罗斯方块解题报告: 遗传算法+分段策略
【参赛经验分享】中年男人写的俄罗斯方块AI外挂,47W分只为爱妻拿一个腾讯视频会员卡
在盆友圈里收到消息,鹅厂举办了一场俄罗斯方块的刷分比赛,私聊一下发图的同学拿到了体验连接,好像还挺简单的嘛,遂决定抽空参赛。
熬夜拧魔方
2021/08/22
2.3K4
【参赛经验分享】中年男人写的俄罗斯方块AI外挂,47W分只为爱妻拿一个腾讯视频会员卡
【参赛经验分享】论 1,413,876 分的成绩是怎么打出来的
七月末的时候看到了腾讯极客挑战赛第四期,发现这不是俄罗斯方块嘛,是之前 Botzone 玩过的 AI 游戏,于是决定来玩玩。没想到一玩玩了好几天,最后的程序也和之前在 Botzone 写的 AI 完全不一样了,最后以 1413876 的分数拿到了外网赛道的第一,同时该分数也是内外网赛道的最高分。
Nano
2021/08/12
1.9K4
【参赛经验分享】论 1,413,876 分的成绩是怎么打出来的
【最强大脑】全球脑王的极客挑战赛之路:1413876分夺冠如何炼成?
导语 | 在腾讯云+社区联合腾讯码客、腾讯安全平台部全新打造的创新赛事【腾讯极客挑战赛 | 鹅罗斯方块】中,4570名参赛者为我们带来前所未有、异彩纷呈的作品。一场技术竞技,把一群志同道合的开发者聚集在一起,激发好奇心和极客精神,这是云+社区举办赛事的初衷。最终来自清华大学计算机科学与技术系的郑林楷在激烈的竞争中脱颖而出,斩获冠军!此次我们特地邀请郑林楷执笔撰稿,聊聊他以1413876超高分夺冠的那些事! 选手介绍 郑林楷,目前就读于清华大学计算机科学与技术系,主攻Web安全领域。第6季《最强大脑之燃
腾讯云开发者
2021/08/27
8230
【腾讯内部赛道-极客挑战赛第四期季军】GPU动态规划鹅罗斯方块
鹅罗斯方块挑战是由10000个方块序列构成的鹅罗斯方块游戏,其中包含了大量的s型和z型,以及少数的I型方块。
用户8813955
2021/08/20
8110
【参赛经验分享】腾讯内部赛道-鹅罗斯方块赛事笔记
我在过去,写过不少游戏AI,所以当看到公司有这样一个比赛很是高兴。不巧比赛的两周刚好项目组特别忙,但我仍希望能在有限的时间来做得更好。
Agent
2021/08/20
1K1
【参赛经验分享】腾讯内部赛道-鹅罗斯方块赛事笔记
201604-2 试题名称: 俄罗斯方块
注意:先分析问题,不要急着分类讨论,你可能分类讨论上百行还不如仔细分析后写几十行。
种花家的奋斗兔
2020/11/13
5070
【参赛经验分享】游戏开发者在"鹅罗斯方块"比赛中的体验(82W)
在游戏开发者的角度来看这道题目的时候,我先想到的是上手打一打看看跟平常的俄罗斯方块有什么不同。结果发现不仅方块出现的顺序是一样的,而且感觉并不是通过随机得到的这一组序列。然后在F12里面看到了具体的规则和一些API,然后就想到可以把核心代码和game代码直接拷贝出来在本机运行,因为最后的答案只需要提交一个操作序列就可以。
京和
2021/08/23
9671
【参赛经验分享】腾讯内部赛道139万分解题报告
我参加的是腾讯内部赛道,最后得分 1395326,在内部赛道排名第一。将内网的解题报告搬运一份到云+社区:
chys
2021/08/16
9551
【计算机本科补全计划】CCF计算机职业资格认证 2016-04-1/2(俄罗斯方块)详解
正文之前 果然,上一篇文章结尾的预言果然一语成谶,2016-09-4我果然没做出来。没错,昨晚到现在都没有做出来,当然,也是我做了一晚上心灰意冷,然后去欺负本文的CCF 2016 - 04 去了 bu
用户1687088
2018/05/07
7950
【计算机本科补全计划】CCF计算机职业资格认证 2016-04-1/2(俄罗斯方块)详解
【参赛经验分享】鹅罗斯方块内部赛道Rank5——硬搜
前言 首先简要概括一下题目,是一个序列完全固定为10000个的俄罗斯方块游戏,需要给出一个操作序列来最大化得分,得分的多少与单次消除的行数和场上已有方块数有关。 主要使用到的算法有: 贪心 单步dfs搜索 蒙特卡罗搜索 除了搜索我还能会点啥嘛,就硬搜 先上代码仓库:https://github.com/Suikasxt/tetris 内容主要在以下两个文件中: GameController.cpp:游戏主体逻辑 tetris.cpp:策略算法 因为代码本来也不是奔着分享写出来的,就不要指望有多好看。 贪心
用户5556120
2021/08/20
7921
C++实现俄罗斯方块(附代码)
  还记得俄罗斯方块吗?相信这是小时候我们每个人都喜欢玩的一个小游戏。顾名思义,俄罗斯方块自然是俄罗斯人发明的。这人叫阿列克谢·帕基特诺夫。他设置这个游戏的规则是:由小方块组成的不同形状的板块陆续从屏幕上方落下来,玩家通过调整板块的位置和方向,使它们在屏幕底部拼出完整的一条或几条。这些完整的横条会随即消失,给新落下来的板块腾出空间,与此同时,玩家得到分数奖励。没有被消除掉的方块不断堆积起来,一旦堆到屏幕顶端,玩家便告输,游戏结束。
墨明棋妙27
2022/08/24
10K4
C++实现俄罗斯方块(附代码)
【参赛经验分享】含可以手玩的网页版(带AI)
简单看了一下游戏源代码,可以发现:(1)游戏里面共有10000块;(2)游戏里面每一块都是确定的,和操作无关。
用户8875579
2021/08/22
1.1K1
【参赛经验分享】分析js代码开启游玩新世界与Pierre Dellacherie算法本地验证
以下仅是我对于这个比赛的思考过程,可能是拿高分的技巧,但我并没有因此拿高分,本人算法水平有限大佬勿喷,对文章中的问题欢迎指出。
一颗小树
2021/08/13
2.8K2
【参赛经验分享】分析js代码开启游玩新世界与Pierre Dellacherie算法本地验证
【参赛经验分享】外部赛道Rank 2解题报告:状态取舍下的动态规划
在七月末,出于偶然了解到腾讯极客挑战赛这个充满趣味性和挑战性的竞赛,于是便报名参加。这次第四期的赛题叫做“鹅罗斯方块”,要求参赛者用所能尽到的各种方式,在一个JS开发的俄罗斯方块游戏中取得尽可能高的分数。经过一周多的持续思考与努力优化,最终通过动态规划+状态取舍,拿到1378178分,获得外部赛道银奖,也算是如愿以偿。下面是我的比赛经过:
Max.D.
2021/08/17
1.1K1
【参赛经验分享】无需关心算法的渐进式解题思路
这是一篇 腾讯极客挑战赛第四期:鹅罗斯方块 的参赛经验分享。这个参赛的主要内容大致是玩俄罗斯方块,最后比较得分。和正常俄罗斯方块不太一样的是这个比赛随机种子被固定了,方块落下的顺序是固定的(方块数量也固定了 10000 的上限),而且得分和你消行时场地上存在的方块数量有关。
白水
2021/08/16
1.4K1
【参赛经验分享】无需关心算法的渐进式解题思路
MFC俄罗斯方块
使用MFC设计一款俄罗斯方块。实现方块下落,方块移动,方块叠加,方块变形,消行等功能。
立羽
2023/08/24
2110
MFC俄罗斯方块
【参赛经验分享】俄罗斯方块的Rust解题记录(腾讯内部赛道第7名)
最近一直在学习 Rust。想起以前每次学习新语言,都会实现一个俄罗斯方块来验证对语言的掌握,但是从来没有尝试去实现其AI。正好这次碰到这个挑战,所以没有多想就使用 Rust 来做此题了。
INmouse
2021/08/20
1.1K1
【参赛经验分享】俄罗斯方块的Rust解题记录(腾讯内部赛道第7名)
Java实现俄罗斯方块小游戏。(附完整源代码)
俄罗斯方块是俄罗斯人发明的。这人叫阿列克谢·帕基特诺夫(Алексей Пажитнов 英文:Alexey Pazhitnov)。俄罗斯方块原名是俄语Тетрис(英语是Tetris),这个名字来源于希腊语tetra,意思是“四”,而游戏的作者最喜欢网球(tennis)。于是,他把两个词tetra和tennis合而为一,命名为Tetris,这也就是俄罗斯方块名字的由来。
百思不得小赵
2022/12/01
5.9K1
Java实现俄罗斯方块小游戏。(附完整源代码)
推荐阅读
俄罗斯方块进阶--AI俄罗斯方块
1.7K0
【参赛经验分享】鹅罗斯方块解题报告: 遗传算法+分段策略
2.3K1
【参赛经验分享】中年男人写的俄罗斯方块AI外挂,47W分只为爱妻拿一个腾讯视频会员卡
2.3K4
【参赛经验分享】论 1,413,876 分的成绩是怎么打出来的
1.9K4
【最强大脑】全球脑王的极客挑战赛之路:1413876分夺冠如何炼成?
8230
【腾讯内部赛道-极客挑战赛第四期季军】GPU动态规划鹅罗斯方块
8110
【参赛经验分享】腾讯内部赛道-鹅罗斯方块赛事笔记
1K1
201604-2 试题名称: 俄罗斯方块
5070
【参赛经验分享】游戏开发者在"鹅罗斯方块"比赛中的体验(82W)
9671
【参赛经验分享】腾讯内部赛道139万分解题报告
9551
【计算机本科补全计划】CCF计算机职业资格认证 2016-04-1/2(俄罗斯方块)详解
7950
【参赛经验分享】鹅罗斯方块内部赛道Rank5——硬搜
7921
C++实现俄罗斯方块(附代码)
10K4
【参赛经验分享】含可以手玩的网页版(带AI)
1.1K1
【参赛经验分享】分析js代码开启游玩新世界与Pierre Dellacherie算法本地验证
2.8K2
【参赛经验分享】外部赛道Rank 2解题报告:状态取舍下的动态规划
1.1K1
【参赛经验分享】无需关心算法的渐进式解题思路
1.4K1
MFC俄罗斯方块
2110
【参赛经验分享】俄罗斯方块的Rust解题记录(腾讯内部赛道第7名)
1.1K1
Java实现俄罗斯方块小游戏。(附完整源代码)
5.9K1
相关推荐
俄罗斯方块进阶--AI俄罗斯方块
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档