2022软工K班结对编程任务


https://github.com/Yummy-y/Kex-Bonesdice.git
https://www.bilibili.com/video/BV1Pg411a7cR?share_source=copy_web

一、结对探索

1.1 队伍基本信息

结对编号:20;队伍名称:饿鬼;

学号姓名作业博客链接分工
032002231谢以盛https://github.com/Yummy-y/Kex-Bonesdice.git后端
032002235杨明https://github.com/Yummy-y/Kex-Bonesdice.git前端

1.2 描述结对的过程

Yummy:搞?
Eson:搞!

1.3 非摆拍的两人在讨论设计或结对编程过程的照片

在这里插入图片描述

二、原型设计

2.1 原型工具的选择

选择的原型工具是墨刀,墨刀是一款打通产设研团队,实现原型,设计,流程,思维导图一体化的在线协同工具。它方便使用,利于协同开发,故选择其为原型工具。

2.2 遇到的困难与解决办法(3分)

  • 困难一:初次使用原型开发工具,缺乏经验。
  • 困难二:手头没有合适美观的现成素材。
    解决尝试:通过文档和视频学习,逐步上手实现原型设计。通过各个软件和搜索引擎的搜索查找,找到美观且风格接近的设计素材。
    是否解决:是。
    收获:世上无难事,只怕有心人。

2.3 原型作品链接

https://modao.cc/app/IrTCOyU9rjod98yMagrDLb
(共两页)

2.4 原型界面图片展示(6分)

  • 主页:背景是明丽鲜艳的古风风格。项目名称《逍遥骰》以及文案“拂去尘烟,一念逍遥。”在正中间展示。往下三个卷轴风格的选项:龙争虎斗(pvp),投石拔距(pve),人外有人(在线对战)。
    在这里插入图片描述
    创新点:左上角三个小功能,打开bgm、切换主页背景、查看游戏规则(音效音乐功能展示还请移步github项目或bilibili视频查看)
    在这里插入图片描述

在这里插入图片描述

  • 对局页面:左下和右上分别是玩家A、B的头像和骰子区,中间是双方的九宫格棋盘。
    在这里插入图片描述
    创新点
  • 左上角增加三个小功能分别是打开bgm、切换背景和返回主页
  • 轮到某一方的回合时,该玩家的头像呼吸灯闪烁。
    在这里插入图片描述
  • 九宫格两旁统计每行得分,并以大写中文展示。
    在这里插入图片描述
  • 点数重复以及消除对方点数会有字母特效(共五种)并伴有音效。
    在这里插入图片描述

三、编程实现

3.1 网络接口的使用

  • 前端部分
    main.js文件:
//导入 axios 使我们可以发起axios请求
import axios from 'axios'
Vue.prototype.$axios = axios
axios.withCredentials = true
// 配置请求的跟路径 由后端提供 这样我们只要输入根路径后面的地址就OK (例如/login /home
axios.defaults.baseURL = 'http://127.0.0.1:5000'

调用接口页面文件Pve.vue(定义接口函数,发起post请求,通过this.getBChangeRow()即可调用):

   //api
    async getBChangeRow() {
      const result = await this.$axios({
        method: "post",
        url: "/pve",
        data: {
          dataA: this.playerBData,
          dataB: this.playerAData,
          point: this.randb,
        },
      });
      this.AIRow = res.data;
      return res.data;
    },
  • 后端部分
import re
from flask import Flask,request
from flask import jsonify
from flask_cors import CORS
import AIcontrol
app = Flask(__name__)
CORS(app,resources=r'/*',supports_credentials=True)
@app.route('/pve',methods=['POST'])
def aAI():
    data=request.get_json()
    print(data)
    next_step=AIcontrol.AI_decide(data['dataA'], data['dataB'], data['point'])
    print(next_step)
    next_step={
        'next_step': next_step
    }
    return jsonify(next_step)

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

  • 前端部分
    在这里插入图片描述
    在这里插入图片描述
  • 后端部分:
    在这里插入图片描述

3.3 说明算法的关键与关键实现部分流程图

  • 前端部分
    游戏对局流程控制流程图如下:
    在这里插入图片描述

  • 后端部分

  • 后端的模块主要是提供交互接口和ai决策;

  • 后端部分简单的交互接口使用flask库建立本地接口;

  • ai决策过程则是以贪心算法为主的简单策略:我们希望每一列都能得到最大分数,所以做决策时尽可能贴近最大的分数,同时对对手进行一定简单干扰,即消除决策。

3.4 贴出重要的/有价值的代码片段并解释

  • 前端部分
    data部分:
