2022软工K班结对编程任务

朱志鹏102192108 2022-10-14 21:52:12

https://github.com/workhardhhh/GameWork
https://www.bilibili.com/video/BV1Fe4y1J7P4/

一、结对探索(4分)

​ 1.1 队伍基本信息(1分)

​ 结对编号:__43__;队伍名称:__没有__;

学号姓名作业博客链接具体分工
102192113欧阳欣泽https://bbs.csdn.net/topics/608611758代码设计以及具体实现
102192108朱志鹏https://bbs.csdn.net/topics/608612331原型设计及代码测试

1.2 描述结对的过程(1分)

跟欧阳是同班且同宿舍,以往作业也有组队过。

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

img

二、原型设计(16分)

2.1 原型工具的选择(2分)

原型选择用墨刀来进行涉及。选择着个工具一方面是支持国产设计工具,一方面是这款产品之前有用过。原本有考虑使用Figma,但搜索时出来的词条都被国内软件厂商投放走了,如即时设计、MasterGo等,也简单了解了下产品功能,考虑到骰子游戏的原型相对还比较简单,墨刀基本就能满足就顺手使用了。

在使用的过程中,也发现墨刀相对于另外两款原型设计工具,虽然更好上手一点,但整体功能和资源等细节方面也会稍显不足或有所限制。一些原型交互的功能在交互实现上并不能够十分地深度实现,后面一部分设计也是选择了曲线方式来伪实现。

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

原型设计中,首先要设计整体的框架,逻辑结构,其次根据结构需要准备好大部分相关的设计资源,由于之前并没有怎么做设计,在寻找资源方面也花了不少时间。

而在具体原型设计过程中,碰到了两次比较卡壳的地方,卡壳的原因是墨刀产品本身组件或功能的限制,如第一个卡壳的地方是在直接复制模块后,在模块上的触发事件的设置并不能够独立开,而是同步地更新设置,这使得我在设置骰子掷/置过程中,前后两页的事件触发老是前后出错,后面定位到可能存在的问题区域后,再针对性的进行测试,判断大概率是他们组件本身就是这样的一个逻辑,后面通过官方客服咨询佐证了我的一个判断。

第二个卡壳部分,是后面整体游戏逻辑已经梳理完毕后,想要再设计掷骰子、置骰子的一些简单动效,使得整体游戏原型的展示更加地真实,就花了比较多的事件在一局已设计的既定游戏过程中不断地调整不同页面切换的动效动画效果(约9*4=36页,每页有4个主要动效),在盘这些逻辑的时候,也遇到整个页面事件中,定时器设置无法设置两个以上组件状态变化,后面只能在游戏细节动效有一定舍弃,但整体上解决了问题。

比较麻烦的后面模拟的一次游戏过程,甲乙双方按顺序掷骰子、置骰子,穿插一次骰子消除的游戏模拟画面。因为希望整个过程尽可能地更像是真实的游戏,所以在动效细节上花了比较多的时间去掌握相关组件功能是使用,和在目标游戏动效的实现上需要如何使用,同时也需要不断梳理前后逻辑,这个比较耗费时间。

整体而言,原型设计下来,首先需要有一定的平面UI设计的能力,能快速地找到相关的设计素材实现目标UI的设计,由于本身在设计这方面技能一般,只能在现有资源基础上东拼西凑。其次,在原型设计上,整体框架在讨论后确立下来,即可按照既定框架去设计,但是在后续的原型设计协同上还比较缺乏,主要就由我这边找素材做设计,再跟欧阳那边沟通根据他的需求就细节做一些调整,在原型设计协同上还可以加强。最后,就是原型设计工具是否优秀,某种程度上也会限制原型开发的效率,如果原型没法直接实现功能动效需求,可能就得要在现有组件功能边界上通过别的也许是更低效更原始的方式方法来基本满足目标效果的实现。当然如有时间其实也可以多使用和比较几款不同的设计工具,最后选择一款适合自己的工具来使用。而且在使用的过程中,由于工具某些功能的限制产生的不便,就会下意识反推自己所需要的效果,有可能通过什么方式设计修改能够满足,这种可能优化修改的判断过程还比较令人感觉到兴奋。

