2023软工K班结对编程任务

Github

B站链接

一.结对探索

1.1队伍基本信息

结对编号:38  队伍名称:拉拉队

学号姓名作业博客链接具体分工
102101109韩欣华https://blog.csdn.net/2301_77513568/article/details/133797922代码设计、代码测试
102101110魏燕清2023软工K班结对编程任务_102101110的博客-CSDN博客原型设计、前端编写、性能分析

1.2描述结对的过程

我们是同班同学,日常一起上课,交流起来很方便。

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

二.原型设计

2.1原型工具的选择

我们主要选择了Axure RP,iconpark

Axure RP是一款免费的可以进行原型设计的软件,并且最后可以导出成html文件,为编写前端程序减轻了一点负担;

iconpark是图标矢量库,可以提供大量免费的素材

2.2遇到的困难与解决方法

困难:
  • 首先,一开始根本不知道什么是原型设计,应该用什么去做

  • 网上推荐使用的软件很多,但是尝试了一下发现很多并不是很好用。比如我一开始使用墨客,制作了三张页面之后,他告诉我要收费了??!崩溃。然后我还使用了墨刀,是很容易上手,但是感觉功能有些欠缺。于是最后使用了Axure RP

  • 素材:网上的资源很多但是符合心意的很难挑选,总感觉页面不够美观

解决方案:

先是在博客园中查找,了解了一下原型设计这是个什么东西,在这个软件开发中有什么用。然后,通过一个个软件的试错,最后确定了我们要使用的Axure。一开始我们找素材就是直接在浏览器中搜索,但是这种图片一般质量很低,后来通过询问GPT,它推荐了Pixabay网站和iconpark。

2.3原型作品链接

 原型设计

2.4原型界面图片展式

1.游戏首页

需要用户登录,注册;右上角是背景音乐控制键,可以控制背景音乐播放和停止

2.本地对战

设置游戏局数,筹码数

正式游戏页面

3.人机对战

4.在线对战

房间号:动态随机生成一个六位数

5.对战结果

6.关于

创新点

1.我们在右上角添加了背景音乐开关,点击时可以切换不同的图片控制背景音乐的 开关

2.在绘画艺术中,「孤注一掷」 可以理解为画家在作品创作时的勇敢和决心,并且投入了全部的心力。这种情感与独特的韵相结合,给作品带来了独特的魅力。
而水墨风则是一种以中国传统水墨画为基础的艺术风格。水墨画追求简洁、含蓄和意境,通过墨色的浓淡、线条的变化以及 留白的运用来表现事物的形态和情感。水墨画通常具有一种深邃、 灵动、凝重的氛围,给人以超然的美感。
在创作水墨画时,画家常常需要孤注一掷, 毫不吝啬地将自己的情感和灵感倾注到作品中。他们像是在画布上注入了生命的力量,通过稳定的手法和独特的笔触,展现出水墨画特有的凝重和灵动的韵味。这种勇敢追求艺术和以心传情的态度,让水墨画更加饱含了生命的力量和创作者的独特个性。
可以体会到「孤注一掷」 与「水墨风」之间的共通之处,即对艺术的投入和追求,以及将自己的情感融 入作品中的表现力。

所以在整体设计时,我们采用水墨画为主要背景。

三、编程实现(14分)

3.1 网络接口的使用(2分)

主要使用WebSockets进行实时通信,用于服务器端和客户端之间的数据交互;还有在线对战时多名玩家之间传递数据

例如websocket_connect建立连接,websocket_receive接收客户端消息,然后通过redis返回即可,最好一定用websocket_disconnect断开与客户机的连接,客户机也可以用socketonclose来断开连接。

还利用到了Fetch API,实现将游戏结果发送到服务器,或者从服务器获取其他数据,利用这些API进行AJAX请求

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

以下是一些类的主要方法和代码的组织:
主要类:
  • 牌类

    • sock(dice* a,int q,int* n1,int r,int fg):锁定位置以及计算倍率

    • count1(dice * a):计算骰子组合的分数

    • init(dice* a):初始化dice类中的锁定点数lock

    • cmp(dice &a,dice &b):交换排序

  • 玩家类

    • twopeople();随即生成两个玩家的骰子组合

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

