第二次结对编程作业

1、链接

队友博客链接戳这里
本次作业博客链接戳这里
github项目地址
UI演示视频

2、具体分工

  • 王景弘:负责实现AI部分,设计出牌算法,编写单元测试,提供算法思路、关键、改进和性能分析等博客内容。
  • 陈靖雯:负责实现UI部分,用接口连接算法形成最终文件,提供UI部分博客内容,用markdown格式编写博客内容。

3、PSP表格

PSP2.1 Personal Software Process Stages 预估耗时
(小时)
实际耗时
(小时)
Planning 计划 1 1.5
· Estimate · 估计这个任务需要多少时间 45 50
Development 开发 5 5
· Analysis · 需求分析 (包括学习新技术) 8 7.5
· Design · 生成设计文档 0.5 0.5
· Design Review · 设计复审 0.2 0.3
· Coding Standard · 代码规范 (为目前的开发制定或选择合适的规范) 1 1
· Design · 具体设计 4 5
· Coding · 具体编码 15 20
· Code Review · 代码复审 1 2
· Test · 测试(自我测试,修改代码,提交修改) 2 3
Reporting 报告 1 0.8
· Test Report · 测试报告 1 0.5
· Size Measurement · 计算工作量 0.1 0.1
· Postmortem & Process Improvement Plan · 事后总结, 并提出改进计划 0.5 0.5
  · 合计 45.3 50.2

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

(1)网络接口的使用

按照所给的接口文档,调用所给接口。本次作业采用html、css、javascript实现UI部分,需要新建一个XMLHttpRequest对象,向所给地址发送GET或POST请求,需要在控制台观察是否响应以便修改错误。成功响应的请求会返回需要的内容。发送的数据用JSON.stringify()转换成json字符串发送,返回的json字符串用JSON.parse()转换为JS对象,再逐一匹配标签id显示到页面中或进行其他操作。由于用到Token认证,需要用cookie保存token值并加入到请求头中。

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

(3)说明算法的关键与关键实现部分流程图

算法关键:

  • 实现的时候需要用到很多重复的switch和if/else语句。
  • 发到的牌按大小排完序之后,存入数组中,按照相同的牌的数量来分类。
  • 给每种牌型赋予权重值。
  • 利用switch语句不断的找到手牌中所有的牌型。
  • 之后将最大的拿出来留给后墩,然后剩下的牌再去寻找最大的牌型留给中墩,前墩的牌型就放在最后用剩下来的三张牌补进去,直到三道都有牌型。
  • 再把牌放到Choice.java中创建的三个数组中(即前中后墩)
  • 最后转换为接口所需的数据格式

关键实现部分流程图

5、关键代码解释