2.3 原型作品链接(5分)

https://modao.cc/app/FTVBULBrjcbny46ndPN45 #逍遥骰子-逍遥骰子-原型

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

  • 游戏开始页面

    img

  • 游戏菜单

    菜单内,可查看游戏规则介绍和得分排行,设置游戏模式;选择退出游戏则返回到首页;开始游戏时,跳出玩家姓名输入弹窗
    

    img

  • 开始游戏

    玩家姓名输入弹窗,输入后点击确认进入游戏对战;点击取消则关闭游戏弹窗
    

    img

  • 模式选择

    模拟了选择游戏模式后,该模式选项颜色变为白色,其他选项则变为红色,此后自动返回游戏菜单页面
    

    img

  • 游戏介绍

    点击右下角返回按钮后回单菜单页
    

    img

  • 得分排行榜

    展示游戏得分排行榜前十名,点击右下角返回按钮后回单菜单页
    

    img

  • 游戏页面

    点击底部置骰子,开始置骰子
    

    img

  • 置骰子

    掷完骰子,提示字变为白色“置骰子”,点击相应的九宫格棋盘,将骰子置入后,判断是否需要消去骰子,并计算得分显示出来;此后骰子区域变回置骰子状态
    

    img

  • 游戏胜利结束

    游戏判断结束时,计算游戏得分并展示,同时显示胜利方画面;点击结束游戏可返回游戏菜单
    

    img

三、编程实现(14分)

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

由于程序是VS+QT开发项目,实现网络交互则需要QT的套接口函数,即还需建立一个服务器应用程序作为中转站,游戏程序为客户端,客户端与服务器通过套接口函数进行TCP连接,客户端在服务器注册房间号,服务器为同号房间的客户端进行转发,客户端实时发送自身的棋盘信息,玩家的顺序信号,另一方则根据发来的信息更新自己的棋盘并作出决策将改变后的棋盘以及玩家的顺序信号发回。由此实现网络通信对战。

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

如图所示主界面持有其他各个状态界面的引用,从而实现在主界面进行动态切换实现不同的监听事件。整体设计按照界面作为划分进行设计,即对每个页面单个设计后由主界面将其整合。

img

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

如图为AI算法流程图以及主界面程序流程图,ai算法采用递归树的方法进行计算,对每个坐标决策完之后的棋盘根据给定树高度进行递归,遍历所有可能情况,得到胜利场次以及失败场次从而计算胜利概率,取最大胜利概率的坐标为决策坐标。

img

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

Index Ai::get_next_step(int** myboard, int** enemyboard, int number)
{
    int** mbd = NULL;
    int** ebd = NULL;
    Index decision = { 0 };
    Index max_index = { 0 };
    double max = 0;
    //判断当前棋盘已有的骰子数目
    int count = 0;
    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            if (myboard[i][j] != 0)
            {
                count++;
            }
            if (enemyboard[i][j] != 0)
            {
                count++;
            }
        }
    }
    //根据骰子数目不同调整递归树的深度
    if (count <= 4)
    {
        tree_depth = 1;
    }
    else if (count > 4 && count <= 9)
    {
        tree_depth = 2;
    }
    else if (count > 9 && count <= 15)
    {
        tree_depth = 3;
    }
    else
    {
        tree_depth = 4;
    }
    //尝试不同位置的放置,获取相应动作递归树返回的胜利概率,以胜利概率最大位置作为决策位置
    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            //复制当前棋盘状况
            mbd = copy_board(myboard);
            ebd = copy_board(enemyboard);
            //若当前位置无值则放置
            if (ebd[i][j] == 0)
            {

                decision.i = i;
                decision.flag = 1;
                decision.j = j;
                ebd[i][j] = number;
                if (is_inline(number, mbd[i], 3))
                {
                    clear_board_line(mbd[i], 3, number);
                }
                double win = 0;
                double fail = 0;
                double problity = 0;
                Decision_tree* root = (Decision_tree*)calloc(1, sizeof(Decision_tree));
                //填充根节点
                fill_Decision(root, mbd, ebd, decision);
                //建立递归树
                build_tree(root, 0, &win, &fail);
                //计算获胜概率
                problity = win / (win + fail);
                cout << "pro" << problity << endl;
                //最大概率位置为决策位置
                if (max < problity)
                {
                    max = problity;
                    max_index.i = i;
                    max_index.j = j;
                }

            }
            free_int(mbd, 3);
            free_int(ebd, 3);

        }

    }
    if (max == 0)
    {
        for (int i = 0; i < 3; i++)
        {
            for (int j = 0; j < 3; j++)
            {
                if (enemyboard[i][j] == 0)
                {
                    max_index.i = i;
                    max_index.j = j;
                }
            }
        }
    }

    return max_index;
}

