第二次结对编程作业

网页链接

结对同学博客链接

本作业博客的链接

仓库链接

UI视频链接

分工

前端:沈梓耀

后端:黄恒杰

此次结对作业的PSP

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 30 30
· Estimate · 估计这个任务需要多少时间 1200 1800
Development 开发 800 800
· Analysis · 需求分析 (包括学习新技术) 900 1000
· Design Spec · 生成设计文档 10 5
· Design Review · 设计复审 10 5
· Coding Standard · 代码规范 (为目前的开发制定合适的规范) 10 0
· Design · 具体设计 400 400
· Coding · 具体编码 60 100
· Code Review · 代码复审 - -
· Test · 测试(自我测试,修改代码,提交修改) 100 100
Reporting 报告 10 10
· Test Repor · 测试报告 10 10
· Size Measurement · 计算工作量 20 20
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 - -
- 合计 1200 1860

解题思路描述与设计实现说明

  • 网络接口的使用

    Java的http包里面自带有HttpUrlConnection的类可以发送http的get请求和post。只是问题的关键在于其很难设置数据包的内容body(首部行还可以,body设置一直不成功),然后只好尝试运用样例里的Unirest类的接口应用,显然更简洁方便。

  • 代码组织与内部实现设计(类图)

    Http调用接口类:


>###ThirteenWater工作类:

>###Poker手牌类:

>###Pai牌类:

  • 说明算法的关键与关键实现部分流程图

    在于先判断特殊牌型,然后在对普通牌型进行递归遍历所有情况,对每种情况进行判断,得到“最好牌”。

关键代码解释

难度的关键在于13张牌分出5 5 3所有情况的遍历,这要求需要使用到组合数的算法,即需要使用递归,同时在组合数递归时还需要“分裂”1次,即在分出5张之后,再递归使用分5张的递归。其中在每次分5张的时候,在递归中不再使用之前拿到的牌,只在“分裂”时才把之前的牌传到下一次(很难说明清楚,就是在分相同组的牌时,尽量避免出现重复)。

private void getzuhe(Vector<pai> vv,int x,int start)
	{
		if(x>8)
		{
				for(int i=start;i<=vv.size();i++)
				{
					if(vv.size()-i+1<x-8) return;
					Enumeration<pai> element=vv.elements();
					element=vv.elements();
					for(int j=1;j<i;j++)
						element.nextElement();
					pai a=element.nextElement();
					v1.add(a);
					if(x==9)
					{
						Vector<pai> vx=new Vector<pai>();
						element=vv.elements();
						while(element.hasMoreElements()) vx.add(element.nextElement());
						element=v1.elements();
						while(element.hasMoreElements()) vx.remove(element.nextElement());
						getzuhe(vx,x-1,1);
					}
					else getzuhe(vv,x-1,i+1);
					v1.remove(v1.size()-1);
				}
			
		}
		else if(x>3)
		{
			for(int i=start;i<=vv.size();i++)
			{
				if(vv.size()-i+1<x-3) return;
				Enumeration<pai> element=vv.elements();
				element=vv.elements();
				for(int j=1;j<i;j++)
					element.nextElement();
				pai a=element.nextElement();
				v2.add(a);
				if(x==4)
				{
					Vector<pai> vx=new Vector<pai>();
					element=vv.elements();
					while(element.hasMoreElements()) vx.add(element.nextElement());
					element=v2.elements();
					while(element.hasMoreElements()) vx.remove(element.nextElement());
					getzuhe(vx,x-1,1);
				}
				else getzuhe(vv,x-1,i+1);
				v2.remove(v2.size()-1);
			}
		}
		else
		{
			Enumeration<pai> element=vv.elements();
				while(element.hasMoreElements())
					v3.add(element.nextElement());
				//
				double fen1,fen2,fen3;
				Vector<pai> nowv=new Vector<pai>();
				element=v1.elements();
				while(element.hasMoreElements())
					nowv.add(element.nextElement());
				Comparator<pai> ct=new MyComparator();
				Collections.sort(nowv,ct);
				fen1=getscore(nowv);
				nowv.removeAllElements();
				element=v2.elements();
				while(element.hasMoreElements())
					nowv.add(element.nextElement());
				ct=new MyComparator();
				Collections.sort(nowv,ct);
				fen2=getscore(nowv);
				if(fen2>fen1) 
				{
					v3.removeAllElements();
					return;
				}
				nowv.removeAllElements();
				element=v3.elements();
				while(element.hasMoreElements())
					nowv.add(element.nextElement());
				ct=new MyComparator();
				Collections.sort(nowv,ct);
				fen3=getscore(nowv);
				if(fen3>fen2) 
				{
					v3.removeAllElements();
					return;
				}
				
				//到这里fen1>fen2>fen3
				if(fen1+fen2+fen3>allscore)
				{
					allscore=fen1+fen2+fen3;
					getv1.removeAllElements();
					getv2.removeAllElements();
					getv3.removeAllElements();
					element=v1.elements();
					while(element.hasMoreElements())
						getv1.add(element.nextElement());
					element=v2.elements();
					while(element.hasMoreElements())
						getv2.add(element.nextElement());
					element=v3.elements();
					while(element.hasMoreElements())
						getv3.add(element.nextElement());
					
				}
				//
				v3.removeAllElements();
		}
	}

性能分析与改进

  • 描述你改进的思路

显然在前几个消耗里面出现了dasda.pocker&MyComparator和Vector类的,从分析可以得到,我对于手牌553的所有遍历(将近3W多种情况)都存入3组Vector临时变量,然后这些递归出来的Vector都需要调用sort函数与Comparator类。

  • 展示性能分析图和程序中消耗最大的函数

    最大消耗函数:

单元测试

比较蠢的没法,只用文件输入多个样例(自己想的样例,自己去抽牌然后人工比对),样例多为普通牌判断

跑的样例,这样子虽然没法随机生成次数少,但在人工拼牌然后比对之后,其实已经很能解决问题了,以下是结果片段

贴出Github的代码签入记录

遇到的代码模块异常或结对困难及解决方法

  • 问题描述

    AI的设计思路难点显然在于如上所说的组合数递归,熬了两个夜才搞出来的循环递归代码(网上教程多为单次递归样例)

  • 做过哪些尝试

    我先尝试写的第一串循环递归没有在循环后给出Vector的开始位置参数,直接每次拿出一张剩下的全给下一次的递归。

    发现跑的时间太久,原因是其实质是排列,情况多达上亿

    加入开始位置参数,在每个循环的递归中不拿之前拿过牌, 往后拿

  • 是否解决

    已解决

  • 有何收获

    写出这个递归,更加理解其实质,头脑风暴的同时头发也被风暴吹走了

    递归的情况次数正好是C(13)(5) *C(13)(5) ,成就满满

评价你的队友

  • 值得学习的地方

    工作完成良好,能力表现很不错(能做好前端的男生都是好姐妹)

  • 需要改进的地方

    有拖延症,需要改正(me too)

学习进度条

第N周 新增代码(行) 累计代码(行) 本周学习耗时(小时) 累计学习耗时(小时) 重要成长
1 0 0 4 4 初步入门了Axure RP8
2 200 200 10 10 完成牌型设计和基础代码
3 800 1000 20 20 完成AI编码和接口对接
- - - - - -
posted @ 2019-10-15 22:44  JayerListen  阅读(233)  评论(3编辑  收藏  举报