AI部分:
最开始发到牌后,将牌从小到大排序,存储到数组中。

	public void change(List<Card> handCard)
	{
	    Collections.sort(handCard,new Comparator<Card>()          //从小到大排序
		{
			public int compare(Card c1, Card c2) 
			{  
				int i = c1.rank - c2.rank;  
				if(i == 0)  
				    return c1.type - c2.type;    
				return i;
			}   
		});
	arrange(handCard);        //将牌整理到arr中

将排好序的牌按照相同的牌的数量来对数组进行分类

    for(int i=0;i<handCard.size();i++)
	{ 
		if((i+1)<handCard.size()&&handCard.get(i).rank==handCard.get(i+1).rank)
		if((i+2)<handCard.size()&&handCard.get(i).rank==handCard.get(i+2).rank)
		if((i+3)<handCard.size()&&handCard.get(i).rank==handCard.get(i+3).rank)    //四张相同的牌
		{
			arr.ranknum4.addAll(handCard.subList(i,i+4));
			i+=3;
		}
		else                                               //三张相同的牌
		{
			arr.ranknum3.addAll(handCard.subList(i,i+3));
		    i+=2;
		}
		else                                   //两张相同的牌
		{
			arr.ranknum2.addAll(handCard.subList(i,i+2));
			i+=1;
		}
		else                                  //没有相同的牌
		{
			arr.ranknum1.add(handCard.get(i));
		}
	}

通过判断读取出的对子数目和剩下的牌的数目来判断是否有牌型
此处为判断是否有四套三条和五对三条

    if(arr.ranknum3.size()==12||(arr.ranknum3.size()==9&&arr.ranknum4.size()==4))              //四套三条
	{
		choice=tochoice(handCard);
		choice.headType="sitaosantiao";
		return;
	}
	if(arr.ranknum2.size()==10&&arr.ranknum3.size()==3)       //五对三条
	{
		choice=tochoice(handCard);
		choice.headType="wuduisantiao";
		return;
	}

通过arr.ranknum4.size和arr.ranknum3.size的大小来判断牌型,并且改变Choice.java中的前中后墩数组(choice.headType/midType/endType)来进行出牌时的文字说明

	if(arr.ranknum4.size()==4)                  //尾道为铁支
	{
		choice.end.addAll(arr.ranknum4);
		card.removeAll(choice.end);
		arrange(card);
		if(arr.ranknum3.size()==6)              //中道是葫芦
		{
			if(!arr.ranknum2.isEmpty())
			{
				choice.mid.addAll(arr.ranknum3.subList(3, 6));
				choice.mid.addAll(arr.ranknum2);
				choice.midType="hulu";
				choice.head.addAll(arr.ranknum3.subList(0, 3));
				choice.headType="santiao";
				card.removeAll(choice.head);
				card.removeAll(choice.mid);
			    choice.end.addAll(card);
				choice.endType="tiezhi";
				return;
			}
			else
			{
				choice.mid.addAll(arr.ranknum3.subList(1, 6));
				card.removeAll(choice.mid);
				choice.end.add(card.get(0));
				choice.head.addAll(card.subList(1, 4));
				choice.endType="tiezhi";
				choice.midType="hulu";
				choice.headType="wulong";
				return;
			}
		}

UI部分:
登录的请求成功后会返回一个token,要用cookie保存,之后的请求要用split函数从cookie中提取出token放在其他需要token的请求的请求头中。

xhr.addEventListener("readystatechange", function () {
      if (this.readyState === this.DONE) {
      console.log(this.responseText);
      var JsonObj = JSON.parse(this.responseText);
      if(JsonObj.status==0)
      {
        document.cookie = JsonObj.data.token;
        valid();
      }
      }
      });
    var token = document.cookie.split(";")[0];
    xhr.setRequestHeader("x-auth-token",token);

进行下一次查询时需要删除之前表格中存在的数据,用到deleteRow函数将存在的行删除,若按从下标小到大的顺序删除,在删除过程中行的下标会不断改变,所以要从大到小删除。

    var tb = document.getElementById('table');
    var rowNum=tb.rows.length;
    for (var j=rowNum-1;j>=0;j--) //下标会变化,要从后往前删
    {
        tb.deleteRow(j);
    }

6、性能分析与改进

(1)描述改进思路

一开始只是单纯的想全用if/else语句来进行所有牌型的罗列但发现工程量实在是太大了,还是得逐步分析才能得到解法。后面想到先对花色和点数综合排序之后填入数组进行第一次分类(分点数大小的类),然后用判断数组大小的方式来进行第二次分类(分牌型的类,如对子三条之类的),再根据第二次分类出的结果来判断有没有特殊牌型(如全大全小、至尊青龙、五对三条之类的),最后给每种判断出的牌型赋予权重,用以判断什么牌型该放在什么位置。在进行完判断牌型的步骤之后再进行一下文字说明。

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

7、单元测试

public static void main(String[] args) {
        List<Card> allCards = new ArrayList<>();
        Random random = new Random();
        CardController cardController = new CardController();
        for (int i = 1;i <= 4; i++){
            for (int j = 1; j <= 13; j++){
                allCards.add(new Card(j,i));
            }
        }

        for (int i = 0; i < 10; i++){
            List<Card> tempCards = new ArrayList<>();
            List<Card> cards = new ArrayList<>();
            tempCards.addAll(allCards);
            for (int j = 0; j < 13; j++){
                Card card = tempCards.get(random.nextInt(52 - j));
                cards.add(card);
                tempCards.remove(card);
            }
            String cardStr = "";
            for (int j = 0; j < 13; j++){
                Card card = cards.get(j);
                cardStr += card.toString();
                if (j < 12)
                    cardStr += " ";
            }
            JSONObject jsonObject = new JSONObject();
            try {
                jsonObject.put("id",0);
                jsonObject.put("card",cardStr);
            } catch (JSONException e) {
                e.printStackTrace();
            }

            System.out.println(cardController.card2(jsonObject.toString()));;

        }
    }

每次随机构造13张牌,并且转化为符合json格式的字符串,再调用接口,得出结果

8、Github的代码签入记录


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

(1)问题描述

UI部分:

  • 不熟悉如何将json数据显示在页面中。
  • 接口调用不知道如何实现。
  • http请求一直失败,显示未授权。

AI部分:

  • 因为刚开始接触java,关键的算法也是一筹莫展。
  • 在调用接口的时候也遇到了不会调接口,每个请求的写法不会,无数次请求失败。

(2)做过哪些尝试

UI部分:

  • 在百度等渠道疯狂搜索解决方法,查找之前练习的代码。
  • 询问同学。

AI部分:

  • 接口和java算法的问题都是老老实实看资料学习

(3)是否解决

UI部分:
已解决。(以下每一点与问题一一对应)

  • 正确使用javascript,理清标签父子关系,使用json.parse()将json格式转化成js对象。
  • 接口文档有code generation,根据需要修改。
  • token值没有保存,设置的请求头有错,使用了document.cookie解决。

AI部分:

  • 已解决。

(4)有何收获

因为刚刚接触java很多知识都不甚了解
这次比较复杂的程序设计也算是逼迫我在ddl之前尝试了一次敏捷开发
虽然很多代码都是对着查到的资料现学现用,但也算是收获了不少java语法、算法相关的知识


10、评价你的队友

(1)值得学习的地方

  • 界面设计得很漂亮,对UI设计有经验。

(2)需要改进的地方

  • 没啥需要改进的地方已经做得很好了

11、学习进度条

第N周 新增代码(行) 累计代码(行) 本周学习耗时(小时) 累计学习耗时(小时) 重要成长
1 476 476 15 15 熟悉了java的基本语法
2 421 897 10 25 通过练习,掌握了数组的多种用法
3 1300 2197 25 50 完善了剩余的算法,学习了接口的使用

制作UI时查找到的实用资料

HTML页面跳转的5种方法
用js实现动态添加表格数据
JSON.parse()
js中设置元素class的三种方法小结
js中删除table里所有行
详细介绍NW.js基本使用
HTML网页打包成EXE可执行文件
将Token添加到请求头Header中
JSON.parse() 与 JSON.stringify() 简单使用
Session与Token认证机制 前后端分离下如何登录
js使用sessionStorage、cookie保存token

posted @ 2019-10-15 22:09  土豆来啦啦啦  阅读(245)  评论(3编辑  收藏  举报