我们如何合并编程IT-Planet Final

我们还不错,但是有很多错误。 在大约7个小时内为“曲棍球”游戏开发人工智能。

最初,这篇文章是针对参与者的策略,他们在比赛中设法做到的事情以及他们对所做的工作是否满意而计划的,但是在采访了八名决赛选手之后,很明显,一切都没有了,改变方向是当务之急。

事实是,对于我们感兴趣的问题,我们最多收到6个单词,然后我们立即听到参与者遇到的错误的不满 。 只有一个人写道:
我不想写任何否定的东西,我认为这是不正确的,组织者自己应该为此感到难过。 因此,尽管我个人并不十分喜欢这种形式的比赛,但我会说分配的想法很有趣(Anna Prozorova)。

从文章标题可以明显看出,我们一无所获。 是的,它是“我们”。 在比赛的日子里,我结识了很多好朋友,包括本文的合著者Anna( odrus )。 同样在最后一刻,我们与Leo( zadamantiy )进行了交谈,并在他的允许下描述了参加决赛的情况。

就个人而言,我是“无投诉世界”运动的成员,但另一方面,我会悬挂手镯并抱怨(尽管是漫画形式),因为另一方面, 这是比赛的条件,您需要成为一名出色的专家才能赢得比赛并应对缺陷! 相反,我们没有任何投诉-非常感谢!

在削减的基础上,除了描述游戏规则,比赛规则和发现的错误外,我们还将与您分享一下门框,我们个人遇到的问题以及我们如何解决该问题,如何为比赛做准备。 如果您参加过这样的比赛,也许您会意识到自己。

本文的目的是从参与者和组织者那里收集竞赛失败的内容,将它们砍在您的鼻子上,再也不会踩到同一把耙子。 我们希望本文能提高下届比赛的水平。



引言


关于我们的几句话


伊利亚


自2017年以来,每年都是俄罗斯AI杯和Mini AI杯的参赛者。 我也关注Codingame和Halite。 我没有什么特别的成就,但是我从别人那里学到了很多东西。 对我来说,最主要的不是参与,而不是胜利,而是献出100%的心血,最后说:“我竭尽所能,意识到我想要的一切,运用了我所知道的一切。” 我不知道Java编程语言。 对我而言,这是从竞赛到竞赛以全面研究新技术堆栈的一种普遍做法。

安娜


一个简单的学生,在解决算法问题方面经验很少,但是在参加奥林匹克竞赛和类似比赛中却没有太多经验。 具体来说,我决定参加IT-Planet,以测试我的知识和能力,积累经验,与有趣的人交流。 她在大学学习过Java编程语言,但是很长一段时间都没有实践经验。

雄狮


他参加了ICPC的各种选择,例如“ Build University 20.35”和“ Digital Breakthrough”之类的黑客马拉松。 好吧,一些大学奥林匹克运动会的小事。
因此,我们的大学通常会派许多人参加sql竞赛,但今年不是。 我被邀请参加Java,我必须在与会话同时的很短时间内为自己处理一种新语言。 在It-planet之前没有参加。

比赛说明


一般职位


IT-Planet是针对IT领域的学生和年轻专业人员的竞赛,其目标是确定和支持有能力的人。 自2007年以来每年举行一次。 参与是一个证明自己的机会。

“ Java编程”提名有助于找到在学习过程中获得的知识的实际应用。

资格考试的第一阶段是缺席,是针对注册教育机构学生的在线考试。 这些问题非常复杂且有趣,但是老实说,大多数问题都包含可以重新读取和运行的代码。

与第一阶段一样,第二阶段排位赛也缺席。 它旨在解决体育节目编排问题。 用了两天的时间来解决10个问题,从而有可能为解决特定问题做充分的准备,以研究算法/方法。 但是,没有人能应付所有任务。 比赛中某些任务的状况发生了变化。 测试中有学校。

全日制国际决赛。 必须为“冰球”游戏编写AI。 约7小时。 近似值是由于缺乏开始的“超前”和对午餐的不理解。 时间是艰辛的,观众并没有关闭,但下面的内容更多。

工作任务


