结对编程作业

https://github.com/wl1055834702/031902122

姓名 分工 博客连接
伍浪 原型实现,部分逻辑功能,修改bug整合代码,AI算法编写 https://www.cnblogs.com/wulang1055/p/15456146.html
叶绍文 收集素材,部分逻辑功能,在线对战实现,界面实现 https://www.cnblogs.com/ysw12345/p/15456059.html

一、原型设计

1.*作品链接

https://modao.cc/app/97bda771cab49febd312a110015cc9275eff3ae5#screen=skv53qkciztql9h

2.*原型开发工具

​ 本次结对编程作业采用原型设计工具墨刀,并使用美图秀秀对图片进行美化

3.*原型界面及说明

  • 初始界面:初始页面设有三个按钮,分别为介绍规则按钮,开始游戏按钮,以及加入我们按钮(点击即可计入猪尾巴内部交流群!)

    在初始界面不设有登录界面,放在模式选择中的在线对战中。点击开始游戏即可进入模式选择。

    介绍规则界面,由作业中截取出的。并设有返回游戏即下一页按钮。

  • 模式选择界面:即选择需要进入的游戏模式

  • 人机对战页面:人机对战模式即玩家同''阿尔发''机器人进行对战。牌堆为堆叠的形状,放置区开始为空。在此页面设置了翻牌与吃牌的功能(由于为动态功能演示,具体可以前往作品链接体验)。玩家可以自主出牌,也可以选择进入托管模式,并可取消托管。点击牌堆即可翻牌,翻牌时或出牌时遇到花色一样即吃牌。在游戏结束之将会弹窗显示玩家胜利或机器人胜利。

  • 双人对战页面:与人机对战基本一致,头像更换为人物,此页面同样实现吃牌翻牌动态演示(具体在作品中演示),玩家1和2同时可以进行托管。

  • 在线对战:在线对战的两个玩家在不同的设备上进行对战,玩家可以自己创建房间获得房间号uuid,或者获得uuid加入他人创建的房间。选择模式中有四个按钮进行选择,分别为创建房间,加入房间,创建AI对局和加入AI对局。点击创建房间后或创建AI对局后,出现等待玩家二加入的页面;点击加入房间或加入AI对局,弹出输入房间号的页面。






4.*困难及解决办法

  • 困难:由于对原型设计软件不够了解,开始的时候使用Axure Rp,但是使用起来困难层出不穷,耗费了一些精力。后来转为使用墨刀,但对原型软件还是不够了解,界面设计没有灵感,设计起来存在一些困难,只能一边操作一边摸索。还有如何制作动态页面展现出所需操作,如何才能实现交互友好也成为一大困难。

  • 解决方法:经过查找在网上有一些墨刀基本操作的教学视频,并且在一次次尝试和修改之后,墨刀的基本功能已经可以操作较为流畅了。由于没有设计的灵感,参考了网络上一些小游戏的设计原型,并且收集了特别多的素材,从中慢慢构建出我们所要设计的页面,中间走了一些弯路,但最后还是按照我们的想法实现了作品。

5.*收获

​ 第一次设计原型,中间虽然困难较多,但得到作品后还是成就慢慢。从中掌握了设计原型的一些基础操作,以后再次需要制作原型一定会有所进步。

二、原型设计实现

