https://link.csdn.net/?target=https%3A%2F%2Fgithub.com%2Fmilkqu26%2FWYQ%2Ftree%2Fall-in GitHub链接
一.结对探索
1.1队伍基本信息
结对编号:38 队伍名称:拉拉队
学号 | 姓名 | 作业博客链接 | 具体分工 |
---|---|---|---|
102101109 | 韩欣华 | https://editor.csdn.net/md?not_checkout=1&spm=1035.2248.3001.5352&articleId=133800008 | 代码设计、代码测试 |
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.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 5040 | 5740 |
-Estimate | -估计这个任务需要多少时间 | 5040 | 5740 |
Development | 开发 | 4860 | 5500 |
-Analysis | -需求分析(包括学习新技术) | 660 | 480 |
-Design Spec | -生成设计文档 | 60 | 90 |
-Design Review | -设计复审 | 30 | 120 |
-Coding Standard | -代码规范 | 30 | 60 |
-Design | -具体设计 | 120 | 840 |
-Coding | -具体编码 | 3780 | 3680 |
-Code Review | -代码复审 | 60 | 60 |
-Test | -测试(自我测试,修改代码,提交修改) | 120 | 30 |
Reporting | 报告 | 180 | 240 |
-Test Repor | -测试报告 | 120 | 30 |
-Size Measurement | -计算工作量 | 30 | 50 |
-Postmortem & Process Improment Plan | -事后总结,并提出过程改进计划 | 30 | 60 |
-合计 | 5160 | 5740 |
4.2学习进度条(每周追加)
-
魏燕清
第N周 新增代码(行) 累计代码(行) 本周学习耗时(小时) 累计学习耗时(小时) 重要成长 1 0 0 10 10 寻找素材,学习HTML和CSS,掌握Axure软件的使用方法,进行原型设计 2 1458 1458 30 40 编写前端页面代码 3 2079 3537 24 64 学习JS,编写页面中的交互效果
-
韩欣华
第N周 | 新增代码(行) | 累计代码(行) | 本周学习耗时(小时) | 累计学习耗时(小时) | 重要成长 |
---|---|---|---|---|---|
1 | 70 | 70 | 12 | 12 | 构思C++实现思路,实现基本布局 |
2 | 121 | 191 | 27 | 39 | 编写主要函数 |
3 | 89 | 280 | 25 | 64 | 制作 总体代码内容 |
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方面的问题占用了很小一部分时间。这个作业的难度主要是在于我并不了解前后端交互问题,我不知道怎么让他们拼接在一起,因为这一部分真的就是没有实践过,我没有这个经验。不过说实话,在写后端的时候我还是真的学到了很多东西,我可能之前在算法中不会实践的内容这次完完整整的掌握了,而且也极大的提高了我思维能力,运用函数块是一个很方便的编写程序的方法。这样断断续续的完成,在单元测试出来那一瞬间我真的有一种从所未有的自豪感,没想到我也能写出来这一游戏!
就是这样的一个表情。这个作业进入了尾声了马上结束了,我觉得还是对我挺有用的,我学会了很多新的东西,巩固了曾经的东西,我也很感谢我的队友,她帮我解决了一些我构思很久想不出来的问题。
- 心得体会:
</article>