该任务由SimbirSoft LLC的专家开发。 以下是每个参与者收到的.pdf文件的内容(本文的最低修订)。

工作任务
任务说明

在一个神秘的国家中,所有居民都是小型机器人的某个地方,有两支球队打曲棍球。 这两支球队都有自己的私人机器人教练,他会不断监控比赛并告诉所有球员他们需要去的地方。 一切都会好起来的,但是机器人手只能理解简单的动作,例如去,击球,到达教练设定的点。

您必须成为红队球员的教练。 一支蓝队将与您对战,这由已经成功击败其他球队的算法控制。 在同一时间,有2个团队参加比赛。 球队由4名球员组成:前锋,2名后卫和门将。

您的任务是编写用于管理红色机器人的算法。 要控制字符,您将有3种方法,如下所述。 还有一种方法可以接收有关场上所有球员和冰球坐标的信息。

游戏限制

守门员只能从球门到达中场。 除了守门员区域(球门附近的红色半圆)以外,防守者和攻击者都可以在整个场地骑行。

应用程序结构说明

该应用程序显示为客户端和服务器。 该服务器将打包到一个jar文件中,并在后台启动。 服务器包含角色和冰球运动的所有基本逻辑,存储有关所有角色,冰球,时间和得分的信息。

当应用程序启动时,客户端与服务器建立连接,并以给定的频率从服务器接收数据。 他还负责在冰球场上渲染所有角色,目标和冰球。

所有程序代码都必须在客户端应用程序的algoritm文件夹中的Algoritm类中编写(其他文件中的所有更改均不考虑在内)。

此类中提供以下方法:

  • move(playerType,x,y)-一种将玩家移动到地图上指定点的方法。
  • kick(playerType)-特定玩家击球的方法。
  • turn(玩家类型,角度)-一种用于旋转特定玩家的方法。
  • getInfo()-获取有关地图上所有玩家和冰球的信息。

还有一个静态变量级别,它负责算法的复杂性级别。 以下级别将适用于奥运会的参加者:

  1. 蓝队站着;
  2. 蓝队随机穿过田野;
  3. 蓝队按照“弱算法”比赛;
  4. 蓝队按照先进的算法进行比赛(用于内部测试)。

所有接受playerType的方法仅适用于红队球员。
playerType变量是PlayerType类的实例,并且包含
值,例如守门员,后卫1,后卫2,前锋。

在Playground类中,写入游戏的常数值(例如,中场,守门员区域等)。

getInfo()方法返回GameInfo类的对象。

细化

  • 如果多次发送move方法,则角色需要到达的端点将发生变化(因此,如果需要到达端点,则必须等到角色到达端点之后再将其发送到另一个点)。
  • 踢球方法只能用于拥有冰球的球员。
  • 转弯方法采用一个角度,而对于田野的下侧,角度采用的值从0(朝向敌人的目标)到180(针对自己的目标),对于上半圆,角度采用的值从0到-180。




评估标准


也摘自.pdf文件。 仅使用来自Algoritm类的代码。 每个参与者的算法将依次针对所有难度级别运行。 根据运行结果,将为比赛结果设置分数,并且还将为算法中已实施机会分配分数。

标准清单
  1. 进球必须从不同角度进行。 例如:在玩家面前,是敌方守门员-必须以一定角度对目标进行攻击。
  2. 球员将球传给自由曲棍球球员,对球门进行进攻。
  3. 仅在球员自己不能进攻(进攻的所有角度都闭合)的情况下才可以传球。
  4. 只能将通行证提供给可以自由通过的球员。 具有进攻目标的曲棍球运动员是优先考虑的。
  5. 如果无法进行进攻,则团队必须撤退并重新分组。
  6. 添加。 积分,如果他们通过转机离开。
  7. 添加。 如果您使用守门员进行重新分组,则为要点。
  8. 在防守中,传给对手另一位球员的能力应该被阻止。
  9. 玩家的团队坚持策略。 例如:1个防御者总是在敌方反击的情况下保持一定距离。
  10. 该算法将计分板考虑在内。 例如:在输钱的情况下打得更积极一些,在输钱的情况下反之则更小心; 在比赛结束时平局会增加攻击性。