一、*代码实现思路:

  1. *网络接口的使用:创建使用网络接口类,使用python中的requests类,以及postman工具,接收接口返回的字典,获取字符串其中信息进行处理。
    • login(str,str):用来传入输入的学号与密码,错误时返回error,输入正确时返回接口生成的 token值,完成登录功能。
    • creategame(token):用来传入创建的token值,返回创建的房间号uuid
    • joingame:(token,uuid):用来传入生成的token值和uuid,完成加入房间(可以加入自己创建的房间)
    • get_operation(token,uuid):用来传入生成的token和uuid,返回接口的字符串,用于进一步实现功能。
    • openpoker(token,uuid,str):用来传入生成的token和uuid,以及翻牌标识符,实现玩家翻牌功能。
    • setpoker(token,uuid,str):用来传入生成的token和uuid,以及出牌标识符,实现玩家出牌功能。
  2. *代码组织与内部实现设计:

  1. *算法的关键与关键实现部分的流程图:

    • 算法的关键:比较关键的一个逻辑点是回合的改变对各种操作及显示的影响,用turn表示谁的回合,然后结合模式及其托管状态决定操作。还有一个比较关键的点是托管或人机状态下关于出牌操作及界面的显示(两次刷新表示机器或托管状态)。

  2. *最重要的代码片段:用这个函数判定ai是否出牌(上面第二张流程图的功能),如果可以用self.lnewcard暂时保存将要出的牌,再一次更新屏幕后将值赋予self.newcard(放置区首张牌),并进行相应的操作并再次更新屏幕。

    def trusteeship(self, lst):         # 判断自动模式下应该打出的那张牌或者选择摸牌
        new_card = ''
        max1=''
        dict = {'count_meihua': 0, 'count_fangkuai': 0, 'count_hongtao': 0, 'count_heitao': 0}
        #if len(lst) == 0:
        #    self.reset(lst)
        for item in lst:
            if item[4] == 'u':
                dict['count_meihua'] += 1
            elif item[4] == 'k':
                dict['count_fangkuai'] += 1
            elif item[4] == 't':
                dict['count_hongtao'] += 1
            else:
                dict['count_heitao'] += 1
        for k, v in dict.items():
            if v == max(dict.values()):
                max1 = k
        if turn==1 and (len(player1)+3*len(pai)+len(setpoker)-2)<len(player2):     #自动或机器ai判定,一定情况下抽牌必赢,则有手牌也自动摸牌
            self.tuopai=0
        if turn==-1 and (len(player2)+3*len(pai)+len(setpoker)-2)<len(player1):
            self.tuopai=0
        if len(setpoker)==0:
            for item in lst:
                if max1[10] == item[4]:  # new_card放选中要被打出去的牌
                    new_card = item
                    break
        else:
            if max1[10] == self.newcard[4]:
                del dict[max1]
                if max(dict.values()) == 0:
                    max1 = ''
                else:
                    for k, v in dict.items():
                        if v == max(dict.values()):
                            max1 = k
            if max1 != '':
                for item in lst:
                    if max1[10] == item[4]:  # new_card放选中要被打出去的牌
                        new_card = item
                        break
            else:
                self.tuopai = 0
        self.lnewcard = new_card
    
  3. *性能分析与改进:


    除去系统自带调用的一些操作,可以看出程序调用最为浪费时间的在屏幕更新这一块,实现的代码完成一个操作或一些较少的指定操作之后,就会更新一次屏幕,这样的调用实属浪费。还有使用接口时,获取上一步操作时发送请求过于频繁,造成巨大的资源浪费。

  4. *改进思路:

    • 将屏幕更新语句更改放置的地方,使得在一系列操作都完成之后,再进行屏幕的更新,这样就可减少调用的次数。
    • 设置一个合适的时间间隔,减少请求次数,从而避免每时每刻都在请求返回值,并且尽力做到使屏幕卡顿较短时间。
  5. *性能分析图与程序中消耗最大的函数:

    检测鼠标调用事件,进行判断执行相应操作为此程序消耗最大的函数。

    def mouse(self, xy):                         # 判断鼠标操作,为鼠标坐标
        turnchange = 0
        global turn
        x = xy[0]
        y = xy[1]
        if self.player1auto.collidepoint(xy):     #玩家一托管与取消托管
            if self.istrusteeship1==False:
                self.istrusteeship1 = True
            else:
                self.istrusteeship1 =False
            self.update()
        elif self.player2auto.collidepoint(xy) and self.ifauoto==0:      #双人时玩家二托管与取消托管
            if self.istrusteeship2==False:
                self.istrusteeship2 = True
            else:
                self.istrusteeship2 =False
            self.update()
    
        else:
            if self.area.collidepoint(xy) and len(pai) != 0:              #抽牌
                self.reset(pai)
                self.eatcard(setpoker)
                self.chupai = -1  # 换人把出牌恢复
            if self.fire1area.collidepoint(xy) and self.chupai != -1 and turn == 1:  #玩家一出牌
                if len(player1) != 0:
                    setpoker.append(player1[self.chupai])
                    self.newcard = player1.pop(self.chupai)
                    self.chupai = -1
                    self.eatcard(setpoker)
                    turn=-turn
            if self.fire2area.collidepoint(xy) and self.chupai != -1 and turn == -1:  #电脑或玩家二出牌
                if len(player2) != 0:
                    setpoker.append(player2[self.chupai])
                    self.newcard = player2.pop(self.chupai)
                    self.chupai = -1
                    self.eatcard(setpoker)
                    turn=-turn
            l1 = (1400 - len(player1) * 20 - 85) / 2                                  #轮到玩家一时判断点的第几张牌,突出显示
            if x < len(player1) * 20 + 85 + l1 and 600 < y < 750 and turn == 1 and self.istrusteeship1 ==False:
                if x <= len(player1) * 20 + l1:
                    self.ifchupai = int((x - l1) // 20)
                else:
                    self.ifchupai = len(player1) - 1
                if self.ifchupai == self.chupai:
                    self.chupai = -1
                else:
                    self.chupai = self.ifchupai
            l2 = (1400 - len(player2) * 20 - 85) / 2                                  #轮到玩家二时判断点的第几张牌,突出显示
            if x < len(player2) * 20 + 85 + l2 and 0 < y < 150 and turn == -1 and self.istrusteeship2 == False:
                if x <= len(player2) * 20 + l2:
                    self.ifchupai = int((x - l2) // 20)
                else:
                    self.ifchupai = len(player2) - 1
                if self.ifchupai == self.chupai:
                    self.chupai = -1
                else:
                    self.chupai = self.ifchupai
            self.update()
    
  6. *单元测试

    def reset(self, lst):                           #摸牌操作
        random.shuffle(lst)
        self.newcard = lst[-1]  # 记录放置区最上面的牌
        setpoker.append(lst.pop())  # 将牌堆弹出的牌放入放置区队列,同时记录这张牌
        global turn
        self.eatcard(setpoker)
        turn = -turn # 换玩家出牌
        return len(lst)
    

​ 简单测试翻牌操作,打乱牌堆之后是否成功翻牌,如果调用函数翻牌之后列表函数未减少一个,则说明该函数存在问题。

二、*github的代码迁入记录

三、*遇到的代码模块异常或结对困难及解决方法:

一个小函数,每次游戏结束无论下一步操作都更新所有参数,在写的时候重新开始因为很多参数改变或出现很多bug(多为显示),这里也花了很多时间调试,放到游戏开始或其它地方重新更新都不太好,结束时就调用更新就可以了

四、*评价你的队友:

队友叶绍文:

​ 值得学习的地方:心态好,好商量,该认真的时候还是非常认真、非常努力的,总之相处非常快乐!

​ 需要改进的地方:规划做的不足,也喜欢划水(谁不喜欢呢),不到deadline不肝(hhh我也一样)

队友伍浪:

​ 值得学习的地方:写代码做原型都非常非常的认真,一起学习时非常有活力

​ 需要改进的地方:时间安排不够合理,和我一样一起赶ddl

伍、*提供此次结对作业的PSP和学习进度条:

N周 新增代码(行) 累计代码(行) 本周学习耗时(小时) 累计学习耗时(小时) 重要成长
1 83 83 23 23 了解原型设计和使用墨刀设计出原型
2 149 232 36 59 学习使用pygame基本操作及完善原型
3 237 469 30 89 完成双人对战和人机对战的功能试实现
4 203 672 34 123 学习使用postman和接口完成在线对战功能
PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划
· Estimate · 估计这个任务需要多少时间 30 30
Development 开发
· Analysis · 需求分析 (包括学习新技术) 2000 2500
· Design Spec · 生成设计文档 30 50
· Design Review · 设计复审 30 50
· Coding Standard · 代码规范 (为目前的开发制定合适的规范) 30 40
· Design · 具体设计 500 500
· Coding · 具体编码 2000 2500
· Code Review · 代码复审 100 100
· Test · 测试(自我测试,修改代码,提交修改) 1000 1000
Reporting 报告
· Test Repor · 测试报告 60 60
· Size Measurement · 计算工作量 30 30
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 60 60
· 合计 5870 6920

三、心得

叶绍文:

记得刚看到这次结对编程作业,居然是写一个游戏,我这种小菜鸡属实被惊到了,玩游戏我到是擅长,作为一个作业写游戏到是出乎意料,不过看到完成时间是一个月也就释然了。 要求写游戏前设计游戏原型,什么,游戏原型?我那时候还真不知道游戏原型具体指什么,不过不懂没事,那就学呗。什么,除了实现双人对战 ,还要实现人机对战?人机对战我要咋实现,还真不懂,不过不懂没事,那就学呗。什么,还要实现在线对战?怎么实现,哦哦下面有说用接口。什么,用接口实现?接口又是什么,真滴看不懂,不过不懂真没事,那就学呗。既然我这个作业要求我基本看不懂,那游戏规则我总得看懂吧。什么,我居然看两遍还是不太懂,害没事,学一学呗。

我不知道其他人想法是什么样,反正以上是我一个月前的心里的感受。但想法归想法,还是要好好规划一下内容该怎么完成。一开始的原型设计,我负责收集素材,然后和我的队友一起商讨页面如何布局,动态页面如何实现,他负责进行具体的操作,这时候的工作还算是较为简单惬意。后面到具体代码功能实现的部分。我们决定每个人完成一部分的功能,然后再拼接起来,这样的想法一开始我也没感觉有什么问题,后面两个人的代码放一起总会产生一些无法理解的bug,终究还是花了大量时间debug。后来我的队友负责改一个巨大的bug,并且整合代码,我负责去实现在线对战功能,但由于接口使用不熟练,最后用接口实现功能没有能够完成,这是比较遗憾的,不过基本的功能还是在磕磕碰碰中完成了。

​ 总的来说,这次的作业自我感觉难度还是较大,毕竟什么东西都要现学,但完成这项作业的过程还是非常充实的,从中我也受益匪浅,

收获了很多。最后要感谢一下我的队友,两个人一起完成作业有相互督促的效果,一起完成这项作业的过程也让我感触良多。

伍浪:

​ 这次结对作业总的来说收获还是挺大的吧,刚开始拿到作业的时候一半兴奋,一半懵逼,兴奋是感觉又有新的挑战感觉能学到很多东西,懵逼是我想了想感觉真的啥也不会hhhh,肯定又是全部要现学,有点难搞。

​ Deadline是第一生产力,这是最近一个很深刻的体会,也是教训,如果有下次,我一定!也不知道会不会等到快到deadline再肝hh。这次一个比较大的问题就是咱两前期太佛系了,时间分配不太合理(划水划太久了),由于各种事情,前期我们除了在国庆做了大部分原型外,几乎所有工作都是在deadline前一周开始开展的,其它就零零散散的学了些东西(时间还是付出了,不过态度问题,没啥实质性的进展,就’技术积累’)。然后就是前期规划做的实在不太行,两个人交流也没太到位,没有做好规划导致一些工作开展比较乱,不过后期的时候磨合好多了,一直处于随机应变状态,总的还是挺顺利的,队友有事一起好商量对我来说太重要了,赞一个。

​ 关于收获,又是一波自学,学到就是赚到,不过由于没太搞清楚要求和时间分配问题,没来得及学前端(开始也没太搞懂前端),游戏主要是直接用python的pygame模块写的,前期学的挺乱的,不过不知道是技术积累到位了还是deadline的力量,在截至前一周感觉顿悟了,用的还是挺不错的。在用头发debug的过程中,感觉对于python的使用还是有些长进的。头发和Bug成正比。一点一点学,到后面也看到了一些进步。

​ 不管什么时候,心态要好!在开始一起写并磨合了一下之后,我们总的进展还是比较顺利的,一人写一部分功能,大概每天交流整合下,挺快的。不过在某天队友写ai和托管我写模式选择等时,他那个bug卡了快两天,然后咱两都找不出来问题。最后我接手了这部分功能,叫他去写接口,然后噩梦开始了……感觉自己就是在写bug你知道吗,完全不知道怎么改,然后接下来几天就一直在debug、写bug……人确实快傻了,还有点想摆烂,不过后面慢慢放宽心,一点一点写,最后好歹还是基本完成了,不过到现在我精神还有点不太正常……总之遇到困难不用慌,慌也没用,不如躺着慢慢解决(不是躺平啊喂!)。

​ 最后感谢一下队友,过程很艰难,不过和队友相处和写bug还是挺快乐的。

posted @ 2021-10-24 22:47  浪平  阅读(91)  评论(0编辑  收藏  举报