该函数为AI获取下一步函数,返回值为Index结构体存储的是其二维数组的下标,函数首先计算棋盘所剩总共的棋子数目,对于起初棋盘位置的放置的影响要小于后面已有较多棋子的局面,基本上棋子越多其决策的影响就越大,故根据当前棋子数目规定递归树的高度,棋子越多递归越多次。
获取棋子数后进入下一步对每一个空位置进行尝试,递归生成树计算获胜概率,后选择最大获胜概率作为决策位置,最后一步对max的判定则是考虑只有最后一个空格的情况则直接填充。返回坐标值。

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

img

img

img

由上图可知占用内存较大的是在QWidgets中继承的绘制图片函数的方法,以及QPainter的Paintevent方法,考虑优化方法只要有外部优化和内部优化,外部优化即对图片进行压缩,而内部优化则考虑存储图片的QPixmap结构体有许多是在函数中声明后被重复绘制而未能及时地释放,从而导致内存不断上涨,考虑将结构体存储为全局变量绘制方法中只需修改已经声明地全局变量结构体的值,这样在初始的时候可能会消耗多点的内存但有利于游戏的长时间的运行。

3.6 单元测试(2分)

void test()
{
    int mybord[3][3] = { {1, 0, 0,}, {6, 6, 6}, {2, 3, 4} };
    int enembord[3][3] = { {2, 0, 2,}, {0, 0, 0}, {2, 3, 4} };
    int number = 6;
    Index index = get_next_step(mybord, enembord, number);
    cout << "getindex i= " << index.i << "j = " << index.j << endl;
}

测试函数为Ai的下一步函数即get_next_step(),主要是考虑此ai函数是否能返回一个决策较好的位置,故在测试数据上将一行全置为最大,将决策的得分差设置得比较明显,来判断ai决策效果的好坏。同时也测试ai决策的速度从而调整递归树高度的设置,因为递归树过高的话极度消耗CPU资源,ai的决策速度也比较慢,因此需要综合决策效果以及决策速度考虑需要选择一个综合性能较好的树高度,也是通过该测试函数进行测试。

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

img

四、总结反思(11分)

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

img

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

第N周新增代码(行)累计代码(行)本周学习耗时(小时)累计学习耗时(小时)重要成长
10055学习了原型工具的使用,主要参与了整体框架的设计,以及相关设计素材的整理
225025038复习了之前Java和面向对象的知识,参与一些基础页面代码

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