奖励积分将授予:

  1. 玩家通过自己的进球得分。
  2. 曲棍球运动员互相阻挡。 (不要让对方通过)。
  3. 故意阻止游戏。 例如:将冰球推向冰球,直到游戏结束。


主体


比赛准备


伊利亚


最初,他们写道,最终将出现“工业发展”。 我希望可以正常使用GUI开发基础。 例如,用于记账的应用程序。 悲痛欲绝,我同意了决赛,因为我对自己要做的事情不太满意。 然而,在9月17日,一封带有决赛规则的信到了,并据报道:“有一个计算机2D游戏“曲棍球”,计算机机器人根据某种算法进行游戏。 有必要使用Java编程语言来实现一种算法,根据该算法参与者的角色将“行动起来”(在网站上写着可以更改任务)。 我立即想起了2014年俄罗斯人工智能杯。 我很高兴并意识到,我同意参加并非徒劳。

我再次去的第一件事是阅读获奖者的文章 。 总的来说,我记得那里是什么,但并不是所有的时刻都是清楚的。 然后,我去了比赛网站并阅读了规则。 我停在这里,因为对规则的任何修改都可以完全改变整个游戏。 我不知道他们的游戏中将有多少位物理学家,不知道如何选择拳头和冰球,等等。 游戏可以大大简化,甚至不需要角落。 所以我开始等待...

等待,等待! 9月27日下午,有一封关于网络研讨会的信! 9月28日19:00。 对我来说,这是完美的一天和时间。 但是...但是,在预定发射前4个小时,又收到一封来信,转至17:00! 转移函是在开始前一个小时到达的……我尽力飞了,迟到了15分钟(我没想到仍然要安装Flash Player)。

在网络研讨会上,他问了一些问题,并对游戏进行了大致了解。 有足够的数据,甚至可以编写自己的数据并进行充分的准备。 但是,直到最后还不清楚如何造成打击,开发人员并未透露某些要点,而且在某些地方,他们自己还没有决定要结束。

写下所有最有价值的东西之后,我去了与RAIC熟悉的活跃成员交谈。 您好,感谢m0rtidoDragoonXenoreshn1k 。 概述了这种情况后,很明显,有必要对ifa进行硬编码,并且不能在此期间谈论世界的任何模拟。 oreshn1k分享了轰炸书“通过实例编程AI”,其中第四章谈到了足球AI的设计。 我非常喜欢这本书,因此决定自己为自己拟定比赛中要写的全部策略,而完全忘记了时间限制。 我要写的内容不适合参加本次比赛...

我可以在quire上完成我所做的无用准备(整洁,已经有168个任务。在某些地方有说明)。 对于这次比赛没有用,但总的来说,它是对从本书中学到的知识的极好的系统化。 在那里,我考虑过模拟冰球,以便在一段时间后找出它的位置,为射门找到合适的角度,在球员之间转移冰球的逻辑和一堆有趣的事情。

我在上面已经写过,不知道如何用Java编写,因此,除了策略之外,我还开始研究该语言的语法。 这得益于出色的网站,我已经使用了不止一次了- 在Y分钟内学习X。 进入IntelliJ IDEA之后,我意识到用C#编写完全相同。

经过这样的准备,我去了莫斯科。

安娜


当我了解大结局的主题时,我决定要重复的第一件事就是岩浆。 为了使所有事情变得更加有趣,我使用了Processing来完成所有工作:我查看了开发人员与运动,计算角度,速度和加速度有关的示例,然后在我的小草图上进行了练习。

我决定不浪费时间来刷新Java的某些细微之处,因为在我看来,该任务建议了编写策略的技巧和一些数学知识。 因此,我决定阅读RAIC 2014获奖者文章 。 这篇文章很有趣,但是对于本次比赛并不特别有用,因为物理学可能会发生根本性的不同,并且会花费更少的时间。

开发人员的网络研讨会非常有趣且有用,它对游戏进行了总体介绍。 但是,不幸的是,我无法完全观看它,因为广播是使用Flash进行的,那时我的笔记本电脑决定播放蓝屏死机。

