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

概述

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

梳理一下主干主要这次比赛项目主要分为一下几大块:

1、Socket注册

开始pk选手向庄家Sever注册自己的信息,这里官方给出的信息作品的运行入口统一命名为game,
支持5个参数( 牌桌程序IP,牌桌程序端口好,牌手程序绑定的IP,牌手程序绑定的端口号,牌手的ID)

调用形式如下:

./game 192.168.0.1 1024 192.168.0.2 2048 6001

因此注册socket采用4参数的,输出字符流采用PrintWrite

// Socket link
			Socket socket = new Socket(args[0], Integer.parseInt(args[1]),
					InetAddress.getByName(args[2]), Integer.parseInt(args[3]));
			// OutputStream
			OutputStream os = socket.getOutputStream();
			PrintWriter pw = new PrintWriter(os);
			pw.write("reg: " + args[4] + " xsfelvis \n");
			pw.flush();

这里PrintWriter提供了PrintStream的所有打印方法,其方法也从不抛出IOException。与PrintStream的区别:作为处理流使用时,PrintStream只能封装OutputStream类型的字节流,而PrintWriter既可以封装OutputStream类型的字节流,还能够封装Writer类型的字符输出流并增强其功能。这样我们就成功的跟Sever服务器通信上了,(但是不要立马关闭socekt,需要接受Sever后续消息,读取到game
over消息时关闭)迈出了第一步

2、解析消息

这里庄家Sever都会在一定的时候向选手发出公共消息,这个在比赛给出的程序通信协议中均有给出,主要包括

"seat/
" 座次

"blind/ "盲注

"hold/ "手牌

"flop/ "公牌

"turn/ "转牌

"river/ "河牌

"inquire/ "询问消息(即是否出牌/check)

"showdown/ "摊牌消息

"pot-win/ " 彩池信息

这些消息都需要进行正确提取作为自己判断的依据,主要先用hashmap将这些信息进行映射,以便于switch对应的信息元素;存储消息采用了StringBuffer,

这些消息都是每一轮的临时消息,但是需要再每一轮结束时都要清空(/pot-win),确保这是最新的一轮最新消息,否则会影响出牌判断。解析消息代码如下