朱志鹏:原型设计以设计原型的平面为主,需要辅以相关的文字进行细节和功能效果的说明。而随着设计工具的进步,一些简单的事件触发、动效功能也能之间展示在原型上,这一定程度上更利于开发者理解原型需求。当然也是这次的游戏设计相对功能比较简单,如果碰到功能复杂的项目,原型设计会更加的复杂,细节页面和细节动态会更繁复,也会占据着比较多的时间。原型设计能够在一定程度上把想象中的产品形态进行平面化显示,但并不能完全地展示想象产品中的复杂功能,需要通过画面或文字说明进行补充。而在原型设计的基础上进行开发,软件开发成果在形态上能够大部分地还原,本次的开发中是以开发便利为导向,所以在具体一些细节效果方面也是以开发能实现的边界为主,因为这些设计细节并不构成核心故而可以适当调整和舍弃。相反,一些游戏规则、效果的实现,基本上是要靠软件来开发实现,基于我们之前沟通过程中对游戏目标的理解进行具体游戏过程实现的开发(尤其是游戏AI算法部分,原型基本无法代替;我们有共识理解的部分直接进行了语言沟通,没有形成文字说明在原型文件中)。

欧阳欣泽:根据志鹏提供的原型设计基础上进行代码的开发,在大体上可以较好的还原原型设计的作品,但在游戏内存控制上则有些差强人意,由于游戏的规则是相对比较简单的最初考虑的内存也应该要比较小,但后面对于各种鼠标监听,动态切换等功能实现内存在不知不觉中超出了自己的规划,且在ai算法的设计中原打算利用递归树的方法创建出完整的棋盘各个情况,但当时也忽略了创建出递归树的内存需要导致无法实现,故只对每一步递归前进若干步来实现ai算法。以及由于本地项目编写的缘故游戏服务器需要自己开发来实现在线对战,由于其代码的复杂性还是需要一定的时间来实现,时间不足也只能暂时放弃。其余的由于在整个设计过程中志鹏的原型设计还是比较完善的,所以除了前面所述困难在代码开发时实现原型设计也没遇到太大的困难。可以说此次设计相对来说实现还是比较理想的。

4.4 评价你的队友(2分)

朱志鹏:在项目过程中,欧阳还是比较给力的,对于项目的实现上能够立马有一个初步的实现想法,因此在项目的整体沟通上更加有效率。在开发方面,欧阳的编程能力是需要我进一步向他学习的。需要改进的方面,一些细节还可以继续优化,在电脑AI的实现上基本上欧阳原本的想法把所有可能情况去进行遍历(把计算机压榨到“极致”的想法虽然也很刺激好玩,但我会更考虑实现性和可玩性)。后面在AI实现按最早的想法算法很冗长,最后退而求其次选择了计算两步的方式简单实现AI功能,在算法的策略方面有机会的话可以进一步沟通研究。

**欧阳欣泽:志鹏在原型设计方面是值得我学习的,无论是在其美观还是完善性上,也由于志鹏的鼎力相助在原型基础上开发设计也比较顺利,整个项目的推进也能循序进行。需要改进的方面则是可能是整个项目的过程中一些细节方面需要改进,如原型设计中可能可以增加更多的动画来增加游戏的趣味性等。

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

朱志鹏:本次的作业从游戏整体功能的实现上来说,还比较好理解并进行设计。但是在具体开发过程中,涉及到游戏AI算法方面,想要设计的能够令游戏足够智能和有可玩性,那还需要花比较多的精力去研究玩法规则并涉及游戏算法。我在这次的作业中主要负责的还是原型这块相关的比较多,在开发过程中也需要跟队友多加交流,互相了解进度情况,以及同步遇到的问题或新的需求,如果可以则提供一定的帮助,尽可能满足需求或者给出相应的需求建议反馈,以便项目开发的继续推进进行。尤其是这一次的结对编程,引入了原型涉及和敏捷开发的概念,比较粗浅的体会到一些关于这种流程的感受(主要是这个项目在原型设计上没有太复杂,对于开发进度的影响没有很大,要是原型对开发影响较大时,那原型涉及反而也会变得棘手起来),感觉得到从开发的流程而言,一个相对成熟完善的开发流程,以及不同部门之间的分工协作,对于一个项目的完成也至关重要,尤其是今后走上工作岗位,许多开发工作都离不开与他人协作,那如何进行分工、划分开发模块,依照相对科学的工程流程进行项目开发,对于我们具体项目开发能力的成长会有所帮助。