结果,就在决赛之前,我没有提前制定策略:当不披露游戏物理细节时,很难计划一些事情。 首先,有一些想法是值得关注的,立即编写什么辅助方法,但仅此而已。 我认为结局之前的主要目的是放松,获得充足的睡眠并保持心情愉快。

雄狮


[准备]大约16-20小时。 因此,我考虑了几何学,不幸的是,我并不是很矛盾。 事先准备好的公式和计算,可以测试所有内容。 我欣赏了可以根据组织者在网络研讨会上给出的条件进行评分的区域,然后编写了一些动作的模拟器,并获得了该区域在直接模拟不同角度的射门和最佳门将策略时的外观。 结果,几乎没有什么用处,我不得不在拐杖上写拐杖。



时间分配


伊利亚


我在比赛和奥林匹克竞赛的时间分配上总是遇到问题。 我第三次踩了耙子。 第一次讲话后,他说他永远不会允许这样做。 他再次坐下来完成一项任务,很长时间没有切换到另一项任务。

午餐前整个比赛的第一部分花了很多时间,用于实施团队成员的各种包装,状态类,他们之间的消息,内部角色。 总的来说,我继续参加比赛之前制定的任务,完全忘记了有经验的参与者对硬编码if和辅助方法的建议。 他只是写而没有考虑时间。

我在晚餐时感动了。 我知道比赛已经结束了一半,而且我还要再工作10个小时,这样至少有些事情才能开始。 决定离开一切,从头开始。 这是比赛的最后几个小时,当我停止感到悲伤和对机器人行为的咯咯笑声时。 很快就开始从一个任务切换到另一个任务。 他没有去那儿-他换了另一个,然后他回来了。 只有一种愿望-至少得分,至少得分。 因此,它完全被遗忘了代码和OOP的简洁性,留下了一些有趣的注释。

安娜


首先,我决定弄清楚游戏中的基本方法是如何工作的:曲棍球运动员的动作,冰球的捕捉,转身和传球。 我花了大约一个小时。 我还研究了曲棍球运动员和冰球所拥有的数据和方法。 然后我决定,学习如何找到两个物体之间的角度(尤其是曲棍球运动员和冰球之间的角度)将是一件很棒的事情。 我对此遇到了很大的困难:首先,我很长一段时间就想出了Math.atan2方法,然后尝试将接收到的数据转换为开发人员角度的系统。 经历了所有这些,我在晚餐前遭受了折磨,感到非常沮丧,因为我花了很多时间来完成一项小任务,尽管在同一时间我至少可以为第一级写一份策略。

午饭后,我决定更合理地分配时间。 通过确定角度快速完成该方法,然后为第一个级别编写了策略。 然后,她顺利地进行了第二阶段的策略,最后在第三阶段应用了该策略。 实际上,这一直坚持到我的曲棍球运动员表现异常时,我一直坚持到决赛结束。 原来的代码很糟糕,不可读,带有大量ifs和复制粘贴,但是它或多或少地满足了它的任务:我的曲棍球运动员进球了。

雄狮


在给定的时间(7个小时,对于这样的比赛来说这真是太少了),他制定了一种简单的算法,能够以令人沮丧的分数持续赢得1-2个级别。然后,根据具有第3级的随机事件,该算法将得分从0-2降低为6-0。不幸的是,不可能看到第四级。同时,我敢肯定,在这段时间内您可以编写一个更好的选择,但是为此,您需要了解某种周转的工作方式,但是组织者在这里耸了耸肩,说我们不明白为什么会这样。

大多数情况下,弄清楚项目中的工作方式和工作方式尤其令人恼火,因为.equals()和两个字段.TypeOfPlayer和.PlayerType不起作用,它们返回的结果完全不同。嗯,组织者确实无法解释玩家的某些奇怪行为(而且我们不知道为什么您的角色在唯一的给定团队中背靠背骑在这里,并且已经提到过:)。然后,在某个时候,事实证明该项目中存在针对不同游戏对象及其位置的大小的常量,似乎最初应该在参考资料中,但最终没有,这浪费了计算它们的时间。用手。

我们的门框


