华为软件精英挑战赛【德州扑克】心得体会

这是华为举办的一个软件竞赛,华为提供一个德州扑克台桌的server,我们要根据牌型等因素,给出出牌的策略,类似模拟牌手的程序。从知道挑战的题目到提交最终版本的程序中间只有一个月的时间,刚看到这个题目一点头绪没有,看了论文有用蒙特卡洛模拟,决策树等,各种没听过的词汇,感觉写出这个程序会很难,和我一个教研室的小伙伴们看到这个题目的时候陆续都放弃了。

思考了半天我也放弃了,因为接下来几个星期还有实习的面试和小论文等着我完成,就这样过了2个星期,期间我把小论文与实习面试都完成了,在一天早晨无意中又点开了比赛的页面,我想试一试,最起码调通一个与sever通信的socket,说动手就动手,先选定编程语言,用的java,java我每天都会编一些小程序,所以用的比较熟练。中午就开始搭建环境,用的unbuntu的环境,以前用的都是VMware来搭建虚拟环境,这次华为指定用的是VirtualBox,很快第一个问题就来了,我用远程登陆工具登陆linux的22端口怎么也登不上去。期间上网查了各种原因,都是无用功,最后只有使用终极大招,将网络连接方式改为host
only,但是这样的方式linux虚拟机就不能联网了。

接下来就要写socket部分的软件了,原以为这是最简单的部分,但就是这部分我改了不下10遍。首先华为的server是用c++写的,所以与java进行socket通信的方式只能用字节流的方式,很快利用最简单的带参数newsocket方法,就与server端建立了链接.问题1很快就来了,由于server端可能比client端启动要慢所以当client端检测不到远端sever端口的时候,就直接跪了。解决的方法很简单在client端加了个延时sleep方法,这个问题就解决了。问题2就是每次启动完后一个client后,运行结束后,立即再运行就不可以,报出unconnect错,这个问题搜了一下就解决掉了,原来是client端可能有端口复用的问题,于是将socket改为无参数newsocket的方法,然后将socket的setReuseAddress设为true,同时为了防止其他的情况,我写了一个while循环,来判断socket是否已经建立,如果没有建立,每隔450毫秒就重新建立,这样的socket就完美了。socket部分就这样完成了,最起码能够与server稳定的建立连接收到注册成功消息。我将策略设为每次都fold,也就是无论什么牌都弃牌,这样除了大小盲要付出筹码,其他的情况都不需要付出筹码,所以全fold的情况最起码能玩到200多局,这时候最诡异的错误出现了,每次到100多局就会出现unconnected。华为提供的server有个机制,就是每次询问你的出牌策略后(notify消息),如果10次没有应答就会把你unconnect,然而我设置的是每次收到notify就发送fold消息,怎么会出错呢。我把每次收到的消息打印到本地文件,才发现原来有的消息发送了一般,有的把下一个消息也发送了,原来这是tcp的通病,叫做粘包。很快我就找到了解决的思路,我把收到的消息统一存储到一个大字符串里,每次截取一个有用信息,这样就解决了粘包的问题。

在解决socket的同时还有一个问题,就是每次启动我的本地程序,都是利用一个game的脚本,由于对shell编程基本是只闻其名,所以看了几小时的博客,算是将就着把shell简单了解下,其实我的shell脚本只要实现一个功能,根据相对路径找到Game.class启动程序,原来linux的简单指令可以直接用在shell脚本中,cd到我的主程序目录,启动我的java程序,就这样搞定了。顺带着把makefile文件的脚本编了,这样每次只需使用makefile脚本就可以完成编译与编译文件的转移了,省的每次都敲一大串javac指令。

完成搭建环境与socket部分已经过了3天了,接着就开始进入出牌策略的环节了,我自己建立了一个模型,包括扑克和对牌局的抽象。扑克的抽象主要是花色和大小,较为困难的是判断牌型的问题。牌局的抽象也很复杂,由于之前根本就没玩过德州扑克,也不知道要提取哪些信息,于是下载了个天天德州,每天睡觉前都会晚上几个小时,与此同时通过看别人的论文,知道了一些德州扑克的常用技巧,建完模型,还没有写出牌策略离提交代码就只剩下不到4天了,而中还没有调通过一次。我把出牌的策略分为两个部分,一个是在拿到两张手牌之前,这个阶段的出牌策略较为简单。一个是在拿到手牌之后,这个阶段的出牌策略就比较复杂,由于时间紧凑,我没有写一些高端的机器学习等策略。就对一些情况做出判断后,给出了不同的出牌策略。这部分也是很难调试,期间遇到各种NullPoint,各种摸不着头脑的错误。但是每遇到一个困难,通过debug都能很好地找到出错原因,java就是比c++好调试啊。

