第二次结对编程作业

第二次结对编程作业

一、结对博客信息:

031702513卢欢

031702545汪佳祥

Github项目地址(前端与AI)

二、具体分工

前端:卢欢,设计与实现十三水界面和交互,实现网络api调用

后端:汪佳祥,负责出牌AI算法设计与实现

三,PSP表格

过程 预估耗时(分钟) 实际耗时(分钟)
计划 30 30
估计任务时间 30 30
开发 600 800
需求分析 (包括学习新技术) 60 60
生成设计文档 30 30
设计复审 15 15
代码规范 (为目前的开发制定合适的规范) 15 30
具体设计 30 15
具体编码 455 655
代码复审 15 15
测试(自我测试,修改代码,提交修改) 30 30
报告 40 45
测试报告 15 15
计算工作量 10 15
事后总结, 并提出过程改进计划 15 15
合计 670 875

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

1.网络接口的使用

其实各个接口使用都是差不多的

贴出登录和开始游戏的C#代码

//开始一局游戏
UnityWebRequest webRequest = new UnityWebRequest(NetMgr.GetUrl("StartGame"), "POST");
        webRequest.SetRequestHeader("X-Auth-Token", NetMgr.TokenDate);
        webRequest.downloadHandler = new DownloadHandlerBuffer();
        yield return webRequest.SendWebRequest();
//登录游戏
        JsonData data = new JsonData
        {
            ["username"] = username,
            ["password"] = password
        };
        string js1 = data.ToJson();
        byte[] postBytes = Encoding.UTF8.GetBytes(js1);

        UnityWebRequest webRequest = new UnityWebRequest(NetMgr.GetUrl("Rigister"), "POST")
        {
            uploadHandler = new UploadHandlerRaw(postBytes)
        };
       // UnityWebRequest.useHttpContinue = false;
        webRequest.SetRequestHeader("Content-Type", "application/json;charset=utf-8");
        webRequest.downloadHandler = new DownloadHandlerBuffer();
        yield return webRequest.SendWebRequest();


五、关键代码解释

重要的/有价值的代码片段
AI出牌函数:

public static List<TypeCard> GetMaxCardType(List<int> cardList)
        {
            List<TypeCard> typeCardList = new List<TypeCard>();

            //从大到小排序
            SortCard(cardList);

            //复制一份从小到大的牌
            List<int> cardList2 = cardList.GetRange(0, cardList.Count);
            SortCardMinToMax(cardList2);

            List<int> FourNum = cardList.GroupBy(p => p % 100).Where(p => p.Count() >= 4).Select(p => p.Key).ToList();
            List<int> ThreeNum = cardList.GroupBy(p => p % 100).Where(p => p.Count() >= 3).Select(p => p.Key).ToList();
            List<int> TwoNum = cardList.GroupBy(p => p % 100).Where(p => p.Count() >= 2).Select(p => p.Key).ToList();
            #region 同花顺
            foreach (var item in cardList2)
            {
                //同花顺最小是从10开始
                if (item % 100 >= 11)
                    break;

                List<int> tempList = new List<int>();
                tempList.Add(item);

                foreach (var item2 in cardList2)
                {
                    if (item2 - 1 == tempList.Last())
                        tempList.Add(item2);

                    if (tempList.Count >= 5)
                    {
                        TypeCard typeCard = new TypeCard() { cardList = tempList, cardType = DeckTypeEnum.TongHuaShun };
                        typeCardList.Add(typeCard);
                        break;
                    }
                }
            }
            #endregion

            #region 炸弹
            foreach (var FourItem in FourNum)
            {
                List<int> tempList = new List<int>();
                foreach (var item in cardList)
                {
                    if (item % 100 == FourItem)
                        tempList.Add(item);

                    if (tempList.Count >= 4)
                    {
                        TypeCard typeCard = new TypeCard() { cardList = tempList, cardType = DeckTypeEnum.Bomb };
                        typeCardList.Add(typeCard);
                        break;
                    }
                }

            }
            #endregion

            #region 葫芦
            foreach (var ThreeItem in ThreeNum)
            {
                List<int> tempList = new List<int>();
                foreach (var item in cardList)
                {
                    if (item % 100 == ThreeItem)
                        tempList.Add(item);

                    if (tempList.Count >= 3)
                    {
                        //找两对
                        foreach (var TwoItem in TwoNum)
                        {
                            if (ThreeItem != TwoItem)
                            {
                                foreach (var AllItem in cardList)
                                {
                                    if (AllItem % 100 != ThreeItem && AllItem % 100 == TwoItem)
                                        tempList.Add(AllItem);

                                    if (tempList.Count >= 5)
                                    {
                                        TypeCard typeCard = new TypeCard() { cardList = tempList, cardType = DeckTypeEnum.Gourd };
                                        typeCardList.Add(typeCard);
                                        tempList = typeCard.cardList.GetRange(0, 3);
                                        break;
                                    }
                                }
                            }
                        }
                        break;
                    }
                }
            }
            #endregion

            #region 同花
            List<int> FiveColor = cardList.GroupBy(p => p / 100).Where(p => p.Count() >= 5).Select(p => p.Key).ToList();
            List<int> FourColor = cardList.GroupBy(p => p / 100).Where(p => p.Count() >= 4).Select(p => p.Key).ToList();
            List<int> ThreeColor = cardList.GroupBy(p => p / 100).Where(p => p.Count() >= 3).Select(p => p.Key).ToList();

            List<TypeCard> typeCards = new List<TypeCard>();

            foreach (var Fiveitem in FiveColor)
            {
                List<int> tempList = new List<int>();
                foreach (var item in cardList)
                {
                    if (item / 100 == Fiveitem)
                    {
                        tempList.Add(item);
                    }
                }
               
                while (true)
                {
                    if (tempList.Count >= 5)
                    {
                        TypeCard typeCard = new TypeCard() { cardList = tempList.GetRange(0, 5), cardType = DeckTypeEnum.TongHua };
                        typeCards.Add(typeCard);
                        //typeCardList.Add(typeCard);
                        tempList.RemoveAt(0);
                    }
                    else
                    {
                        break;
                    }
                }
            }
            //收集同花集合后
            //对同花进行排序
            //
            if (typeCards.Count > 1)
            {
                
                //排序的优先级从高到低
                typeCards.Sort((x, y) => -((x.cardList[0] % 100).CompareTo(y.cardList[0] % 100) * (1 << 4)
                + (x.cardList[1] % 100).CompareTo(y.cardList[1] % 100) * (1 << 3)
                 + (x.cardList[2] % 100).CompareTo(y.cardList[2] % 100) * (1 << 2)
                  + (x.cardList[3] % 100).CompareTo(y.cardList[3] % 100) * (1 << 1)
                  + (x.cardList[4] % 100).CompareTo(y.cardList[4] % 100)
                ));
                //typeCards.Sort((x, y) => -((x.cardList[1]%100).CompareTo(y.cardList[1]%100)));
            }
            foreach (var typeCard in typeCards)
            {
                typeCardList.Add(typeCard);
            }

            #endregion

            #region 顺子

            foreach (var MaxItem in cardList)
            {

                if (MaxItem % 100 <= 5)
                {
                    break;//从大到小,后面的也不需要循环了
                }

                List<int> tempList = new List<int>();
                tempList.Add(MaxItem);

                while (tempList.Count < 5)
                {
                    bool flag = false;
                    foreach (var item in cardList)
                    {
                        if (item % 100 + 1 == tempList.Last() % 100)
                        {
                            tempList.Add(item);
                            flag = true;
                            break;
                        }
                    }
                    if (!flag)
                    {
                        break;
                    }
                }

                if (tempList.Count >= 5)
                {
                    TypeCard typeCard = new TypeCard() { cardList = tempList, cardType = DeckTypeEnum.ShunZi };
                    typeCardList.Add(typeCard);
                }
            }

            #endregion

            #region 三张
            foreach (var Threeitem in ThreeNum)
            {
                List<int> tempList = new List<int>();
                foreach (var item in cardList)
                {
                    if (item % 100 == Threeitem)
                        tempList.Add(item);

                    if (tempList.Count >= 3)
                    {
                        TypeCard typeCard = new TypeCard() { cardList = tempList, cardType = DeckTypeEnum.Three };
                        typeCardList.Add(typeCard);
                        break;
                    }
                }
            }

            #endregion

            #region 两对

            for (int i = 0; i < TwoNum.Count; i++)
            {
                List<int> tempList = new List<int>();

                foreach (var item in cardList)
                {
                    if (item % 100 == TwoNum[i])
                    {
                        tempList.Add(item);
                    }
                }

                while (tempList.Count >= 2)
                {

                    for (int j = i + 1; j < TwoNum.Count; j++)
                    {
                        List<int> tempList2 = new List<int>();
                        foreach (var item in cardList)
                        {
                            if (item % 100 == TwoNum[j])
                            {
                                tempList2.Add(item);
                            }
                        }

                        while ((tempList2.Count >= 2))
                        {
                            TypeCard typeCard = new TypeCard() { cardList = tempList.GetRange(0, 2), cardType = DeckTypeEnum.TwoDouble };

                            //直接加入连对的判断
                            if (tempList[0] % 100 - 1 == tempList2[0] % 100)
                            {
                                //连对
                                typeCard.cardType = DeckTypeEnum.ContinuousTwoDouble;
                            }
                            typeCard.cardList.AddRange(tempList2.GetRange(0, 2));
                            typeCardList.Add(typeCard);
                            tempList2.RemoveAt(0);
                        }

                    }
                    tempList.RemoveAt(0);
                }

            }

六、性能分析与改进

1.改进的思路
消耗最大的函数是网络请求和AI,我们重点关注AI的改进。
算法开始的时连对没考虑到,后面就加了这种情况
然后对于一些特殊情况,可以先提前判断,可以减少消耗。
2.展示性能分析图和程序中消耗最大的函数


    IEnumerator PostResult(string jsondata)
    {

        byte[] postBytes = Encoding.UTF8.GetBytes(jsondata);

        UnityWebRequest webRequest = new UnityWebRequest(NetMgr.GetUrl("submit"), "POST")
        {
            uploadHandler = new UploadHandlerRaw(postBytes)
        };
        webRequest.SetRequestHeader("X-Auth-Token", NetMgr.TokenDate);
        webRequest.SetRequestHeader("Content-Type", "application/json;charset=utf-8");
        webRequest.downloadHandler = new DownloadHandlerBuffer();
        yield return webRequest.SendWebRequest();
        if (webRequest.isDone)
        {
            string result = webRequest.downloadHandler.text;
            if (result == "")
            {
                ShowMes("网络连接失败");
            }
            else
            {
                JsonData results = JsonMapper.ToObject(result);
                string state = "";
                try
                {
                    state = results["status"].ToJson();
                }
                catch
                {
                    ShowMes("连接失败");

                }
                if (state == "0")
                {
                    Pokemgr.Instance.Clean();
                    ExitButton.onClick.Invoke();
                    BackButton.onClick.Invoke();

                    if (AIScore)
                    {
                        StartButton.onClick.Invoke();
                    }
                    else
                    {
                        ShowMes("出牌成功");
                    }
                }
                else
                {
                    ShowMes(NetMgr.GetState(state));
                }
            }
        }
        else
        {
            if (Application.internetReachability == NetworkReachability.NotReachable)
            {
                ShowMes("网络连接失败");
            }
        }
    }

七、单元测试

通过服务器获取牌堆,AI出牌后自动提交,同时留下记录
如果服务器返回错误,则说明我们测试失败

八、Github的代码签入记录

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

汪佳祥(后端)

1.

遇到的问题:一开始AI出牌算法毫无思绪,后来。欢哥要求我使用C#写出算法,我被赶鸭子上架

做过哪些尝试:到微信小程序玩了几十把罗松渐渐熟悉起来

是否解决:是

收获:一天速成C#简单语法,第二天开始写算法,也遇到许多bug,例如中墩比尾墩来得大(都是我的锅),都被欢哥逐一解决(再次抱紧欢哥大腿)。这些问题在我欢哥面前简直都不是个事

卢欢(前端)

1.

问题描述:界面的设计没什么特别难的问题,主要是我自己写了很多界面动画,有时没有想要的效果

做过哪些尝试:一直在改,强迫症犯了,就一直想做得好看,虽然现在做的也挺丑。。。

是否解决:是

有何收获:提高审美

2.

问题描述:网络接口

做过哪些尝试:开始没用过,找个例子就理解了

是否解决:成功解决

有何收获:再次理解了网络异步通信,网络请求的代码写在协程里

十、评价你的队友

汪佳祥

  • 值得学习的地方
    • 评价队友:通过本次的软工实践,我紧抱欢哥大腿,感觉到了我的队友十分强悍,他设计的这个前端界面让我让我感觉我的后端算法有点配不上他,他也给我提供了许多的帮助,我还需要继续向他学习
  • 需要改进的地方
    • 应该尽可能地不要通宵,少熬夜。

卢欢

  • 值得学习的地方
    • 祥哥真是个大忙人,不过敲起代码来效率飞快,总的来说碰的壁比较少吧,因此我们这个项目花的时间不是很多就写完成了
  • 需要改进的地方
    • AI能够更强大就好了

十一、学习进度条

  • 后端(汪佳祥)
第N周 新增代码(行) 累计代码(行) 本周学习耗时(小时) 累计学习耗时(小时) 重要成长
1 0 0 10 10 上手墨刀,了解原型设计的过程
2 600 600 15 25 写算法
3 200 800 10 35 学习网络接口的使用
  • 前端(卢欢)
第N周 新增代码(行) 累计代码(行) 本周学习耗时(小时) 累计学习耗时(小时) 重要成长
1 0 0 8 8 上手墨刀,了解原型设计
2 0 0 20 28 学会设计界面
3 1170 1170 22 50 学会接口的使用
原文地址:https://www.cnblogs.com/wjx-1999/p/11768047.html