2023软工K班结对编程任务

GitHub:https://github.com/same-dust/roll_game
B站:https://b23.tv/utRdWUA

一、结对探索

1.1 队伍基本信息

结对编号: 队伍名称;

学号姓名作业博客链接具体分工
102101315王辉凡UI设计、算法设计、UI素材寻找、博客撰写
102101322吴文景https://bbs.csdn.net/topics/617401533前端、算法设计、AI算法、项目代码规划、页面交互

1.2 描述结对的过程

一个宿舍的,自然而然组队了

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

二、原型设计

2.1 原型工具的选择

墨刀。首先最重要的一点是墨刀免费且方便使用。其次,墨刀的免费版本自带部件、交互、功能,基本上能满足网页端产品原型的设计要求,其控件的拖拉、大小的调整,都会自然的去匹配相应的母版大小。因此在里面可以首先选择相应的设备布局,减少了不少工作环节。然后是素材库比较丰富,墨刀内置了很多的素材库,做这类原型的时候会方便很多,易用性也强很多。另外他的学习成本也比较低:一般大概半天就能掌握所有基础操作。所以几个原型工具体验下来后选择了墨刀。

​ 2.2 遇到的困难与解决办法

困难
1、素材查找:网上的资源很多但也很杂,想要找到心仪的素材需要花费一定的时间。

​ 解决办法:先找到喜欢的游戏页面布局进行模仿,通过ProKnockout 进行抠图和素材编辑,Procreate自行绘画素材,小图标从阿里图标库下载。
2、初次使用: 对于初次使用墨刀的我来说,掌握软件的操作和功能可能需要一定时间和学习。这导致设计进度较慢或出现一些技术性错误。
解决办法: 积极地进行墨刀相关的学习和培训,阅读文档和教程,以快速掌握软件的使用技巧。同时,我还会与其他使用过的朋友进行交流和分享经验,以便更好地利用墨刀进行原型设计。

收获:最直接的收获就是学会了原型设计以及墨刀的使用;遇到的一些困难,经历,这些经验将有助于我们

2.3 原型作品链接

https://modao.cc/proto/aumZ1OBys21pgjMVAtBEaD/sharing?view_mode=device&screen=rbpTrnOlM5rWOCtrE&canvasId=rcTrnUyd1KS9DrVg #孤注一掷-分享

2.4 原型界面图片展示

在这里插入图片描述

在这里插入图片描述
页面一:
欢迎界面,选择游戏模式后跳页面二。
在这里插入图片描述页面二:选择游戏局数后跳转页面三
在这里插入图片描述页面三:开始游戏。
在这里插入图片描述
页面四:选择赔率
在这里插入图片描述
页面五:结算页面

三、编程实现

3.1 网络接口的使用

网络编程的实现主要是使用到了socket.io来实现两个客户端的同步通讯

3.2 代码组织与内部实现设计

在这里插入图片描述

就是尽量解一下嵌套吧,因为游戏玩家做一个动作就需要更新相应的数据,数据容易混在一起,所以就让每个玩家都都独立的数据。内部实现设计就基本是采用封装函数的形式,让代码模块化,可复用性高一点

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

算法的关键就是如何使用全局变量控制程序在用户‘做一件事情’后,程序该调用哪种函数(也就是程序如何响应用户的交互)

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

这个代码用来重置页面,并刷新回合数,局数等,我认为这个比较重要是因为,游戏的多次游玩并不能单靠循环实现,有些地方要resset,而有些地方是update,所以,当一轮游戏结束后,如何重新渲染页面就显得比较重要.

function settlement(){
    // 隐藏网页中的一些元素
    document.querySelector('.desktop').style.display = 'none'; // 隐藏名为"desktop"的元素
    document.querySelector('.odds_select').style.visibility='hidden'; // 隐藏名为"odds_select"的元素的可见性

    // 从网页中获取双方的骰子点数值并存入两个数组arr1和arr2
    for(let i=1;i<=5;i++){
        arr1[i-1]=document.querySelector(`.player-area.left`).querySelector(`.dice${i}`).dataset.value; // 获取左侧玩家区域中骰子点数值
        arr2[i-1]=document.querySelector(`.player-area.right`).querySelector(`.dice${i}`).dataset.value; // 获取右侧玩家区域中骰子点数值
    }

    score(); // 调用score()函数,计算得分

    // 延迟2秒后执行以下操作,等待得分计算完成并进行一些重置操作
    setTimeout(function(){
        reset(); // 调用reset()函数,对需要重置的地方进行重置,确保上一轮的操作完全清除,不会影响下一轮

        current_round++; // 增加当前回合数
        document.querySelector('h1').innerText=`Round:${current_round}`; // 更新网页中显示的当前回合数
        document.querySelector('.Rn-rounds').innerText=`剩余回合:${round-current_round}`; // 更新网页中显示的剩余回合数

        document.querySelector('.desktop').style.display = 'block'; // 显示名为"desktop"的元素,恢复显示网页内容
    },2000); // 设置延迟时间为2秒
}

