2023秋软工实践 第二次结对编程作业

失重漂流 2023-10-06 20:45:43
这个作业属于哪个课程2023秋-福州大学软件工程
这个作业要求在哪里2023秋软工实践 第二次结对编程作业
个人学号102102104
结对成员学号102102105
GitHub 仓库地址GitHub仓库

PSP表格

PSPPersonal Software Process Stages预估耗时(分钟)实际耗时(分钟)
Planning计划1020
Analysis需求分析 (包括学习新技术)6030
Desin Spec生成设计文档1520
Coding Standard代码规范 (为目前的开发制定合适的规范)1015
Design具体设计3030
Coding具体编码3001440
Postmortem & Process Improvement Plan事后总结, 并提出过程改进计划2030
合计4451585

重难点功能及编程思考

  • 进行9个数独的并发求解,通过点击“查看答案”实现

  • 能够对所生成的数独进行填写与检查

    • 填写正确:给出“正确”的提示框,并给出成功的动画
    • 填写错误:对错误的数字所在的框进行标红,方便重新填写
  • 编程思考思维导图

img

相关的算法与技术

  • js提供了async和await搭配进行并发操作,以及worker进行多线程,我们采用了async和await搭配
async function solveSudokus() {
  let solvePromises = [];
  for (let i = 0; i < 9; i++) {      
  solvePromises.push(new Promise(resolve => {
    let sd = initSudokus[i];
    sd.solve();
    resolve(sd);
  }));
  }
  let solvedSudokus = await Promise.all(solvePromises);
  console.log("After solve:");
  solvedSudokus.forEach((sd, i) => {
  console.log(`Sudoku ${i}:`, sd.sdArr); 
  });
}
  • 求解原理与生成有解的数独原理一样,通过回溯判断该数字在对应行、列、三宫格是否存在
solveSdArr:function(){
        var that = this;
        try{
            this.sdArr = [];
            this.setThird(2,2);
            this.setThird(5,5);
            this.setThird(8,8);
            var allNum = [1,2,3,4,5,6,7,8,9];
            outerfor:
            for(var i=1;i<=9;i++){
                innerfor:
                for(var j=1;j<=9;j++){
                    if(this.sdArr[parseInt(i+''+j)]){
                        continue innerfor;
                    }
                    var XArr = this.getXArr(j,this.sdArr);
                    var YArr = this.getYArr(i,this.sdArr);
                    var thArr = this.getThArr(i,j,this.sdArr);
                    var arr = getConnect(getConnect(XArr,YArr),thArr);
                    var ableArr = arrMinus(allNum,arr);
                    if(ableArr.length == 0){
                        this.createSdArr();
                        return;
                        break outerfor;
                    }
                    var item;
                    //如果生成的重复了就重新生成。
                    do{
                        item = ableArr[getRandom(ableArr.length)-1];
                    }while(($.inArray(item, arr)>-1));

                    this.sdArr[parseInt(i+''+j)] = item;
                }
            }
            this.backupSdArr = this.sdArr.slice();
        }catch(e){
            //如果因为超出浏览器的栈限制出错,就重新运行。
            that.createSdArr();
        }
    },
getXArr:function(j,sdArr){
        //获取所在行的值。
        var arr = [];
        for(var a =1;a<=9;a++){
            if(this.sdArr[parseInt(a+""+j)]){
                arr.push(sdArr[parseInt(a+""+j)])
            }
        }
        return arr;
    },
    getYArr:function(i,sdArr){
        //获取所在列的值。
        var arr = [];
        for(var a =1;a<=9;a++){
            if(sdArr[parseInt(i+''+a)]){
                arr.push(sdArr[parseInt(i+''+a)])
            }
        }
        return arr;
    },
    getThArr:function(i,j,sdArr){
        //获取所在三宫格的值。
        var arr = [];
        var cenNum = this.getTh(i,j);
        var thIndexArr = [cenNum-11,cenNum-1,cenNum+9,cenNum-10,cenNum,cenNum+10,cenNum-9,cenNum+1,cenNum+11];
        for(var a =0;a<9;a++){
            if(sdArr[thIndexArr[a]]){
                arr.push(sdArr[thIndexArr[a]]);
            }
        }
        return arr;
    },