第一次将socket和策略部分联调,竟然奇迹般的成功,没有一个bug。然后就与华为提供的葫芦娃玩了几局,所谓的葫芦娃就是一群只会一个策略的无脑程序,然而就是简单地无脑娃把我得程序各种花式吊打,最终花了一天的时间调试各种参数,总算是能玩过葫芦娃了。最后的一段时间真的很紧迫,要不是组委会决定程序可以缓两天交,我真的就没法完成了。组后的几天基本都是一起床就开始搞,看游戏log,调程序,改bug。某天在贴吧里看到可以把程序发给某个官方的邮箱,就可以在实际的环境中与其他人对决。规则是这样的,随机抽取8人一个牌桌,前四名进如下一轮,我总共比了三次,每次都在round3,看来很稳定啊,谋事在人,成事在天。不可强也!坐等比赛的结果了。

过了大约一个星期出了结果,进入了32强。然而只有区域的4强才能进入决赛,从知道进入复赛到复赛开始只有一个星期的时间。复赛的内容不变,只是我们有了和别人比赛的log,可以作为自己制定策略的参考。复赛的水平肯定比预赛的要强不少,用我的初赛if else程序肯定是没戏的,这时候我看到了一篇哈工大的硕士论文,用的是蒙特卡洛模拟。于是仔细搜了一下这个东东,原来也没有听上去那么高大上,就是尽量多的模拟,来求出你获胜的概率,模拟的次数越多也就越接近真实的获胜概率。就像在一个正方形中有一个内切圆,然后向其中丢黄豆,就可已根据掉在圆中的黄豆的比例求出圆的面积。很快我就把模拟的程序写好了,并且作为一个线程调用,这样就可以开多个线程进行牌桌的模拟了,当然线程数也不是越多越好,在我本机上测试4线程的模拟效率最高。然而结果并不是我想象的那样,每次都被我原来的程序吊打,综合分析原因,还是模拟次数太少,于是开始各种搜,终于在github上看到一个很牛逼的想法,只需32位int整数就可以存储并判断你的牌型,而且所有的牌型都已经存在数组里,判断牌型快的飞起,于是果断的移植,模拟次数瞬间增加了100倍。原来的程序也是各种被花式吊打,然而写完这套程序离复赛只有一个晚上了,并没有在实际环境中与别人比过,当要用这个新程序比赛,其实开始我心里是拒绝的。第一:我的新程序要多线程模拟,所以必须开一个守护线程控制模拟时间,发回消息的时间只有500ms,但是我要尽量多的时间去模拟,所以实际环境中socket的发送,接收延时是我要考虑的因素,毕竟在我的机器上server与cliernt是在一起的,所以延时可以不作为考虑因素。第二:模拟的时间可以从知道自己手牌开始,而不一定是从接收到notify信息开始,但是这存在线程参数的传递与何时结束的问题,因为我知道手牌的时候并不知道牌桌上还有多少人,而我的模拟要知道牌桌上剩的人数,所以在知道牌型的时候,要在不同的人数同时模拟,同时在接到nontify消息的时候找到人数符合的线程获得相应的参数,最终我没有找到好的解决方案。

复赛的结果没给我惊喜,我还是被淘汰了,但是经过这一段时间的编程给我的帮助真的很大,我独立一个人完成了整个项目的建模,编写,调试,测试。这是最让我自豪的一件事。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-26 14:40:52

华为软件精英挑战赛【德州扑克】心得体会的相关文章

德州扑克 2015 华为软件精英挑战赛

概述 华为2015软件挑战赛比赛总结,跟队友当时奋斗了15天吧,最后差点进32强了,第三轮遇到的对手太厉害,止步64强了.这次官方提供 Ubuntu 纯命令行镜像和庄家 Server,选手编写德州扑克选手机器人程序互相 PK(8人一组)500轮后钱多者胜出.运行只要运行华为提供的ne">dist_check_and_run.sh 脚本 即可,里面会给自动运行每个game程序.最近快要找工作了一些项目还是要总结一下的,感觉欠缺的地方还是有很多的,下面进入正题. 梳理一下主干主要这次比赛项目主

<路径算法>哈密顿路径变种问题(2016华为软件精英挑战赛初赛)

原创博客,转载请联系博主! 前言:几天前华为的这个软件精英(算法外包)挑战赛初赛刚刚落幕,其实这次是我第二次参加,只不过去年只入围到了64强(32强是复赛线),最后搞到了一个华为的一顶帽子(感谢交大某妹纸快递寄过来!),今年小较了一把真,幸运地闯进了排行榜.(第17位的就是我们Team噢!耶鲁顾神很给力!)    所以呢,回到正题首先来看一下初赛赛题吧! 初赛赛题要求 已知有向图G的拓扑(结点V,边E)和V的一个子图V’,在G内求一条从start结点到end结点的路径,要求经过V’的所有结点并且