首先隐藏了一些网页中的元素,然后从网页中获取双方骰子的点数值,并存入两个数组中。接下来调用score()函数来计算得分。之后,通过延迟2秒的操作,在重置一些状态后,增加当前回合数并更新网页中的相关显示内容。最后,显示之前隐藏的网页元素,恢复显示网页内容。

function score(){
    let base1=0; // 玩家1的基础得分
    let base2=0; // 玩家2的基础得分
    let judge1=[0,0,0,0,0,0]; // 玩家1每个点数出现的次数
    let judge2=[0,0,0,0,0,0]; // 玩家2每个点数出现的次数
    let bonus1=0; // 玩家1的额外得分
    let bonus2=0; // 玩家2的额外得分
    let double1=0; // 玩家1的双对数量
    let double2=0; // 玩家2的双对数量
    let triple1=0; // 玩家1的三连数量
    let triple2=0; // 玩家2的三连数量
    let straight1=0; // 玩家1的顺子数量
    let straight2=0; // 玩家2的顺子数量

    // 计算基础得分和点数出现次数
    for(let i=0;i<=4;i++){
        base1+=Number(arr1[i]); // 累加玩家1骰子点数
        base2+=Number(arr2[i]); // 累加玩家2骰子点数
        judge1[Number(arr1[i])-1]++; // 对应的点数出现次数加1
        judge2[Number(arr2[i])-1]++; // 对应的点数出现次数加1
    }

    // 计算玩家1的额外得分
    for(let i=0;i<=5;i++){
        if(judge1[i] === 1){
            straight1++; // 记录顺子出现的点数数量
        }
        if(judge1[i] === 2){
            double1++; // 记录双对出现的点数数量
        }
        if(judge1[i] === 3){
            triple1++; // 记录三连出现的点数数量
        }
        if(judge1[i] === 4){
            bonus1+=40; // 四连,额外得40分
            break; // 只要出现了四连,不需要再判断其他情况
        }
        if(judge1[i] === 5){
            bonus1+=100; // 五连,额外得100分
            break; // 只要出现了五连,不需要再判断其他情况
        }  
    }

    // 根据额外得分情况,给玩家1添加额外得分
    if(double1 === 1 && triple1 === 1){
        bonus1+=20; // 葫芦,额外得20分
    }
    else if(double1 === 2 && triple1 === 0){
        bonus1+=10; // 双对,额外得10分
    }
    else if(double1 === 0 && triple1 === 1){
        bonus1+=10; // 三连,额外得10分
    }

    // 判断玩家1是否出现顺子,并给予相应的额外得分
    if(straight1 === 5){
        if(judge1[0] === 0){
            if(arr1[0] === '2' && arr1[1] === '3' && arr1[2] === '4' && arr1[3] === '5' && arr1[4] === '6'){
                bonus1+=60; // 大顺子,额外得60分
            }
        }
        else if(judge1[5] === 0){
            if(arr1[0] === '1' && arr1[1] === '2' && arr1[2] === '3' && arr1[3] === '4' && arr1[4] === '5'){
                bonus1+=60; // 大顺子,额外得60分
            }
        }
        else if(judge1[1] === 0){
            if(arr1[0] === '1' && arr1[1] === '3' && arr1[2] === '4' && arr1[3] === '5' && arr1[4] === '6'){
                bonus1+=30; // 小顺子,额外得30分
            }
        }
        else if(judge1[2] === 0){
            if(arr1[0] === '1' && arr1[1] === '2' && arr1[2] === '4' && arr1[3] === '5' && arr1[4] === '6'){
                bonus1+=30; // 小顺子,额外得30分
            }
        }
        else if(judge1[3] === 0){
            if(arr1[0] === '1' && arr1[1] === '2' && arr1[2] === '3' && arr1[3] === '5' && arr1[4] === '6'){
                bonus1+=30; // 小顺子,额外得30分
            }
        }
        else if(judge1[4] === 0){
            if(arr1[0] === '1' && arr1[1] === '2' && arr1[2] === '3' && arr1[3] === '4' && arr1[4] === '6'){
                bonus1+=30; // 小顺子,额外得30分
            }
        }
    }

    // 计算玩家2的额外得分
    for(let i=0;i<=5;i++){
        if(judge2[i] === 1){
            straight2++; // 记录顺子出现的点数数量
        }
        if(judge2[i] === 5){
            bonus2+=100; // 五连,额外得100分
            break; // 只要出现了五连,不需要再判断其他情况
        }
        if(judge2[i] === 4){
            bonus2+=40; // 四连,额外得40分
            break; // 只要出现了四连,不需要再判断其他情况
        }
        if(judge2[i] === 3){
            triple2++; // 记录三连出现的点数数量
        }
        if(judge2[i] === 2){
            double2++; // 记录双对出现的点数数量
        }
    }

    // 根据额外得分情况,给玩家2添加额外得分
    if(double2 === 1 && triple2 === 1){
        bonus2+=20; // 葫芦,额外得20分
    }
    else if(double2 === 2 && triple2 === 0){
        bonus2+=10; // 双对,额外得10分
    }
    else if(double2 === 0 && triple2 === 1){
        bonus2+=10; // 三连,额外得10分
    }

    // 判断玩家2是否出现顺子,并给予相应的额外得分
    if(straight2 === 5){
        if(judge2[0] === 0){
            if(arr2[0] === '2' && arr2[1] === '3' && arr2[2] === '4' && arr2[3] === '5' && arr2[4] === '6'){
                bonus2+=60; // 大顺子,额外得60分
            }
        }
        else if(judge2[5] === 0){
            if(arr2[0] === '1' && arr2[1] === '2' && arr2[2] === '3' && arr2[3] === '4' && arr2[4] === '5'){
                bonus2+=60; // 大顺子,额外得60分
            }
        }
        else if(judge2[1] === 0){
            if(arr2[0] === '1' && arr2[1] === '3' && arr2[2] === '4' && arr2[3] === '5' && arr2[4] === '6'){
                bonus2+=30; // 小顺子,额外得30分
            }
        }
        else if(judge2[2] === 0){
            if(arr2[0] === '1' && arr2[1] === '2' && arr2[2] === '4' && arr2[3] === '5' && arr2[4] === '6'){
                bonus2+=30; // 小顺子,额外得30分
            }
        }
        else if(judge2[3] === 0){
            if(arr2[0] === '1' && arr2[1] === '2' && arr2[2] === '3' && arr2[3] === '5' && arr2[4] === '6'){
                bonus2+=30; // 小顺子,额外得30分
            }
        }
        else if(judge2[4] === 0){
            if(arr2[0] === '1' && arr2[1] === '2' && arr2[2] === '3' && arr2[3] === '4' && arr2[4] === '6'){
                bonus2+=30; // 小顺子,额外得30分
            }
        }
    }
    
    const final1 = base1 + bonus1; // 玩家1的最终得分
    const final2 = base2 + bonus2; // 玩家2的最终得分

    let str = document.querySelector('.Total-odds').innerText; // 获取网页中显示的赔率字符串
    let str1 = document.querySelector('.chip.left').innerText; // 获取网页中显示的玩家1筹码字符串
    let str2 = document.querySelector('.chip.right').innerText; // 获取网页中显示的玩家2筹码字符串

    const odd = Number(str.slice(4)); // 解析赔率的数值部分
    let chip1 = Number(str1.slice(3)); // 解析玩家1的筹码数量
    let chip2 = Number(str2.slice(3)); // 解析玩家2的筹码数量

    let final; // 最后的得分差额
    if(final1 > final2){
        final = (final1 - final2) * odd; // 计算得分差额
        chip1 += final; // 玩家1获得得分差额的筹码
        chip2 -= final; // 玩家2失去得分差额的筹码
    }
    else{
        final = (final2 - final1) * odd; // 计算得分差额
        chip1 -= final; // 玩家1失去得分差额的筹码
        chip2 += final; // 玩家2获得得分差额的筹码
    }

    // 在网页中更新最新的筹码数量
    document.querySelector('.chip.left').innerText = `筹码:${chip1}`;
    document.querySelector('.chip.right').innerText = `筹码:${chip2}`;

    // 打印最终得分和玩家筹码数量,用于调试
    console.log(final1);
    console.log(final2);
    console.log(chip1);
    console.log(chip2);
}