GitHub仓库

github仓库

照片

返校后线下:

img

线上腾讯会议:

img

编码、争论、复审等活动中花费时间较长、收获较大的事件。

  • 在对第一作业进行重构便遇到了巨大的问题与困难,第一作业我们采用了通过输入9次难度并发生成9个数独,我们自以为这样是我们的创新之处,可是讨论过后觉得这样其实不符合用户的想法,输入9次难度过于繁琐,因为使用系统的提示框,输入太快会导致跟不上,因此在这次作业进行了修改,采用简单、中等、困难与大师模式供给用户选择,之前我们9个数独为9行,每行只有1个,这次经过改版,排版变为3*3,在重构这两个功能就花费了5个小时。在重构中,我们对css的排版功能以及各个页面之间的连接与跳转有了更加深刻地认识,如何连接同级文件与次级文件也能熟练应用。

各种页面的跳转

 <button onclick="window.location.href='难度选择.html'">开始游戏</button>
 <button onclick="window.location.href='数独规则.html'">数独规则</button>
<button onclick="window.location.href='./easy/easy.html'">简单模式</button>
<button onclick="window.location.href='./medium/medium.html'">中等模式</button>
<button onclick="window.location.href='./hard/hard.html'">困难模式</button>
<button onclick="window.location.href='./master/master.html'">大师模式</button>
<button onclick="window.location.href='index.html'">返回</button>
<link rel="Stylesheet" type="text/css" href="../soduku.css" />
<button onclick="window.location.href='../难度选择.html'">返回</button>

修改数独排版只需修改版面的margin

.sd{
    float : left;
    width: 260px;
    margin: 50px 70px 0;
}

img

  • 在上一次作业中,我们只是并发生成9个数独,但如果只是在原来基础上增加数独求解功能,只能求解最后一个生成的数独,经过一番讨论,才发现是因为之前的的数独没有被储存,所以一直对最后一个数独进行修改。所以我们先通过一个全局数组进行存储并发生成的9个数独,然后并发求解时遍历数组。并发求解与并发生成采用同一个原理,通过async和await进行并发操作。经过两次的并发生成,我们对于并发、多线程、异步有了更加深刻的认识与了解。

通过JSON.parse(JSON.stringify(this.sdArr))在初始化数组时便对数组进行存储并在求解数组时进行遍历

init:function(blankNum){
        this.createDoms();
        this.createSdArr();
        this.globalSdArr = JSON.parse(JSON.stringify(this.sdArr)); // 存储数独的初始状态
        this.blankNum =1;        
        this.drawCells();
        this.originalSudokus.push(this.drawCells());
        this.createBlank(this.blankNum);
        this.createBlankCells();
    },
  • 求解的数独该如何输出?我们想过很多种方案,在原来对应的9个数独上面生成答案、在每个数独的旁边生成答案、在原数独的空上直接填入答案、跳转到一个新的页面。在经过讨论之后,决定跳转到一个新的页面,所以我们通过getElementById设置Button的点击事件。本来以为这个功能不难,但因为最开始点击完没有响应或者跳转后为空白页面,后来通过gpt的一系列操作,最终勉强实现了这个功能。通过实现这个功能,我们对html的id属性以及getElementById函数有了更深刻地了解。
<button id="solve-button">查看答案</button>
let buttonElement = document.getElementById("solve-button")