对于分数计算,首先先统计不同骰子元素出现的次数,让这些内容放在一个count数组里面,方便调用计算,其次先判断是否为四连和五连还有三连,这三块很容易,只需要一个while循环调用count数组看看count的内容是否存在count[i]是否等于3,4,5就好,这里无论i是几,也就是骰子点数为几都可以直接进行判断,然后如果是四连和五连的话,那么可以直接对sum也就是分数计算,退出函数了。但是如果是三连的话,还要判断一下是否为葫芦,这里仍旧是使用了一个循环,这里的小循环和大循环的内容一样来判断count[i]是否等于2,如果等于的话,sum+10,也就是三连本身sum+10的基础上再加10。
然后是判断是否为双对,双对和三连是一样的,只不过小循环的j,是从大循环判断好的i后面再进行判断。
之后是对小顺子和大顺子进行判断,这里首先先使用了递增数列删除重复项,这样再利用循环判断会很方便,删除重复项后只需要对数组内递增数列的个数dest进行判断就行,看看是否为连续的递增数列就能最后进行判断
 

流程图:

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

判断骰子组合中的小顺子和大顺子思考了很久,因为就算先给骰子组合进行了排序,也还是难以判断,如果前后有重复项就很难用平时想的骰子点数加1一直到末尾看是否为顺子来进行判断,后面想到了算法中递增数列删除重复项的方法来解决这一问题,只要删除了重复项,那么就可以直接判断

//判断玩家的牌面,计算赢得的筹码数
int count1(dice * a)
{
    int count[10] = { 0 };
    int sum = 0;
    int flag1 = 1;
    int flag2 = 1;
    for (int i = 0; i < 5; i++)
    {
        count[a[i].d]++;
    }
    sort(a, a+5, cmp);
    for (int i = 1; i <= 6; i++)
    {
        if (count[i] == 5)
        {
            sum += 100;
            break;
        }//五连加100
        else if (count[i] == 4)
        {
            sum += 40;
            break;
        }//四连 
        else if (count[i] == 3)
        {
            int p = 1;
            sum += 10;
            while (p <= 6)
            {
                if (count[p] == 2) sum += 10;
                p++;
            }
            break;
        }//三连和葫芦
        else if (count[i] == 2)
        {
            int p = i + 1;
            while (p <= 6)
            {
                if (count[p] == 2) sum += 10;
                p++;
            }
            break;
        }//双对
    }
    int b[10] = { 0 };
    int t = 0;
    int dest = 0;
    int cur = 1;
    a[dest].d = a[0].d;
    //从cur==1  cur<numsSize
    while (cur < 5)
    {
        if (a[cur].d != a[dest].d)
        {
            b[t] = a[dest].d;
            a[++dest].d = a[cur++].d;
            t++;
        }
        else
        {
            cur++;
        }
    }//递增数列删除重复项
    b[dest] = a[dest].d;
    if (dest == 4)
    {
        int m = dest;
        while (m != 0)
        {
            if (b[m] != b[m - 1] + 1)
            {
                flag1 = 0;
                break;
            }
            m--;
        }
    }//判断大顺子
    else if (dest == 3)
    {
        int m = dest;
        while (m != 0)
        {
            if (b[m] != b[m - 1] + 1)
            {
                flag2 = 0;
                break;
            }
            m--;
        }
    }//判断小顺子
    if (flag1 == 1 && dest == 4)
        sum += 60;
    if (flag2 == 1 && dest == 3)
        sum += 30;
    return sum;
}
​

这一片段是进行骰子锁定,这一片段的思路就是输入要锁定的位置后转成数组,看数组的元素等于哪一个位置的下标,然后让lock为1,进行锁定,不相等的就进行此位置生成随机数