//用对象包数组方式表示九宫格,对象的KEX三元素表示数组的三行
data() {
    return {
      playerAData: {
        K: [],
        E: [],
        X: [],
      },
      playerBData: {
        K: [],
        E: [],
        X: [],
      },
}

用数组方法push()实现放置骰子的点数:

//this.randa为我们掷得的点数
pushAE() {
      this.playerAData.E.push(this.randa);
      this.changeRow = "E";
      this.removeB();//remove方法即消除方法
    },

用数组方法splice()实现点数的消除:

removeA() {
      var row = this.changeRow;
      for (let i = 0; i < this.playerAData[row].length; i++) {
        if (this.playerAData[row][i] == this.randb) {
          var removed = this.playerAData[row].splice(i, 1);
          console.log("remove the " + removed + "!");
        }
      }
      for (let i = 0; i < this.playerAData[row].length; i++) {
        if (this.playerAData[row][i] == this.randb) {
          var removed = this.playerAData[row].splice(i, 1);
          console.log("remove the " + removed + "!");
        }
      }

至此,实现游戏的基本也是核心功能,点数的放置和消除,其他功能(流程控制、消除特效、得分统计、图形界面转化等)在此基础上通过增加判断条件变量,监听和获取九宫格数据,即可逐一实现(实现逻辑思路大于算法设计),具体各个判断变量的设置和使用以及九宫格监听思路,本博客篇幅有限还请移步github项目查看。
ps:为便于后端开发,九宫格数据重构为以下格式(数组本质是特殊的对象,重构后不影响已实现的任何功能)

playerAData: [[], [], []],
playerBData: [[], [], []],
  • 后端部分
    后端的AI由简单策略组成:
    获取每列未来预期最大能够获取的分数:比如列状态为[1],那么它未来填满时最大得分的状态为[1,6,6],分数为25,而状态[1,5]的未来最大得分为[1,5,5],分数为21。这些状态我们枚举保存。
def exp_score1(board,list):
    maxn = 0
    k = 1
    for i in range(1, 7):
        list.append(i)
        score = exp_score2(board, list)
        list.pop()
        if (score > maxn):
            maxn = score
            k = i
    board[str(list)] = score
    return score


def exp_score2(board,list):
    maxn=0
    k=1
    for i in range(1, 7):
        list.append(i)
        score = exp_score3(board, list)
        list.pop()
        if(score>maxn):
            maxn=score
            k=i
    board[str(list)] = maxn
    return maxn

def exp_score3(board,list):
    score=0
    num=[0,0,0,0,0,0]
    for i in range(0,3):
        num[list[i]-1]+=1
    for i in range(0,6):
        score+=num[i]*num[i]*(i+1)
    board[str(list)]=score
    return score

def exp_socre():
    dict={}
    list=[]
    dict['[]']=-54
    for x1 in range(1,7):
        list.append(x1)
        exp_score1(dict,list)
        for x2 in range(1, 7):
            list.append(x2)
            exp_score2(dict, list)
            for x3 in range(1, 7):
                list.append(x3)
                exp_score3(dict,list)
                list.pop()
            list.pop()
        list.pop()
    return dict
#嵌套获取每一种情况下的未来最大得分

将点数填入每列中并获取它未来的最大得分,将其与现在的未来最大得分相减,得到权重以比较,抉择接下来放在哪一列。这里我们希望它们的差值越小越好。

得分模块外,消除对手的干扰行为同样重要,但是消除对手的骰子有可能会减少分数收入,所以我们设定一定限制,不难发现,1,2这样的点数一般来说是不值得消除的。综合观察的情况,对程序予以一定阈值以操控消除决策。
以下是简单决策的环节:

    for i in range(0,3):
        if(list_count(my_data[i])==3):
            print(i,":max!")
        else:

            my_max=exp_dict[str(my_data[i])]
            his_max=exp_dict[str(his_data[i])]

            my_data[i].append(point)
            my_exp = exp_dict[str(my_data[i])]
            my_data[i].pop()

            ans=0
            while point in his_data[i]:
                his_data[i].remove(point)
                ans+=1
            his_exp = exp_dict[str(his_data[i])]
            while ans:
                ans-=1
                his_data[i].append(point)

            pd=my_exp-his_exp
            pd2=my_max-his_exp
            pd3=pd-pd2

            score=Exp_add(my_data[i],point)+Exp_lost(his_data[i],point)#当前步收益
            print(i,":",my_max - my_exp)
            nt[i]=my_max
            if score>=12:
                set=i
                situ=0
            if situ==2:
                if my_max - my_exp < change:
                    change = my_max - my_exp
                    set = i
                elif my_max - my_exp == change:
                    if my_max>nt[set]:
                        set = i

3.5 性能分析与改进

因为是简单的贪心策略,后端的AI算法基本上只是 O(1)级别的时间复杂度,所以没什么需要优化的。
​ (描述你改进的思路,展示性能分析图和程序中消耗最大的函数)

3.6 单元测试

在这里插入图片描述

  • 模拟前端的游戏流程,实现PVE以测试AI流程

3.7 贴出GitHub的代码签入记录,合理记录commit信息

在这里插入图片描述

四、总结反思

4.1 本次任务的PSP表格

PSP2.1Personal Software Process Stages预估耗时(分钟)实际耗时(分钟)
Planning计划
Estimate·估计这个任务需要多少时间2020
Development开发
Analysis·需求分析 (包括学习新技术)300250
Design Spec·生成设计文档6060
Design Review·设计复审1520
Coding Standard·代码规范 (为目前的开发制定合适的规范)3015
Design·具体设计6060
Coding·具体编码1000800
Code Review·代码复审120120
Test·测试(自我测试,修改代码,提交修改)50150
Reporting报告
Test Repor·测试报告2015
Size Measurement·计算工作量2015
Postmortem & Process Improvement Plan·事后总结, 并提出过程改进计划3030
合计17251605

4.2 学习进度条(每周追加)(2分)

第N周新增代码(行)累计代码(行))本周学习耗时(小时)累计学习耗时(小时)重要成长
170070088熟练用vue框架搭建项目
2· 80015001018学会动态修改vue背景图,熟练使用vue动画,掌握后端接口书写的基本流程
370022001028熟练使用flask库实现后端接口开发

4.3 最初想象中的产品形态、原型设计作品、软件开发成果三者的差距如何?

产品形态和预期的有些差别,最初本来想做个很酷的小游戏。有丰富的音效和动画效果,交互感强,功能丰富,页面信息清晰明了又面面俱到,最好是小程序。但是实际开发过程中考虑到技术栈(前端动画效果的实现,页面各类高质量素材获取,后端数据库调用,对跨域的处理等等。)以及完成度(学习成本大,可分配时间有限。)很多想法都被pass掉了。原型设计上我们根据自身能力对预期实现功能进行了考量,原型设计作品和软件开发成果很接近,基本还原了原型设计,还额外补充了一些功能。这点还算是比较满意。

4.4 评价你的队友

  • 评价Eson:
    谢以盛是一个很好的队友。积极配合我们两人小队完成本次作业,积极和我进行前后端对接,互相调试找出错误。不断优化自己的算法。他一丝不苟,热情配合的精神值得我学习。需要改进的地方:第二周尾正式进行后端的开发学习,这个时间可以再提早一些,可以为后续的对接配合可以提供更多弹性空间和容错。
  • 评价Yummy:
    杨明是一个一个很优秀的队友啊(喜)。他对于本次作业非常上心,在前端工作上投入了大量时间,对于自己工作的热情这一点很值得我学习。需要改进的地方:队友在一些细节上会钻牛角尖而导致自己进入一些耗费很大的状态,希望能够自我调整一下。

​ 4.5 结对编程作业心得体会

心得体会

  • Yummy:这次作业比较有挑战性,项目比较完整,开发过程中基于产品的完成度要做很多考虑,例如要满足基本功能、要提升用户交互感、游戏对局的流程控制要符合逻辑等等。在前端开发上还尝试了不少此前没有尝试的功能开发。还是有不少收获的,但是也看到自己能力有限,很多想法也会因为自己的技术水平而被局限,很多算法和布局以及功能实现并没有尽善尽美,不过遗憾也会是自己继续奋斗学习的动力!继续加油!
  • Eson:预期做这次作业时没有什么概念,上手了才发现问题多多。在我负责后端处理接口时,因为不了解前端数据结构,给队友带来一些意义不明的错误,在我们实现前后端实现对接之间沟通不顺利;另外就是能力局限导致不能完成预期项目,没能成功抽象作业的游戏流程,对深度学习的算法也不够熟悉,只能手动写策略。在这次作业完成过程中,对所学的知识是一次很好的检验,今后也要再接再厉,继续努力。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ChatGPT结对编程是一种将两个程序员合作编写代码的技术。这种技术可以提高编写代码的效率和质量,同时也可以提高两位程序员的技能水平。以下是ChatGPT结对编程的步骤: 1. 首先,找到一个合适的编程伙伴。最好是一个有一定编程经验的人,但如果你是新手,也可以与另一个新手合作。 2. 确定你们编写的代码项目。你们可以选择一个共同感兴趣的项目或者一个有挑战性的项目。确保你们都对项目有一定的理解。 3. 确定你们的角色。一个人可以担任主要代码编写者,另一个人可以担任代码审核者。这样可以确保代码的质量。 4. 确定编程环境。你们可以使用一个共同的编程环境,如Visual Studio Code或者Atom。也可以使用在线编程环境,如CodePen或JSFiddle。 5. 开始编写代码。一个人负责编写代码,另一个人负责审核代码。在编写代码的过程中,你们可以随时通过聊天工具进行交流和讨论。 6. 定期进行代码审核。定期进行代码审核可以确保代码的质量。你们可以定期的分享代码,并相互审核对方的代码。 7. 完成项目并进行总结。完成项目后,你们可以总结你们的经验和教训,并提出改进建议。这将有助于你们以后更好的编写代码。 总之,ChatGPT结对编程是一种非常有用的技术,可以提高编写代码的效率和质量。通过合作编写代码,你们可以相互学习,相互支持,以及增强你们的编程技能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值