• 结对编程作业


    https://github.com/CNllb/pig_end

    学号 姓名 分工 博客链接
    031902610 刘凌斌 前端界面,模型设计,游戏逻辑 https://www.cnblogs.com/CNLLB/p/15456141.html
    131901121 肖清江 AI算法 https://www.cnblogs.com/xiao-qingjiang/p/15456122.html

    一、原型设计

    (1.1)原型作品链接为:https://app.mockplus.cn/s/WSoYi3myuw7c

    (1.2)原型开发工具:在本次结队编程作业中,我们小组采用了操作起来较为简单的Mockup工具对原型进行设计。

    (1.3)原型简单说明:

    (1)缺点和不足:

    ① 本次原型设计是由两位直男协同完成的,在审美方面或许还有较大的欠缺,希望大家批评指正。

    ② 作品链接中的原型作品的原型组件未进行及时更新,较为简陋,下文博客提供实现前后对比。

    (2)主要页面原型和实际效果对比:、

    原型和小程序实现的机型:iPhone X(812*375)

    主要效果的区别产生在原型设计未导入相关字体库和相关图标,实际界面与原型在实现上存在计算误差。

    登录页

    ① 原型:

    this is image

    ② 实际效果:

    this is image

    首页:

    ① 原型:

    image

    ② 实际效果:

    image

    对战界面:

    ① 原型:

    this is image

    ② 实际效果:

    this is image

    (1.4)遇到的困难和解决方法:

    困难:本次制作原型是我们小组第一次使用原型制作工具,在这过程中最难熬的就是想出一个好的idea,并做好颜色搭配。这对于两个理工男来说并不友好。我们也想过直接使用暴发户气息爆棚的传统斗地主风格,或者直接竖屏实现按钮点击,带出汽配城风格,但还是想着,既然要自己从0开始做一个小程序,那么不管结果如何,总要尽自己的可能,尽可能实现效果好一些。

    解决方法:多次讨论之后,我们决定背道而行,将棋牌游戏打出养生的感觉,所以,在图片方面,选择了色调较为柔和的水墨山水画,再结合莫兰迪色系,调出了属于我们小组的软件设计风格。

    收获:在原型开发的过程中,我们成员之间可以天马行空,可以一次次地进行犯错,颜色搭配有问题就马上更改颜色,再进行分析,这是软件开发中极为有趣的一部分,我们也开始能够理解UI小姐姐没有灵感时候的痛楚。在这过程中,我们又掌握了一个对软件开发非常有帮助的开发工具。

    二、原型设计实现

    简易思维导图:

    this is image

    (2.1)代码实现思路:

    (1)网络接口的使用

    • 登录接口的使用

      • 在实现过程中,使用input进行账号和密码的输入,点击登录实现网络通信,成功获取用户信息

      • 登录函数设置了常规输入检测,保证用户名和密码内容不为空,并对登录返回的status进行了判断。

            login: function (e) {
                    var that = this;
                    let formData = e.detail.value;
                    this.setData({
                        student_id:formData.student_id,
                        password:formData.password
                    })
                    console.log(formData);
                    if (that.data.student_id == ""||that.data.password == "") {
                      wx.showModal({
                        title: "错误",
                        content: "用户名或密码不能为空"
                      });
                      that.isname = false;
                      that.ispass = false;
                    } else {
                      that.isname = true;
                      that.ispass = true;
                    }
                    if (that.ispass && that.isname){
                        wx.request({
                            url: 'http://172.17.173.97:8080/api/user/login',
                            header:{
                                "Content-Type":"application/x-www-form-urlencoded"
                            },
                            data: formData,
                            method: "POST",
                            success: function (res) {
                                console.log(res.data);
                                if (res.data.status == 200) {
                                    that.setData({
                                        id_token: res.data.data.token,
                                        response: res
                                    }),
                                    wx.setStorageSync('id_token', that.data.id_token),
                                    wx.navigateTo({
                                        url: '../../pages/home/home',
                                    })
                                }else{
                                    wx.showModal({
                                        title: "错误",
                                        content: "密码或账号错误"
                                      });
                                }
                                
                            },
                            fail: function (res) {
                                console.log(res.data);
                                console.log('is failed');
                                console.log('获取信息失败');
                            }
                        })
                    }
                }
      
    • 获取房间信息的实现

          getHome:function (params) {
              var that = this;
              wx.request({
                url: 'http://172.17.173.97:9000/api/game/index',
                method: "get",
                data:{
                  page_size:that.data.page_size,
                  page_num:that.data.page_num,
                },
                header:{
                  "Authorization": wx.getStorageSync('id_token'),
                },
                success: function (res) {
                  console.log(res);
                  that.setData({
                    home_detail:res.data.data.games,
                    isOpenHome:false,
                    total_home:res.data.data.total,
                    total_pages_num:res.data.data.total_page_num
                  })
                  console.log(that.data.home_detail);
                  console.log(that.data.total_pages_num);
                },
                fail:function(err){
                  console.log(err)
                }
              })
            }
    
    • 加入房间接口实现
          joinHome: function (e) {
              var that = this;
              console.log(e.currentTarget.dataset.uuid);
              wx.request({
                url: 'http://172.17.173.97:9000/api/game/'+this.data.uuid,
                method: "POST",
                header:{
                  "Authorization": wx.getStorageSync('id_token'),
                  "content-type":'application/json'
                },
                data:{
                  uuid:e.currentTarget.dataset.uuid
                },
                success: function (res) {
                  that.setData({
                    Gaming:true
                  })
                },
                fail:function(err){
                  console.log(err)
                }
              })
            },
    
    • 创建房间的接口实现
          createHome: function () {
                var that = this;
                wx.request({
                  url: 'http://172.17.173.97:9000/api/game',
                  method: "POST",
                  data:{
                    "private":that.data.private
                  },
                  header:{
                    "Authorization": wx.getStorageSync('id_token'),
                  },
                  success: function (res) {
                    that.setData({
                      uuid: res.data.uuid
                    })
                    console.log(res);
                    console.log(that.data.uuid);
                  },
                  fail:function(err){
                    console.log(err)
                  }
                })
            },
    

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

    this is image

    (3)贴出你认为重要的/有价值的代码片段,并解释

    ​ 人机对战之中,AI的实现感觉比较有意思,我们小组是采用设置延时进行实现。在实现的时候,经过2000ms之后,自动实现AI的步骤,模拟较为有效

          setTimeout(() => {
                // 延迟后操作
                that.selectWay()
              }, 2000)
    

    (4)描述你改进的思路

    • 在本来的代码中,对战过程只使用一个界面进行展现,但是在传参过程中,多次造成传参错误,或者逻辑混乱的问题。
    • 在这样的前提下,我们决定了重构代码,一个界面实现两次刷新,这样每个数据都能够单独处理,大大降低了发生逻辑错误的概率。

    (5)展示出项目部分单元测试代码,并说明测试的函数,构造测试数据的思路。

    • 本次结队编程项目,我们小组采用的是微信小程序进行实现,出于微信小程序的局限性,并未进行小程序代码的单独单元测试。但对各个函数进行了单独封装,并进行多次单例测试。
          // 封装的抽牌函数
          POP_Get_pork_1: function () {
              var that = this;
              this.data.last_value = this.data.now_value;
              this.data.now_pork = this.data.get_pork_set.pop();
              this.data.now_value = this.data.now_pork.value;
              this.data.set_pork_set.push(this.data.now_pork)
              switch (Math.floor((this.data.now_pork.value - 1) / 13)) {
                case 0:
                  this.setData({
                    get_pork_black_peach_count: this.data.get_pork_black_peach_count - 1,
                  })
                  break;
                case 1:
                  this.setData({
                    get_pork_red_heart_count: this.data.get_pork_red_heart_count - 1,
                  })
                  break;
                case 2:
                  this.setData({
                    get_pork_black_flower_count: this.data.get_pork_black_flower_count - 1,
                  })
                  break;
                default:
                  this.setData({
                    get_pork_red_block_count: this.data.get_pork_red_block_count - 1
                  })
                  break;
              };
              that.check_card_1();
              that.check_winner();
              this.setData({
                now_pork: this.data.now_pork,
                now_index: (this.data.now_index + 1) % 2,
                set_pork_block: this.data.set_pork_set.length == 0 ? false : true,
                get_pork_block: this.data.get_pork_set.length == 0 ? false : true,
                player1_black_peach_count: this.data.player1_black_peach.length,
                player1_red_heart_count: this.data.player1_red_heart.length,
                player1_black_flower_count: this.data.player1_black_flower.length,
                player1_red_block_count: this.data.player1_red_block.length
              });
              that.set_top_card_1();
              if (this.data.get_pork_set.length == 0) {
                this.setData({
                  get_pork_block: true
                })
              }
            },
    
          // 封装的检查牌堆函数
          check_card_1: function () {
              if (Math.floor((this.data.now_value - 1) / 13) == Math.floor((this.data.last_value - 1) / 13)) {
                while (this.data.set_pork_set.length != 0) {
                  var pork_1 = this.data.set_pork_set.pop();
                  console.log(pork_1);
                  switch (Math.floor((pork_1.value - 1) / 13)) {
                    case 0:
                      this.data.player1_black_peach.push(pork_1);
                      break;
                    case 1:
                      this.data.player1_red_heart.push(pork_1);
                      break;
                    case 2:
                      this.data.player1_black_flower.push(pork_1);
                      break;
                    default:
                      this.data.player1_red_block.push(pork_1);
                      break;
                  }
                }
                this.data.last_value = null;
                this.data.now_value = null;
              }
            },
    
          // 封装的设置牌顶的函数
          set_top_card_1: function () {
              this.setData({
                player1_top_black_peach: this.data.player1_black_peach.pop(),
                player1_top_red_heart: this.data.player1_red_heart.pop(),
                player1_top_black_flower: this.data.player1_black_flower.pop(),
                player1_top_red_block: this.data.player1_red_block.pop()
              })
              if (this.data.player1_top_black_peach != null) {
                this.data.player1_black_peach.push(this.data.player1_top_black_peach)
              }
              if (this.data.player1_top_red_heart != null) {
                this.data.player1_red_heart.push(this.data.player1_top_red_heart)
              }
              if (this.data.player1_top_black_flower != null) {
                this.data.player1_black_flower.push(this.data.player1_top_black_flower)
              }
              if (this.data.player1_top_red_block != null) {
                this.data.player1_red_block.push(this.data.player1_top_red_block)
              }
            },
    
          // 封装的检查对局胜利的函数
          check_winner: function () {
              if (this.data.get_pork_set.length == 0) {
                this.setData({
                  Gaming: false
                })
                if (this.data.player1_black_peach_count + this.data.player1_red_heart_count + this.data.player1_black_flower_count + this.data.player1_red_block_count > this.data.player2_black_peach_count + this.data.player2_red_heart_count + this.data.player2_black_flower_count + this.data.player2_red_block_count) {
                  this.setData({
                    winner: this.data.player_2
                  })
                } else {
                  this.setData({
                    winner: this.data.player_1
                  })
                }
              }
            }
    

    (2.2)贴出Github的代码签入记录,合理记录commit信息。

    小组的很大的不足:小组成员欠缺日常对Github的使用习惯,没有养成及时push代码的习惯,我们的commit记录并不好

    this is image

    小组有设置todo的习惯,以下是我们小组的todo记录截图(使用的是“敬业签”APP):

    this is image

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

    (1)在代码模块异常方面,前期的网络通信采用Postman进行模拟网络通信,和实际实现校园网通信有很大的不同,微信小程序对局域网通信的不支持也是一个很大的问题。在刚接入校园网的时候,各种报错,是真的头大。

    解决办法:微信开发者工具强行不检查网络的证书和合法性,再接入校园网,成功获取信息。

    (2)结队困难:首先,这是和队友的第一次合作,在实现代码的过程中,没有那么的默契。其次,两个人对各自负责的领域,了解得都不够深刻,前端对微信开发者工具的相关合法性不够了解,后端对框架不够熟练,这就造成了到处碰壁。

    解决方法:通过制定todo进行计划,保证项目顺利地进行。

    (2.4)评价你的队友。

    • 值得学习的地方:

      学习能力很强,也很热衷学习新事物,今后我也要做到这一点,无论是在软件开发领域还是其他领域。

    • 需要改进的地方:

      有时候联系不上哈哈,希望之后可以保持更紧密的联系哈哈。

    (2.5)提供此次结对作业的PSP和学习进度条(每周追加)

    N周 新增代码(行) 累计代码(行) 本周学习耗时(小时) 累计学习耗时(小时) 重要成长
    1 0 0 12 12 前端:学习安卓开发和微信小游戏的开发;后端:考虑使用Java进行后端编程,对Java基础知识进行巩固
    2 1000 1000 12 24 前端:学了一周的游戏引擎和微信小游戏开发后,果断放弃,短时间把握不住,做了无用功,第2周,对原型进行设计,并实现微信小程序界面;后端:学习使用flask框架的python后端开发;
    3 2500 3500 8 32 前端:实现微信小程序打牌逻辑,制作简易的人机对战;后端:完成AI的百分80代码。
    4 1000 4500 10 42 前端:对代码进行封装,使得游戏的逻辑清晰明了,遗憾是,在线对战代码重构还未全部完成;后端:完成AI,并制作接口

    三、心得

    刘凌斌:

    作业难度:本次作业给我带来的最大的困难应该是在游戏逻辑的实现,犯了专业性的错误,对各个操作的代码并未实现有效的封装。造成了后期代码需要重构,浪费了很多的时间;其次是对时间的规划不够合理,前期想要实现很多附属功能,后面发现附属功能还未完成,主要功能来不及实现,只能草草的实现,效果很差,这是犯的很致命的错误。

    作业感想:即使本次作业完成的并不完善,但我们小组仍然会在后期将这个项目实现完全,也会开始学会习惯使用GitHub进行代码的pull和push,也借此提高自己的代码能力。

    启发:制定项目需求一定要合理,要与实力相互匹配,不能好高骛远,要一直学下去,我们不会的还有很多东西。

    肖清江:

    作业难度: 这次作业难度我个人感觉较大,因为之前没有开放一个可以联网的功能(在线对战),只做过命令行小游戏,并且也没有做过前后端分离的工作(之前甚至分不清前后端),所以这次的作业对我挑战还是相当大的。
    作业感想: 即使这次作业难度较大,但我还是尽量根据完成作业的需要去学相对应的内容。虽然起步的时候相当困难,但好在b站大学有各种各样的学习资料嘿嘿,终于还是学会了flask框架来实现后端,总而言之,完成这次作业还是相当有满足感的,尤其是看到自己的代码能给成功应用的时候!
    启发: 这次给我最大的启发就是,要勇于尝试新事物,之前一直害怕学来不及,但不管如何,尽力而为,最终一定能得到收获,相信自己,勇于尝试新事物!

  • 相关阅读:
    计算一个月有多少天
    模拟迭代器next方法
    Promise实现
    控制台命令
    Linux下通过ssh上传下载文件
    简单使用template-web.js
    安装echo框架
    gin框架博客实战教程2019web页面开发go语言实战博客开发
    TP5使用phpoffice phpexcel包操作excel(导出)
    两分钟让你明白Go中如何继承
  • 原文地址:https://www.cnblogs.com/xiao-qingjiang/p/15456122.html
Copyright © 2020-2023  润新知