华为软件精英挑战赛2016题解

代码:https://github.com/jinhang/2016_Huawei_SoftWareMatch 前言 赛题源自"未来网络"业务发放中的路由计算问题.算路问题属于基础算法问题,在图论.网络.交通等各个方面均有着广泛的研究与运用,里面不乏一些经典的算法,例如最短路中的广度优先搜索,Dijkstra算法等.网络算路问题的更优算法实现对于网络资源高效配置具有重要价值. 本次大赛分为初赛.复赛和总决赛三个主要阶段,当前为总决赛/复赛阶段. 总决赛/复赛赛题描述 1 问题定义 给定

华为2017软件精英挑战赛初赛源码

2017年三月底四月初跟实验室的小伙伴一起参加了华为的软件精英挑战赛,可惜实力不济,止步于赛区64强,还是倒数几名...... 我们使用了模拟退火+spfa最大流最小费用算法,通过上百次迭代,获取近似解. 核心代码如下: package com.cacheserverdeploy.deploy; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.H

2017华为软件精英大赛复赛体验及最终代码

踉踉跄跄进入复赛,复赛题目出来的那一天,结点数最多10000,边最多10000.感觉我的费用流肯定要崩了啊:都有点想弃赛的冲动: 但是缓了几天之后,还是准备试一试,不能给学校丢人啊,到最后一个0分多尴尬: 复赛最大的变化就是服务器有了带宽上限,这点其实不难解决,计算费用流的时候每次加服务器不再提供无限流聊,提供最大档的流量不就可以了,但是这么做出来的结果cost一直很大:改了好久都没有解决: 还有遇到的参赛以来最大的困难就是输出路径那一块了,初赛的时候也听说好几个人输出路径有问题,搞了好几天,我

华为软件精英大赛复赛体验及最终代码

踉踉跄跄进入复赛,复赛题目出来的那一天,结点数最多10000,边最多10000.感觉我的费用流肯定要崩了啊:都有点想弃赛的冲动: 但是缓了几天之后,还是准备试一试,不能给学校丢人啊,到最后一个0分多尴尬: 复赛最大的变化就是服务器有了带宽上限,这点其实不难解决,计算费用流的时候每次加服务器不再提供无限流聊,提供最大档的流量不就可以了,但是这么做出来的结果cost一直很大:改了好久都没有解决: 还有遇到的参赛以来最大的困难就是输出路径那一块了,初赛的时候也听说好几个人输出路径有问题,搞了好几天,我

德州扑克AI简介——2015华为软件精英赛小结

2015华为软件精英挑战赛的比赛目的是设计德州扑克比赛的牌手程序,采用的是无限注的比赛规则.具体比赛规则见下面链接.在接到这个赛题之初,我们做的第一件事情是熟悉德州扑克的比赛规则,并尽可能去寻找现有的开源项目或者程序.具体来说,着手点主要有四点:维基.论文.比赛和开源项目. 首先阅读的是维基,这里参考的主要是英文的维基百科.通过维基百科,大致了解了德州扑克的发展历史和现状,并且得知在现在每年的都会有人与机器的德州扑克比赛和机器与机器之间的德州扑克比赛.此外,通过维基百科,还了解到当前主流学术界对

2015华为德州扑克入境摘要——软体project

直到6一个月2号下午12时00,华为长达一个月的德州扑克锦标赛落下帷幕也被认为是. 我们的团队一直共同拥有3民,间.一个同学(吴)负责算法设计,一个同学(宋)负责分析消息,而我负责的实现框架设计和详细的决策算法.离5报名早年1月开始,要设置环境,设计框架,任务分工,以及各个模块代码的编写.从我个人的感觉来看,整个过程能够说是一个比較艰辛的历程. 德州扑克是一种棋牌类游戏.属于一种博弈过程,起先我对这个游戏没有不论什么的了解,最多的也仅仅是在影视题材里面见过,可是详细的游戏规则并不懂.而正是在这种

2015华为德州扑克参赛总结——软件工程

直到6月2号晚上零点,为期一个月的华为德州扑克比赛也算告一段落了.我们团队总共有3人,其中,一个同学(吴晓东)负责算法的设计,一个同学(宋振兴)负责消息的解析,而我则负责整个框架的设计以及具体决策算法的实现.从5月份初报名开始,到环境的搭建,框架的设计,任务的分工,算法的设计以及各个模块代码的编写,从我个人的感觉来看,整个过程可以说是一个比较艰辛的历程. 德州扑克是一种棋牌类游戏,属于一种博弈过程,起先我对这个游戏没有任何的了解,最多的也只是在影视题材里面见过,但是具体的游戏规则并不懂.而正是在