首先,我定义了一系列的变量用于存储得分和各种情况的统计数量。然后,通过循环遍历玩家的骰子点数,累加基础得分并统计每个点数出现的次数。接下来,根据点数出现的次数和规则,计算额外得分,包括连续的顺子和相同点数的组合(如双对、三连等)。之后,根据赔率和得分差额,更新玩家的筹码数量。最后,通过修改网页中相应的元素,更新显示最新的筹码数量。

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

在这里插入图片描述

四、总结反思

4.1 本次任务的PSP表格

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

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

吴文景

第N周新增代码(行)累计代码(行)本周学习耗时(小时)累计学习耗时(小时)重要成长
17807803131学习前端知识,html
289516753263学习前端,css,js
3945261832100交互式设计,socket.js
45473k+32132websocket,node.js后端
第N周新增代码(行)累计代码(行)本周学习耗时(小时)累计学习耗时(小时)重要成长
15405403131学习后端知识,springboot
298715273263学习后端,java stream流
3991251832100交互式设计,websocket
4668318628128ui,原型设计

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

最初想法比较丰富,比如背景音乐和多人随机匹配啥的,但是理想很丰满,现实很骨感。知识储备和编程能力始终是一个大坑,其中web编程困扰了我们许多天,后端服务器搭建起来到最后也没太搞明白,只能舍弃掉这种想法。最后只实现了两个人联机对战。其次是原型设计,两个大老粗的艺术细胞都接近负数,不会ps也不会设计,最后在网上找来找去找了几张图贯穿全局。总的来说,我们基本都是从零开始学起,包括前端后端和原型设计,花费了许多时间在上面,最后也算勉强完成作业。