欧阳欣泽:本次作业中在已有原型基础上进行代码的开发设计,整个过程还是比较享受的,在整个项目代码设计中也更会去考虑代码的可维护性来进行设计,将代码的耦合度尽量降低从方便以后的整改。同时也学习的QT的前端绘制,学习了其主要使用的API。在代码的锻炼上还是得到了不小的提升的。同时在开发过程中也有遇到难题,印象最深的还是ai算法的实现,本想采用递归整个棋盘树的情况然后ai直接进行遍历计算得到最大胜利概率来实现,无疑此种方法其决策是比较优良的,但决策速度以及硬件资源则很不理想。所以采用有限递归的方法来替代,同时也学习到了代码设计的过程中总是有舍有取的,难以两全,所以需要综合自己的需要选择一个最适合开发需求的区间来进行开发。同时经过此次团队协作也体会到了协作的重要性,团队往往能发挥出更强大的能量,每个人工作起来也事半功倍,总的来说经过此次的作业我受益良多,相信对于往后踏上工作岗位也会很有益处。

...全文
189 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复
【采用BPSK或GMSK的Turbo码】MSK、GMSK调制二比特差分解调、turbo+BPSK、turbo+GMSK研究(Matlab代码实现)【采用BPSK或GMSK的Turbo码】MSK、GMS内容概要:本文主要介绍了采用BPSK或GMSK调制方式的Turbo码相关技术研究,重点涵盖GMSK调制下的二比特差分解调方法、Turbo码与BPSK/GMSK调制相结合的系统性能分析,并提供了完整的Matlab代码实现方案。研究内容包括调制解调原理、编码结构设计、误码率仿真及系统优化等关键环节,旨在通过仿真手段验证所提出方案的有效性和可靠性,帮助研究人员深入理解现代数字通信系统中的关键技术和其实现方法。; 适合人群:具备一定通信原理和Matlab编程基础,从事无线通信、信号处理、编码理论等相关领域的研究生、科研人员及工程技术人员。; 使用场景及目标:①掌握GMSK调制与Turbo码结合的系统设计与仿真方法;②学习二比特差分解调算法在实际通信系统中的应用;③通过Matlab代码实现提升对数字调制解调和信道编码技术的理解与实践能力;④为相关课题研究、毕业设计或工程项目提供参考和技术支持。; 阅读建议:建议读者结合文中提供的Matlab代码逐模块运行与调试,对照通信系统基本原理深入理解各环节功能,重点关注调制解调过程与Turbo译码的协同工作机制,并尝试修改参数以观察系统性能变化,从而达到理论与实践相结合的学习效果。
代码转载自:https://pan.quark.cn/s/a4b39357ea24 LA 1010 逻辑分析仪被视作一种效能卓越的数字信号分析设备,其核心功能在于对数字通信协议,例如I²C,进行检测与解构。本资源将集中阐述LA 1010的操作流程以及如何借助该设备对I²C协议的波形展开分析。 确保逻辑分析仪被正确地连接至目标系统是极为关键的环节。在运用LA 1010的过程中,必须将分析仪的通道0与通道1分别对应连接至目标装置的SCL(时钟)与SDA(数据)线路。务必保证连接的稳固性且无任何干扰因素,以此确保数据采集的精确度。 随后,需要设定采样参数。采样频率对于能否成功捕捉到信号具有决定性的作用。针对I²C协议,通常选用的采样频率范围介于100kHz到400kHz之间,这一范围的选择取决于实际应用场景中I²C总线的运行速度。然而,LA 1010所能达到的最高采样速率可能高达500MHz,因此需要根据具体需求进行相应的调整。此外,还必须精心挑选适配目标设备工作电压的电压等级,例如3.3V、5V或1.8V。 在软件操作层面,需要选取恰当的通道与协议种类,即I²C。一旦启动采样,逻辑分析仪便开始记录相关数据。软件界面通常会实时展示波形图,为观察与分析提供便利。 关于I²C协议波形的解读,我们可以遵循以下步骤: 1. 总线处于空闲状态时:SCL与SDA均维持在高电平位置,这表明总线当前未进行数据传输。 2. 传输起始信号:当SCL处于高电平期间,SDA线从高电平转换至低电平,此动作标志着数据传输的开始。 3. 地址、数据及应答的识别:在每一个SCL高电平脉冲的持续时间内,SDA线上的电平状态代表了数据位。地址与数据的传输均为双向过程,而读写标识则由SDA线上的电平来...
下载代码方式:https://pan.quark.cn/s/a4b39357ea24 在当前文档中,我们将详细研究在C#开发平台中借助BouncyCastle.Crypto库1.8.10版本达成中国的国家标准密码学方案,涵盖SM2、SM3以及SM4这几项技术。这些密码学方案在中国网络安全保障与数据维护领域具有核心地位,为本地化安全解决方案提供了坚实的技术支撑。 让我们首先掌握这三个国家密码算法的基本原理: 1. **SM2算法**:SM2是一种基于椭圆曲线密码体系(ECC)的公钥加密方案,主要用于数字签名和加密操作。它提供了一种高效且安全的身份确认和数据防护机制。 2. **SM3算法**:SM3是一种密码学哈希函数,与SHA-256类似,能够将任意长度的输入信息压缩为固定长度的摘要,常用于数据完整性的检验和确认。 3. **SM4算法**:SM4是一种分组密码方案,采用128位的分组大小和128位的密钥,适用于对称加密,广泛用于无线网络传输和存储数据的加密处理。 接下来,我们将逐步解析如何运用BouncyCastle.Crypto库在C#环境下实现这些密码学方案: **1. 引入库与配置开发环境** 在C#应用程序中,需要通过NuGet包管理工具或手动方式添加BouncyCastle库的引用。务必确保安装的是1.8.10版本。 ```csharp using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Security; ``` **2. 实施SM2的加签与解签** SM2的签名过程和验证操作涉及椭圆曲线运算。必须创建一个私...
源码下载地址: https://pan.quark.cn/s/28d95df2f2ec 在数字化时代的进程中,微信小程序凭借其便捷性、无需下载安装的优势,成为了移动互联网应用的热门选择。本篇将详细剖析“猫眼微信小程序源码”,展示其内部开发技术和设计思想,为计划从事微信小程序开发的人员提供重要的学习素材。猫眼微信小程序是一款融合了电影票务购买、影片资讯检索、影评交流等功能的娱乐软件,其源代码具有显著的学习意义。我们必须掌握微信小程序的基本构成。微信小程序由JSON配置文档、WXML结构文档、WXSS样式文档和JavaScript逻辑文档四个部分构成,这些部分共同创建了小程序的运行条件。 1. JSON配置文档:这是小程序的整体设置,包括小程序的基本要素,例如AppID、页面路由、网络请求地址等。猫眼小程序的JSON配置文档或许包含了特定的功能配置,例如个性化主题色调、导航栏设计等,以达成其独特的视觉呈现。 2. WXML(WeiXin Markup Language):这是微信小程序的结构性语言,类似于HTML,用于构建页面的结构和布局。猫眼小程序的WXML文档中,可能包含了丰富的组件,如button(按钮)、view(视图容器)、image(图片)等,通过这些组件来设计出用户交互界面。 3. WXSS(WeiXin Style Sheet):这是微信小程序的样式定义语言,基于CSS,但包含一些扩展功能。猫眼小程序的WXSS文档中,可能会采用多种布局技术(如Flex布局)以及样式动画,以完成精细的UI设计和平滑的用户体验。 4. JavaScript逻辑文档:这是小程序的关键部分,负责处理业务流程和数据管理。猫眼小程序的JavaScript文档中,可能包含了接口调...

137

社区成员

发帖
与我相关
我的任务
社区描述
2022福州大学软件工程K班
软件工程 高校 福建省·福州市
社区管理员
  • kevinkex
  • Forest_Onee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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