第二次结对编程作业
PART1 链接
PART2 分工
钟博:制作UI,处理接口传入的数据以及传出接口的数据,原型设计
林得翔:写AI以及http请求的部分,根据同伴提出的输出格式和http请求返回的数据进行处理
PART3 PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 90 | 180 |
Estimate | 估计这个任务需要多少时间 | 2560 | 2910 |
Developm | 开发 | 1680 | 1800 |
Analysis | 需求分析(包括学习新技术) | 600 | 720 |
Design Spec | 生成设计文档 | 30 | 30 |
Design Review | 设计复审 | 10 | 10 |
Coding Standard | 代码规范(为目前的开发制定合适的规范) | 10 | 10 |
Design | 具体设计 | 30 | 60 |
Coding | 具体编码 | 1680 | 1800 |
Code Review | 代码复审 | 10 | 30 |
Test | 测试(自我测试,修改代码,提交修改) | 60 | 120 |
Reporting | 报告 | 60 | 60 |
Test Report | 测试报告 | 10 | 10 |
Size Measurement | 计算工作量 | 30 | 30 |
Postmortem & Process Improvement Plan | 事后总结,并提出过程改进计划 | 30 | 30 |
合计 | 2640 | 3090 |
PART4 解题思路及设计实现
网络接口的使用
这幅图里就是用于申请http请求的HttpUntil类,由于负责写网络接口的这位(我)实在是菜的惊人,以至于并没有弄懂具体这个接口怎么写最后像网络求助。我根据这回不同的网络接口的参数要求对原类进行了重载,不过基本框架还是一样的。基本流程为建立HttpClient对象,设置Header域,提交http请求,接收返回的参数。
部分UI展示
-
进入UI后的界面
-
登录界面,登录后会显示开始战局和历史记录等其他按钮
-
开始战局的界面,里面可以看到自己的战局的ID,还有自己拿到的牌以及前中后墩
-
点开历史后的界面
-
查询自己的历史战绩,分好几页,从第一页开始算起,输入页数查询就可以看到那一页的历史战绩,一页有25条历史战绩,越往前的页数战绩是越新的
-
查询战绩后就可以看到自己的信息了
代码组织(类图)
上图为类之间的数据传入
说明算法关键
我这此主要负责的范围是算法部分,对于这次的十三水我是通过贪心算法来解决问题的,选贪心的原因是我自己在打十三水时也基本上是基于贪心的方法来打牌的。我这会的代码有以下几个要点:
- 贪心策略是先贪心最优的后墩,再贪心最优的中墩,最后剩下的就是前墩。这种方法有两个优点,第一个是实现方便,第二个则是可以保证不会出现“相公”的情况。
- 有扑克牌中所有的牌都有自己的花色与牌面数字所以每一张牌都可以认为是第一无二的,我为了方便统计就使用了一个4*14的矩阵对收到的扑克牌进行计数,两张牌如果同一行就说明花色形同,同一列就说明牌面大小相同。有了这个矩阵我判断各类牌型尤其是与花色相关的是有就会方便许多。
- 贪心算法大致流程图
沿流程图中顺序询问下去就会选出当前能选到的最大的牌组。
PART5 关键代码解释
public class Poker {
public static int id = 0;
public static String totp = new String();
public static boolean[][] card = new boolean[4][14];
public static int row[] = new int[4];
public static int col[] = new int[14];
public static char suit[] = {'*', '#', '&', '$'};
static void begin(char[] s) {
for (int i = 0; i < s.length; i++) {
if (s[i] != ' ') {
int t = 0, num = 0;
for (int j = 0; j < 4; j++) {
if (s[i] == suit[j]) {
t = j;
break;
}
}
num = change(s[i+1]);
if (num == 9)
i++;
i++;
card[t][num] = true;
row[t]++;
col[num]++;
}
}
}
static void print() {
for (int i = 0; i < 4; i++) {
for (int j = 0; j <= 13; j++) {
System.out.print((card[i][j] == true));
if (j == 13)
System.out.println();
else
System.out.print(' ');
}
}
}
static int change(char c) {
if (c >= '2' && c <= '9')
return (int)(c - '1');
else if (c == '1')
return 9;
else if (c == 'J')
return 10;
else if (c == 'Q')
return 11;
else if (c == 'K')
return 12;
else if (c == 'A')
return 13;
else
return 0;
}
static void init(String card_json, int num){
int len = card_json.length();
id = num;
char[] s = new char[len + 2];
for (int i = 0; i < len; i++)s[i] = card_json.charAt(i);
s[len + 1] = s[len] = ' ';
for (int i = 0; i < 4; i++)row[i] = 0;
for (int i = 0; i < 14; i++)col[i] = 0;
for (int i = 0; i < 4; i++){
for (int j = 0; j < 14; j++){
card[i][j] = false;
}
}
begin(s);
}
}
- 1.主要用来存储当前剩余的手牌的Poker类,通过矩阵来存牌本质上就是一个桶排序。其中card数组就是之前提到的矩阵,row数组的值位当前花色还有多少张牌,col[i]的值代表值为i的扑克牌共有几张。
PART6 性能分析与改进
性能分析和程序消耗最大类
- 其中消耗最大的类是Rank_and_History,里面的方法和变量被调用得比较多,且涉及较多的字符处理。
改进思路
- 在速度方面可以用优化AI的方法尽可能地加快速度,还有我们在字符串处理方面调用得比较多,相对而言,速度会慢一些,所以字符串处理上可以减少或优化处理。在UI上很多组件会被多次重复调用,可以声明一个类进行操作,会大大减少一些相近地组件反复声明。接口部分可以进行重载,重载以后的运行速度也会大大增加,但是代价就是代码看起来会相对冗长一点。
PART7 单元测试
测试代码
测试数据
$5 #7 #9 &9 $9 *2 #K &3 #A $Q #3 #6 $3
&3 #4 &10 #K *8 &9 &2 &J *Q &7 #A *9 &5
*Q &5 $J #4 #A $5 $7 #2 &3 $2 &J $Q *8
&10 #4 *9 &2 *A $3 &6 #K $J *8 #7 $K &8
#10 #Q #4 #2 &J &8 *8 &7 #9 *10 *Q *6 #8
$9 &10 &2 *3 #K #5 *10 $6 *8 $5 &6 #A #8
&7 &4 &9 *8 *K #10 $5 #9 $10 #A &K $Q $9
$10 #8 &Q &3 *J *2 *6 #10 $Q &2 #5 $6 $7
#9 *2 *3 *4 #5 $Q &Q &8 $A &6 *J $2 *9
#Q $8 *Q #3 #8 #2 &10 *2 &9 *10 *4 $Q *3
输出数据
"$5 $3 *2","#A #K $Q #7 #6","#9 &9 $9 #3 &3"
"&5 &3 &2","*8 #4 &7 *9 &9","&10 &J *Q #K #A"
"$7 #4 &3","#A &5 $5 #2 $2","*8 &J $J *Q $Q"
"&6 $3 &2","*A #4 &8 #K $K","#7 *8 *9 &10 $J"
"&J &7 #2","*6 #9 #4 *Q #Q","*8 #8 &8 *10 #10"
"&10 $9 &2","*3 #A #K *8 #8","*10 #5 $5 &6 $6"
"$Q $5 &4","*8 #A &7 *K &K","#9 &9 $9 #10 $10"
"$7 #5 &3","#8 *6 $6 *2 &2","*J &Q $Q #10 $10"
"$A &8 $2","*J &Q $Q *9 #9","*2 *3 *4 #5 &6"
"&9 *3 #3","*4 *10 &10 #8 $8","*Q #Q $Q *2 #2"
PART8 Github签入记录
PART9 遇到代码异常及结对困难
问题描述
- 1.设计简单的UI界面很简单就可以设计出来,但是对界面的精修做起来不是那么简单,比较大的困难就是给窗体插入背景图片的时候试了好几种方法,要么就是拼命报错,要么就是显示不出来,还有就是UI的界面是窗体弹出所以开很多个窗体不是很美观,所以对窗体间的交互,隐藏上花了比较大功夫。
-
2.在同伴编写的网络的接口和自己的UI界面进行数据上的对接时,发生了代码跑崩的致命bug,因为双方都对彼此的代码不是特别了解,所以也不知道是谁的代码有问题,当时的情况是如果是我的代码有bug的话,我的代码可能面临大部分的重构,相当于前面的大半努力都要白费。
-
3.这是我第一次用java编写程序而且一写就是好几百行,有种赶鸭子上架的感觉,对java从头开始学起是我这此面临的最大的困难之一。java和C++无论是在代码的写法上还是在代码的风格上都有相当大的差距,学习起来也总会因为带入了之前对C++的印象而出不少差错。
-
4.对我来说这一次最大的麻烦还是学习怎么写http请求,我本就没有写过java,也没有接触过关于网络的编程,两个一起来真的是感受到了无尽的“快乐”,连着两三天明知道问题出在哪里就是写不下去,之后根据永福大佬给的各种请求重载http请求的类也是伴随着一大堆麻烦。
做过的尝试
- 1.对窗体的背景图的插入问题,上网查了好几种方法,去修改了它的方法并解决出现的bug,窗体的交互也是上网找了多方面资料,然后去进行实际交互查看结果。
-
2.上网查找各种自己代码可能发生的错误,然后对自己的代码进行理论上的排除错误,尽可能缩短自己代码的bug的出现范围。
-
3.比起看书我自己认为还是直接写代码学习来的快得多,先从“Hello world”开始看下怎么输出在一步一步的去熟悉数组、字符数组、字符串、字符串数组等基础的东西,在看书的同时尽量自己去实现那些代码。
-
4.最开始我是想找书的,后面发现我不太擅长翻书,然后我就去翻网页了。最后我在网上找到了一篇相对能看得懂的代码,但是我在学习的过程中还是遇到了相当多的麻烦,不过还好我有鲍老师的帮助总算是完成了http请求部分的代码。
是否解决
-
1.问题解决了,上网查了多种方法后对其中一种比较通用易懂的方法研究后成功加入了背景,窗体的交互也在多次尝试以后成功解决了。
-
2.经过一个多小时的焦头烂额的时间后,通过两个人的轮番上阵排除bug后最后确定了bug的原因出现在网络的接口上,然后也成功地解决了。
-
3.只要敢去打代码上手的还是比较快的,只针对这次作业的话这个问题已经解决了。
-
4.已解决。虽然说我学写http请求的方法基本上是摸黑箱子,但是我还是解决了这个问题。
有何收获
-
1.对UI的设计有了进一步的了解,虽然过程很痛苦,但解决还是很欣慰的。
-
2.对自己的代码有了一个更系统的了解,前面学的东西就像用工具一样的去编写代码,没有对它有个系统的理论上的了解,通过网上的科普,相对而言,会对自己的代码为什么这样写有了更深刻的理解。
-
3.这次的结对作业成功地催促了我学习java,虽然说肯定还有一大堆问题,但是至少我现在已经开了一个头比起无线拖延症什么来的要好得多。
-
4.学到了不少东西,我之前对网络编程完全是一头雾水但是我现在至少知道了http请求的一些大致的结构在很大程度上也历练了我的编程能力。
PART10 评价队友
值得学习的地方
-
钟博:队友很认真,脑子很灵活,学东西非常快,而且网上查找资料学习的能力也很强,遇到事情也比较冷静,心态很稳,有时候我心态崩了时候,还好有队友稳定一下局势,只能说一句,林老师牛逼!
-
林得翔:钟老师是个做事很稳妥的人,我做事感觉好像做得了实际动手的时候发现根本做不了,我这次拖了他无数次的后腿,钟老师牛逼!我只能跪下来给钟老师擦鞋。
需要改进的地方
-
钟博:总体上没啥需要改进的,就是队友太忙了,国庆没法正式开工,导致开工的时间相对有点晚,做起来有点赶。
-
林得翔:可以改进的地方还是比较多的尤其是AI我看了一下那个胜率,能不能赢基本看发牌。
PART11 学习进度条
第N周 | 新增代码(行) | 累计代码(行) | 本周学习耗时(小时) | 累计学习耗时(小时) | 重要成长 |
---|---|---|---|---|---|
1 | 0 | 0 | 20 | 20 | 熟悉Axure Rp工具 |
2 | 0 | 0 | 12 | 32 | 查阅相关资料,了解项目大概的做法流程 |
3 | 300 | 300 | 20 | 52 | 学习java翻书了解java,并试着写一些比较基本的代码 |
4 | 300 | 600 | 25 | 52 | 学习http请求写法,学习如何在项目上和他人配合 |