结对编程作业

https://github.com/CNllb/pig_end

学号 姓名 分工 博客链接
031902610 刘凌斌 前端界面,模型设计,游戏逻辑 结对编程作业
131901121 肖清江 AI算法 结对编程作业

一、原型设计

(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框架来实现后端,总而言之,完成这次作业还是相当有满足感的,尤其是看到自己的代码能给成功应用的时候!
启发: 这次给我最大的启发就是,要勇于尝试新事物,之前一直害怕学来不及,但不管如何,尽力而为,最终一定能得到收获,相信自己,勇于尝试新事物!

posted @ 2021-10-24 22:46  刘凌斌  阅读(25)  评论(0编辑  收藏  举报