伊利亚


  • 我的主要观点是时间的糟糕分配和多余抽象的徒劳写作。当您有7个小时的时间时,如果您想赢,请编写一个错误的不受支持的代码。
  • 罗夫与岩浆。我仍然不知道应该添加哪个角度以及服务器如何处理它,所以360%就在那里了,也许90 +,也许180,也许所有270。我根本没有考虑过它,只是把它放在任何机会上...

    double res = 180 / Math.PI * Math.acos((pp.x - tp.x) / pp.dist(tp)); return (90 + (int) res) % 360; 
  • 比赛结束前约40分钟,我决定进行比赛,该比赛是为了寻找最接近冰球的球员。 原来是我的Paint类的squareDist方法具有符号-,而不是坐标差的平方之间的+(顺便说一下,在quire任务中也是如此-)。 有了这样一个错误,我考虑了几个小时的绝对距离...
  • 在比赛开始之初,我始终牢记着将来获得冰球的位置。 这需要它的速度。 事实证明,从世界的现状来看,没有任何有用的东西(我认为这是组织者的门,取决于其他相同格式的比赛提供了什么)。 因此,必须基于在游戏中不同点的位置获得相同的冰球速度。 我花了很多时间进行调试,却不明白为什么数据如此之少(每5毫秒一次)。 通常,我无法完成错误的计算,但是在比赛结束前一个小时,我注意到组织者在我的策略中留下了一段有趣的代码:

     try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } 

    将值设置为10时,我收到了非常频繁的数据更新,未注释负责获取速度的代码部分,并且它起作用了! 大约20分钟后,我听到了参与者向组织者提出的有关这段代码的问题,他向他解释说这是特别为我们完成的,因此开发起来会更容易。 在那一刻,我微笑着,意识到我不是唯一一个这么晚才意识到这一点的人。

安娜


  • 像Ilya一样,我一开始就无法正确分配时间:我花了很多时间来完成一项虽然有用的小任务,但是我必须教曲棍球运动员进球。
  • 她浪费了很多时间,因为她忘记了Math.atan2方法的签名:首先出现y,然后出现x。 我做了相反的事情。
  • 当编写一种方法来确定在路径的某一段上是否有敌方曲棍球运动员时,我犯了两个错误,因为有时曲棍球运动员会拒绝向任何地方移动。
  • 总体而言,比赛没有得到足够重视。 一个人可以做得更彻底,最后做得更加勤奋和专心。

雄狮


  • 日志中的前两个小时都是在盟军的命令下两次随机迭代,而不是第二次在机器人的命令下进行了迭代。