typedef struct  {
    int d;//骰子点数
    int lock;//锁定点数
}dice;
void sock(dice* a,int q,int* n1,int r,int fg)
{
    cout << "你要锁定的位置: ";
    char b1[10];
    int num1 = 0;//t的长度
    cin.getline(b1, 10);
    int t[10] = { 0 };
    int m1[10] = { 0 };//锁定区域
    for (size_t i = 0; i < strlen(b1); i++) {
        t[i] = t[i] * 10 + (b1[i] - '0');
        num1++;
    }
    cout << "你要锁定的数字为: ";
    if (num1 != 0) 
    for (int i = 0; i < num1; i++)
    {
        m1[i] = a[t[i]-1].d;
        cout << m1[i] << " ";
    }
    cout << endl;
    for (int i = 0; i < 5; i++)
    {
        int flag = 0;
        for (int j = 0; j < num1; j++)
            if (i == t[j]-1) {
                flag = 1;
                a[i].lock = 1;
                break;
            }
        srand(time(0));
        std::random_device rd;
        std::mt19937 gen(rd());
        std::uniform_int_distribution<int> dis(1, 6);
        if (flag == 0&& a[i].lock == 0)
        {
            a[i].d = dis(gen);
            n1[r] = a[i].d;
            r++;
        }
    }//进行锁定
    cout << "新的数组为: ";
    for (int i = 0; i < 5; i++)
    {
        cout << a[i].d << " ";
    }
    cout << endl;
    if (q < 5 && sum_round<4) {
        cout << "你可以选择的区域为: ";
        for (int i = q; i < r; i++, q++)
            cout << n1[i] << " ";
        cout << endl;
    }
    cout << "选择您的倍数:[1,2,3] ";
    if (fg == 1)
    {
        cin >> mul1w1;
        cin.get();
        mulw1 = mul1w1 * mulw1;
    }
    else if (fg == 2)
    {
        cin >> mul1w2;
        cin.get();
        mulw2 = mul1w2 * mulw2;
    }
    sum_round++;
}

3.5 性能分析与改进(2分)

(描述你改进的思路,展示性能分析图和程序中消耗最大的函数)

由上图可以看出:消耗最大的是sock()函数,就是当玩家确认后要锁住骰子点数的函数。

改进:可以减少函数使用的参数个数,修改定义的dice类,将锁标志放在函数当中。

3.6 单元测试(2分)

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

//测试
void test()
{
	cout << "设置局数: ";
	cin >> numl;
	cout << "设置筹码: ";
	int dollor;//筹码
	cin >> dollor;
	int dollor1 = dollor;
	int dollor2 = dollor;
	cin.get();
	for (int i = 0; i < numl; i++)
	{
		q1 = 0;
		q2 = 0;
		r1 = 0;
		r2 = 0;
		sum_round = 1;
		init(a);
		init(b);
		twopeople();
		mulw1 = 1;
		mulw2 = 1;
		while (sum_round < 5)
		{
			sock(a, q1, n1, r1, 1);
			sock(b, q2, n2, r2, 2);
		}
		cout << "玩家1的分数: ";
		cout << count1(a) << endl;
		cout << "玩家2的分数: ";
		cout << count1(b) << endl;
		if (count1(a) > count1(b))
		{
			dollor1 = dollor1 + mulw1 * (count1(a) - count1(b));
			cout << "玩家1从玩家2手里获得的筹码数:" << mulw1 * (count1(a) - count1(b)) << endl;
		}
		else if (count1(a) == count1(b))
		{
			cout << "平局" << endl;
		}
		else
		{
			dollor2 = dollor2 + mulw2 * (count1(b) - count1(a));
			cout << "玩家2从玩家1手里获得的筹码数:" << mulw2 * (count1(b) - count1(a)) << endl;
		}
	}
	cout << "玩家1的筹码为: " << dollor1 << endl;
	cout << "玩家2的筹码为: " << dollor2 << endl;
	if (dollor1 > dollor2) {
		cout << "玩家1获胜" << endl;
	}
	else if (dollor1 == dollor2)
		cout << "平局" << endl;
	else
		cout << "玩家2获胜" << endl;
}

思路:简单运行一下,查看编写的游戏逻辑是否有错。

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

四.反思与总结

4.1 本次任务的PSP表格(2分)

PSP2.1Personal Software Process Stages预估耗时(分钟)实际耗时(分钟)
Planning计划50405740
-Estimate-估计这个任务需要多少时间50405740
Development开发48605500
-Analysis-需求分析(包括学习新技术)660480
-Design Spec-生成设计文档6090
-Design Review-设计复审30120
-Coding Standard-代码规范3060
-Design-具体设计120840
-Coding-具体编码37803680
-Code Review-代码复审6060
-Test-测试(自我测试,修改代码,提交修改)12030
Reporting报告180240
-Test Repor-测试报告12030
-Size Measurement-计算工作量3050
-Postmortem & Process Improment Plan-事后总结,并提出过程改进计划3060
-合计51605740

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

  • 魏燕清

    第N周新增代码(行)累计代码(行)本周学习耗时(小时)累计学习耗时(小时)重要成长
    1001010寻找素材,学习HTML和CSS,掌握Axure软件的使用方法,进行原型设计
    2145814583040编写前端页面代码
    3207935372464学习JS,编写页面中的交互效果
  • 韩欣华