img

  • 将设计的九个check按钮与九个数独一一对应地进行检查与报错这个问题卡了很久,反复修改checkRes函数只能得到每一题的报错都在第九个数独上或者全都不显现,在求助gpt时,他在全局定义了一个gird.id,为每个数独生成一个唯一的标识:

    this.gridId = "grid-" + Math.random().toString(36).substr(2, 9);
    

    将checkRes与createDoms函数中的

    $(".bg_red").removeClass('bg_red');
    

    for (var k = 0; k < 9; k++) {
            // 添加样式类
            $(".sdli:eq("+k+") .sdspan").eq(2).addClass("br");
            $(".sdli:eq("+k+") .sdspan").eq(5).addClass("br");
            $(".sdli:eq("+k+") .sdspan").eq(3).addClass("bl");
            $(".sdli:eq("+k+") .sdspan").eq(6).addClass("bl");
            }
    $(".sdli:eq(2) .sdspan, .sdli:eq(5) .sdspan").addClass("bb");
    $(".sdli:eq(3) .sdspan, .sdli:eq(6) .sdspan").addClass("bt");
    

    改为了

    $("#" + this.gridId + " .bg_red").removeClass('bg_red');
    

    for (k = 0; k < 9; k++) {
              $("#" + gridId + " .sdli:eq(" + k + ") .sdspan").eq(2).addClass('br');
              $("#" + gridId + " .sdli:eq(" + k + ") .sdspan").eq(5).addClass('br');
              $("#" + gridId + " .sdli:eq(" + k + ") .sdspan").eq(3).addClass('bl');
              $("#" + gridId + " .sdli:eq(" + k + ") .sdspan").eq(6).addClass('bl');
            }
    $("#" + gridId + " .sdli:eq(2) .sdspan, #" + gridId + " .sdli:eq(5) .sdspan").addClass('bb');
    $("#" + gridId + " .sdli:eq(3) .sdspan, #" + gridId + " .sdli:eq(6) .sdspan").addClass('bt');
    

    但结果只实现了每个数独定位到标识并进行修改,得此启发,将其他函数的有带$相关语句都修改为

    "#" + this.gridId + 原本内容
    

    的形式后,终于实现了每一道题的报错都一一对应数独本身!!!!!!!!!!!(依稀记得解决这个问题的那天晚上异常的兴奋
    正确:

img

img

错误:

img

未填写:

img

注:为了方便试验,将简单模式的空格数改为两个,便于查看不同结果的对应响应,实际简单模式的空格数为20个。

总结与收获

我主要负责页面的重构与附加题相关功能的实现,在实现九个数独3*3的排版上大费周章,后来发现其实只要改变sd中margin的值就可以轻松解决,感受到了自己对该语言掌握的浅薄以及身临其境地体会到选择比努力重要的人生大道理。

其次就是上述提到的对报错不对应问题的解决,还得感谢gpt给我产生的灵感,对每个函数进行类似的修改后,竟然实现了该功能,为这个功能努力了近12h,发现实现的时刻真的兴奋地手在抖哈哈哈哈,感受到为每个数独生成唯一标识,再将功能与每个数独的标识一一对应的作用之强大。

接着就是在git的使用上,一开始按照上次作业的基础指令上传一直显示错误,随后查阅csdn相关报错进行尝试后,使用以下指令解决了这个问题

//从远端仓库拉去不相关历史
git pull origin main --allow-unrelated-histories 

报错:

img

解决:

img

但只能通过强制上传,强制推送会覆盖远程仓库的提交记录,可能会导致其他开发者的工作被覆盖和丢失,但所幸是要直接修改整个文件夹,对整个项目并无损失。

img

第二次结对编程的过程比第一次要艰辛很多,难度提升需要讨论的细节变多再加上国庆需要线上会议,加大整个作业进程推动的难度,由于暑假就和小伙伴约好了国庆的出游计划,因此国庆期间可以说是非常充实,除了旅游的三天基本都在做软工作业,也提前一天和结对伙伴约好返校进行博客的撰写,不过依然算是一次难忘的记忆,和上次说的一样,我觉得结对作业的并肩作战比个人作业的孤军奋战来的有意思一些,两个人的集思广益也会让我更加踏实一点,困难所幸在最后也能解决很大的一部分,还是一次艰难但充实的体验!

...全文
72 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

121

社区成员

发帖
与我相关
我的任务
社区描述
2023秋-福州大学软件工程
软件工程 高校
社区管理员
  • fzusdn
  • 篱隙光远
  • Jason_Zhou1
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