组织者浅滩


  • 很少有数据可以轻松编写强大的策略。 给我们的是控制场上球员位置的四种方法。 是的,冰球也有它的主人。 从常数可以访问领域的中心,守门员和目标区域。 谢谢您,但是在我们看来,下面的值列表只是必要的。 我们只是cr住了他们!

    1. 球员的速度(每个角色都有自己的速度),冰球;
    2. 有关降低冰球速度的信息;
    3. 球员的起始位置;
    4. 球员,冰球的大小;
  • 在网络研讨会上,开发人员明确表示,将无法获取服务器的源代码。 关于某些打包程序,据说.exe会滑动。 “混淆”一词没有闪烁,而是暗示。 实际上,我们得到了一个.jar文件,该文件将在几秒钟内反编译,不仅可以获得参与者缺乏的游戏物理原理的常数和逻辑,而且还提供了与我们对抗的3层机器人的源代码。 不幸的是,我回到家时就注意到了这一点,并在比赛后听到了有关反编译的信息。 他们讲述了有人在结局中如何使用它。 如果这是真的,那就太不愉快了。 在这样的时刻,您开始后悔只有一个合适的人。
    但是在这种情况下,这不是很诚实(Alexander Polishchuk boba-alex )。
    好吧,他们使用它做得很好,因为规则中没有禁令,但他们决定不通过混淆器,因此它是奥林匹克运动会的一部分(Maxim Pyankov maxzxwd )。

  • 曲棍球运动员可能会在场上随机消失,直到比赛结束才露面。 您可以将玩家推入守门员区域。

  • 调用move()方法时,曲棍球运动员可能转向了错误的方向。 因此,它可能类似于“月球漫步”。

    录影带

  • turn()方法将玩家部署到某个点的速度明显慢于move()方法(在正确的方向上有自动转弯)。 通常,这与另一个曲棍球运动员发生冲突。 两种方法的比较:

  • 反射角差。 从侧面弹起后,速度非常快(视频速度降低了4倍)。 即使她已射中目标,洗衣机也不需要。


    为了进行比较,以直角通过的示例为例,其中一切都很好,速度很快,但速度变慢。

    录影带

  • 敌军的攻击者更靠近战场中心,并在回合开始时立即拦截了冰球(不在战场中心的冰球也是正常的)。


  • “守门员只能从球门中部到达球门”的限制仅适用于我们的球队,敌人没有这样的规则。
  • 为了使曲棍球运动员能够执行任何动作,必须首先对其中任何一个应用move()方法;
  • 策略代码中的组织者超时,影响了接收新数据的频率。 如果仅删除此代码,所有内容将冻结。 许多人不了解它的目的,也没有收到组织者的解释。 在规则中,代码的这一部分也没有出现。 许多人坐在水坑里。
  • 许多参与者在制定和更改策略级别时遇到问题(事实证明,很少有人知道如何使用maven'om)。
  • 在网络研讨会上,组织者表示Java将使用版本8,但最后,该项目至少需要Java 11。
  • Anna:我坐在一台能正常工作的计算机上之后,由于代码中多余的空格破坏了变量名,因此构建出现了问题。 不是很关键,但不是很好。
  • 在某些计算机上,最初没有任务文件或Internet,并且依赖项加载了很长时间。
  • 参加人数超出预期。 它的发生是由于某种附加功能。 因此,一个人〜13搜寻计算机(某些人拿出了他们的笔记本电脑)时遇到了麻烦,并从头开始了这个项目。
  • 午餐没有严格规定。 他们没有给他们一定的用餐时间,也没有关闭听众。 挨饿的人要多卖一个小时。
  • 上方,在比赛说明中,有一个带有评估标准的小标题。 他们的问题是关于要点的内容,但是没有写出多少和内容。 结果,我们变得不透明,并且普遍缺乏对如何赢得胜利的理解。
    比较接近水平的参与者可能很困难,因为没有明确的特征点分配,只有一个列表。 参与者可以实现不同的功能,但是从所有相同的角度来看,有必要进行比较(罗马)。

结论


结论


总的来说,如果您停止对结局的过分重视,那将很有趣,有趣并且很粘。 是的,我不得不花时间不写策略,而是要应付开发人员的错误。 但是,当您适应并开始遵循他们的规则时,您甚至会从过程中获得一些乐趣。 当然,我希望开发人员对这一任务采取更负责任的态度,并且在不为最终参与者提供未加工和未完成的材料的情况下解决问题。

值得一提的是,本次大结局的获奖者是非常出色的人:在如此艰难和出乎意料的情况下,他们能够聚在一起,弄清一切并提出高质量的解决方案。 尊重这样的男孩。

致谢


首先,我要感谢那些帮助撰写本文并同意回答我们问题的参与者。 不幸的是,由于方向的改变,不需要很多材料。

感谢Anna( odrus ),Leo( zadamantiy ),Alexander( boba-alex ),Maxim( maxzxwd ),Ivan,Roman,Anna,Donat和Alexander。

我还要感谢IT-Planet竞赛本身的组织者,SimbirSoft编程竞赛Java决赛的组织者,尤其是出席决赛并帮助参与者解决问题的开发人员Edward,可以澄清游戏逻辑中不明显的时刻。

感谢您,比赛根本没有像sisharp(亚历山大)那样展开。
决赛的想法很好,也有排位赛的机会(伊万)。

聚苯乙烯


在撰写文章时,比赛和协议的照片就到了,这意味着现在我们可以宣布我们的位置!

伊利亚(Ilya)吸引最多的人-在33中占28-32
安娜-16
狮子座-14

感谢您阅读此处的内容!

Source: https://habr.com/ru/post/zh-CN472248/


All Articles