第N周新增代码(行)累计代码(行)本周学习耗时(小时)累计学习耗时(小时)重要成长
170701212构思C++实现思路,实现基本布局
21211912739编写主要函数
3892802564制作 总体代码内容

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

(也就是谈一谈本次任务中“理想与现实的差距”,是哪些因素造成了这些差距?)

想象中的产品是想开发成微信小程序的一个多人联机,可以进行双人对战和人机对战以及增加各种趣味玩法的,但是事实上算法思考的问题很多,还有一些bug需要反复修复。后端要学习的东西很多,把基本算法写出来后还要学习后端的很多以及和前端进行交互,还要学习接口,而且只能进行网页版制作.产品最后的页面形态和预想的差不多,进行原型设计的时候非常顺利,但是自己编写前端代码的时候就会遇到各种问题,导致页面看起来没有原型设计的时候合理、流畅。开发成果没有达到预期,本来以后前端和后端可以分开编写,没有考虑到它们需要交互!!

4.4 评价你的队友(2分)

(分别评价队友值得学习的地方需要改进的地方) (本部分需要包含队伍内所有成员的心得体会,若缺少一人,则队伍总分减少2分,减满4分为止)

  • 魏燕清

    评价队友:队友最让我佩服的一点就是在国庆节期间写这个程序写了很久,她负责前端部分,基本都是初学,我应该学习她在节假日放松期间仍然能够进行学习和自我进步 改进的地方:我们之间交流较少,所以后续的同步问题比较严重

  • 韩欣华

    评价队友:在这次之前我们都没有过做项目的经验,在这次结对编程期间,她也很负责地写完了这个骰子小游戏的逻辑部分,基本复现了群里的要求,已经有了很大进步!不过在前后端交互的时候有点欠缺,可以再多改进一点

4.5 结对编程作业心得体会(3分)

(可包含但不限于评价作业难度、完成后的感受、遇到的代码模块异常或结对困难及解决方法、对之后学习或软件开发的启发) (本部分需要包含队伍内所有成员的心得体会,若缺少一人,则队伍总分减少3分,减满6分为止)

  • 魏燕清

    • 作业还是有点难的,之前我只自学过HTML CSS JS之类的一些前端知识,但是还没有自己上手做过项目T~T。这次作业也让我捡起来了之前学过的东西,锻炼了自己的动手能力。然后在写一些页面交互效果的时候,一开始非常不熟悉JS的语法和怎么编写,但是一回生二回熟,多写几个页面就好咯~在这次作业过程中,和队友交流的不够多,导致很多地方实现的不够好T~T,以后要注意沟通的主要性!

  • 韩欣华

    • 心得体会:
      这个作业我认为还是挺有挑战性的吧,其实代码的内容,我觉得并没有说特别难的地方,基本其实靠着数组就完全可以做出来,主要就是构思这些后端代码块和连接问题真的很需要逻辑,说实话我敲代码并没有说敲了特别久,主要就是构思占用了很大很大的时间,在作业发布期间,我没事干我就会构思这些内容,函数要写的部分,基本上就是每天都会花时间去想究竟要怎么才能实现这类功能,所以构思真的占用了我非常大的时间,然后就是一开始写的时候,就直接用构思好的东西写了很多很多,结果出现了bug都不知道哪里出错了,还是依靠我的队友来完成的,我还是很感谢我的队友,她不仅是前端设计,在一些构思方面也帮了我很大的忙,哭死。然后就这个第一块的代码bug找了很久之后我就学会了边写边测试,尽量让我之后不会再遇到bug不知道在哪里出现的情况,就是因为这一行为的改变,再写后续部分的代码bug方面的问题占用了很小一部分时间。这个作业的难度主要是在于我并不了解前后端交互问题,我不知道怎么让他们拼接在一起,因为这一部分真的就是没有实践过,我没有这个经验。不过说实话,在写后端的时候我还是真的学到了很多东西,我可能之前在算法中不会实践的内容这次完完整整的掌握了,而且也极大的提高了我思维能力,运用函数块是一个很方便的编写程序的方法。这样断断续续的完成,在单元测试出来那一瞬间我真的有一种从所未有的自豪感,没想到我也能写出来这一游戏!
      就是这样的一个表情。这个作业进入了尾声了马上结束了,我觉得还是对我挺有用的,我学会了很多新的东西,巩固了曾经的东西,我也很感谢我的队友,她帮我解决了一些我构思很久想不出来的问题。
       
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值