4.4 评价你的队友

102101315 王辉凡:
队友的技术能力十分突出。他不仅对编程语言和开发工具的掌握十分熟练,而且有着解决复杂问题的能力,在前端页面开发和大部分js的编写完成的很好。在面临困难和挑战时,他总是能迅速找到解决方案,为我们的作业的完成提供重要支持。他的思维方很全面。

102101322吴文景:
我的队友是一个非常勤奋和有毅力的人。在这次作业中,他始终保持积极的态度,全身心投入到后端开发和原型设计中。即使遇到困难和挫折,他也从不轻言放弃,而是坚持不懈地寻求解决方案。

4.5 结对编程作业心得体会

102101315王辉凡:

  • 首先,这是我第一次完整的开发一个小游戏,给我带来了许多经验和挑战。对于没有项目经验的小白来说,这次作业让我系统性的运用所学的知识,以及不断地学习新的知识,包括后端框架,原型设计,stream数据流的学习与使用。都让我拥有了一次深刻的体验。
  • 其次,这也是我第一次结对完成任务。结对编程的精髓在于团队的协作和沟通。每个人都有自己的长处和短处,只有通过互相学习,互相补充,才能达到最好的效果。在我们的项目中,我主要负责了页面的设计和交互,而我的队友则主要负责了逻辑处理以及页面实现。我们的工作虽然各有侧重,但是在整个开发过程中,我们始终保持密切的交流,不断地分享我们的想法和见解。
    +最后,在编程过程中,我们难免会遇到各种预料之外的问题。但是,正是通过解决这些问题,我们才能更好地理解编程的实际操作。摇骰子的逻辑看似简单,但在实际操作中却遇到了各种困难,如如何设计摇骰子的算法,如何处理用户的不正当操作等。通过不断地试错和学习,我们最终成功地完成了这个项目。

通过这次结对编程的作业,我不仅提高了自己的编程技能,也深刻理解了团队协作的重要性。

102101322吴文景:
首先为了完成这次作业,我深入地学习和了解了前端三件套(js,html,css)的知识,以及websocket网络编程的知识,让我的技能点多了许多,我的编程能力也得到了一定的提高。
其次,这是我头一次与他人结对编程完成作业,这给我带来了许多收获和启发。它让我明白了协作和沟通的重要性,因为与队友密切合作是成功的关键,即使遇到挑战,通过共同讨论和解决问题,我学到了更多,获得了更好的提升。在解决代码模块异常时,及时的代码审查和互相提供反馈是关键。最重要的是,结对编程让我认识到在软件开发中团队协作的价值。它也启发了我更多关于不同编程方法和技术的学习,以改进我的技能。通过互相学习,我觉得更有信心应对未来的编程项目。
最后,能够完成这份作业让我感到十分的愉悦,满满的成就感是前所未有的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值