final HashMap<String, Integer> MsgCommand = new HashMap<String, Integer>();
		MsgCommand.put("seat/ ", 1);// seat flag
		MsgCommand.put("blind/ ", 2);// bind flag
		MsgCommand.put("hold/ ", 3);// hold flag
		MsgCommand.put("flop/ ", 4);// flop flag
		MsgCommand.put("turn/ ", 5);// turn flag
		MsgCommand.put("river/ ", 6);// river flag
		MsgCommand.put("inquire/ ", 7);// inquire flag
		MsgCommand.put("showdown/ ", 8);// showdown flag
		MsgCommand.put("pot-win/ ", 9);// pot flag
		int ServerCommand;
		try {
			// Socket link
			Socket socket = new Socket(args[0], Integer.parseInt(args[1]),
					InetAddress.getByName(args[2]), Integer.parseInt(args[3]));
			// OutputStream 向Sever发送注册消息
			OutputStream os = socket.getOutputStream();
			PrintWriter pw = new PrintWriter(os);
			pw.write("reg: " + args[4] + " xsfelvis \n");
			pw.flush();
			// InputStream 接受Sever的消息
			InputStream is = socket.getInputStream();
			InputStreamReader isr = new InputStreamReader(is);
			BufferedReader br = new BufferedReader(isr);
			// define Msg StringBuffer 存储消息
			StringBuffer SeatMsg = new StringBuffer("");
			StringBuffer BlindMsg = new StringBuffer("");
			StringBuffer CardsMsg = new StringBuffer("");
			StringBuffer InquireMsg = new StringBuffer("");
			StringBuffer ShowdownMsg = new StringBuffer("");
			StringBuffer PotWinMsg = new StringBuffer("");
			String info;
			String ActMsg;
			int Seat_num = 0;
			//开始消息解析存储到对应的StringBuffer中
			while (true) {
				info = br.readLine();// get a line of info
				ServerCommand = MsgCommand.get(info);// get hashmap value
				switch (ServerCommand) {
				case 1: {
					while (info != null) {
						info = br.readLine();
						if (info.equals("/seat "))
							break;
						Seat_num++;
						SeatMsg.append(info);
					}
					break;
				}
				case 2: {
					while (info != null) {
						info = br.readLine();
						if (info.equals("/blind "))
							break;
						BlindMsg.append(info);
					}
					break;
				}
				case 3: {
					while (info != null) {
						info = br.readLine();
						if (info.equals("/hold "))
							break;
						CardsMsg.append(info);
					}
					break;
				}
				case 4: {
					while (info != null) {
						info = br.readLine();
						if (info.equals("/flop "))
							break;
						CardsMsg.append(info);
					}
					break;
				}
				case 5: {
					while (info != null) {
						info = br.readLine();
						if (info.equals("/turn "))
							break;
						CardsMsg.append(info);
					}
					break;
				}
				case 6: {
					while (info != null) {
						info = br.readLine();
						if (info.equals("/river "))
							break;
						CardsMsg.append(info);
					}
					break;
				}
				case 7: {
					while (info != null) {
						info = br.readLine();
						if (info.equals("/inquire "))
							break;
						InquireMsg.append(info);
					}
					break;
				}
				case 8: {
					while (info != null) {
						info = br.readLine();
						if (info.equals("/showdown "))
							break;
						ShowdownMsg.append(info);
					}
					break;
				}
				case 9: {
					while (info != null) {
						info = br.readLine();
						if (info.equals("/pot-win "))
							break;
						PotWinMsg.append(info);
					}
					break;
				}
				default:
					break;
				}
				if (info.equals("/inquire ")) {
					//出牌算法 核心所在!
					ActMsg = Alg(CardsMsg.toString(), InquireMsg.toString(),
							args[4], Seat_num);
					InquireMsg = new StringBuffer("");
					pw.write(ActMsg);
					pw.flush();
				}
				if (info.equals("/pot-win ")) {
					Seat_num = 0;
					SeatMsg = new StringBuffer("");
					BlindMsg = new StringBuffer("");
					CardsMsg = new StringBuffer("");
					ShowdownMsg = new StringBuffer("");
					PotWinMsg = new StringBuffer("");
				}
				if (info.equals("game-over ")) {
					br.close();
					isr.close();
					pw.close();
					os.close();
					socket.close();
					break;
				}
			}

		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

补充:

这里由于Sever每次发送
一串字符串,开头和结尾都有特定的标志,而且都是双方约定好的字符串,因而无需考虑TCP的粘包问题。

3
、算法部分

用一句话总结一下就是“只玩大牌,小牌能check就check,不能则fold”所谓的大牌主要参考了百度一篇《德州扑克最佳技巧》

德州扑克最佳技巧

感觉算法部分不是很好没有做太多的优化,也没有基于对手建立相应的数学模型或者是加入博弈论的知识,就不展示了

详细代码下载

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

时间: 2024-11-20 03:04:23

德州扑克 2015 华为软件精英挑战赛的相关文章

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

这是华为举办的一个软件竞赛,华为提供一个德州扑克台桌的server,我们要根据牌型等因素,给出出牌的策略,类似模拟牌手的程序.从知道挑战的题目到提交最终版本的程序中间只有一个月的时间,刚看到这个题目一点头绪没有,看了论文有用蒙特卡洛模拟,决策树等,各种没听过的词汇,感觉写出这个程序会很难,和我一个教研室的小伙伴们看到这个题目的时候陆续都放弃了. 思考了半天我也放弃了,因为接下来几个星期还有实习的面试和小论文等着我完成,就这样过了2个星期,期间我把小论文与实习面试都完成了,在一天早晨无意中又点开了

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

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

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

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

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

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

华为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一直很大:改了好久都没有解决: 还有遇到的参赛以来最大的困难就是输出路径那一块了,初赛的时候也听说好几个人输出路径有问题,搞了好几天,我

德州扑克输赢判断-C#

首先讲一下思路吧. 德州扑克一把有7张牌,可能组成10种牌型,所以,在网络游戏中,不可能是两两比较,然后排序,最简单的做法就是对每个玩家的手牌计算一个权值,然后对最终玩家的权值进行排序即可得到最终的输赢顺序. 其实这个是我的毕业设计,在大三的时候,我曾在一位学长王总的带领下做过一个德州扑克的记录软件,那个软件比较简单,只是有记录员记录现实世界中正在进行的游戏,然后把玩家的牌,叫牌操作和游戏结果记录下来,以供将来重放时做教学使用.当时的项目并没有输赢判断的功能,而是由记录员自己输入输赢的玩家顺序.

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

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