结对编程作业

一、链接
github博客链接:https://github.com/031804120/huarongdao
队友博客链接:https://www.cnblogs.com/sunqingqing/p/13799014.html
队友孙晴晴的github链接:https://github.com/031804126/pairWork
游戏部分为Java语言,AI大比拼代码重点内容为python。
具体分工:
结对编程作业

  • 二、原型设计
    (1)设计说明:
    1、HTML界面主要分为两部分,游戏菜单部分和游戏活动区域。
    2、整个html文件采用flex布局,所以css文件里需要使用flex布局实现html文件的界面需求;总体布局采用列方向排列子元素;然后每一列中采用行方向排列子元素。
    结对编程作业

3、进行游戏的区域中内容通过JS动态生成
所以生成的界面是这样的。
结对编程作业

在这个界面内,实现的功能有:
关于更换游戏图片的实现
因为要动态更换图片,所以我们需要一个全局变量来记录我们当前用到的图片,在js中我们用到了image对象以及imagePath这两个变量。image对象在动态计算小方格的宽度和高度时需要用到;而imagePath则是为了在更换图片事件发生时,重新修改image对象的属性;具体功能由onChooseImage()函数实现;
关于难度选择的实现
通过image的宽度和高度除以难度值来计算每一个小方格的宽度和高度,并计算填充小方块时图片的偏移量;具体功能由onChooseDifficulty()来实现;
关于记录操作次数的实现
我们都需要交换两个小方块的数据(即背景图像的位置信息),所以只需要在这个函数里更新一个score全局变量即可;这个函数是doExchange(item);即将item的相关内容同emptyBlock(空方块)交换;
关于提示功能:
在getOpeningPosition()函数里模拟用户操作交换小方块时,如果空块向左移动,那么我们就将一个使空块向右移动的函数emptyMoveRIght对象压入操作栈,即把用户操作的反动作压入操作栈;当用户产生操作时,我们就接着把对应的反动作压入操作栈。当用户点击提示时,我们从操作栈弹出一个函数对象并执行,当栈空时,自然游戏场景被还原,即游戏结束。
数据存储
每一个position对象有x属性和y属性;然后将该对象转换为字符串后存到div的dataset中。当触发事件是就可以获得div的imagePosition和physicalPosition。

(2)原型设计工具:
JavaScript。Prototype。

(3)讨论照片
结对编程作业

(4)遇到的困难与解决方法
1、困难描述:HTML浏览器打开的时候,碰到了不稳定的情况,如以下。
结对编程作业
2、解决尝试:
查询了B站,百度,知乎等相关APP极其网站上的相关知识文章。
3、是否解决:不是非常的确定。
4、有何收获:
通过这一次的学习和查询资料,我更加的理解了js的使用,以及在网页脚本之类的内容有了亲身实践过后的理解。

  • 三、AI与原型设计实现
    (1)、代码实现思路:
    1、网络接口的使用:
    一开始的接口用的是:
url = "http://47.102.118.1:8089/api/problem?stuid=031804120"
# 发送get请求
r=requests.get(url)
user_dic = json.loads(r.text)
# swap=user_dic['step']
# uuid=user_dic['uuid']
data = user_dic['img']
image_data = base64.b64decode(data)
np_img=imageio.imread(image_data)
plt.imshow(np_img)
plt.show()

后面发现还不如用postman。
结对编程作业

2、代码组织与内部实现设计(类图):
结对编程作业

3、说明算法的关键与关键实现部分流程图:
AI大比拼的算法:主要还是广度优先搜索,A*那里只是大约是排序,把那些最有可能得到解的结果先搜索。
结对编程作业
游戏设计的时候:我觉得在进行图片排列的这一步挺重要的。
结对编程作业

4、贴出你认为重要的/有价值的代码片段,并解释:
AI中:

  def cal_distance(idxs):
            distance = 0
            for i in range(len(idxs)):
                if idxs[i] == 0:
                    continue
                distance += abs(i // width - (idxs[i] - 1) // width) + 
                            abs(i % width - (idxs[i] - 1) % width)
            return distance

        # 优先队列,值越小,优先级越高
        pq = PriorityQueue()
        # [优先级, 中间List(3*3=9), 初始值的0索引, 步数, 按键顺序输出序列, 拼图中间转换过程]
        pq.put([0 + cal_distance(board_start), board_start, board_start.index(0), 0, "", []])
        # 已遍历过的序列
        visited = set(board_start)
        # BFS搜索
        while not pq.empty():
            # 获取中间值
            _, board, position, step, move_str, board_roads = pq.get()
            # 最终结果返回, 循环停止条件
            if board == board_end:
                return step, move_str, board_roads
            # BFS遍历上下左右的相邻结点
            for idx in (-width, width, -1, 1):
                # wsad字母 对应 上下左右 的按钮
                id2button = {-1: "a", 1: "d", - "w",  "s"}
                # 下一个需要遍历的点
                neighbor = position + idx
                # 不是相邻点的跳过
                if abs(neighbor // width - position // width) + abs(neighbor % width - position % width) != 1:
                    continue
                # 遍历上下左右符合边界条件的相邻数字(图片)
                if 0 <= neighbor < width * hight:
                    board_mid = list(board)
                    # 交换, 即移动0(即空图片)
                    board_mid[position], board_mid[neighbor] = board_mid[neighbor], board_mid[position]
                    board_new = tuple(board_mid)
                    if board_new not in visited:
                        visited.add(board_new)
                        pq.put([cal_distance(board_new) + step + 1, board_new, neighbor, step + 1,
                                move_str + id2button[idx], board_roads + [board_mid]])

这个地方主要就是为了找出好的路劲来。
游戏:

class ImgButtonAction implements ActionListener {
        public void actionPerformed(ActionEvent e) {
//			System.out.println(444);
            nums++;
//			System.out.println(nums);
            if (nums > 20) {
                JButton clickButton = (JButton) e.getSource();
                JPanel panel = (JPanel) clickButton.getParent();
                JButton one;
                while ((one = (JButton) panel.getComponent((int) (Math.random() * panel.getComponentCount()))) == emptyButton) {
                }
                JButton two;
                while ((two = (JButton) panel.getComponent((int) (Math.random() * panel.getComponentCount()))) == emptyButton || two == one) {
                }
                Icon icon=one.getIcon();
                one.setIcon(two.getIcon());
                two.setIcon(icon);
                nums=0;
            } else {
                String emptyName = emptyButton.getName();
                char emptyRow = emptyName.charAt(0);
//			System.out.println(emptyRow);
                if (emptyRow == '1') {
                    System.out.println("s");
                } else {
                    System.out.println("w");
                }

                char emptyCol = emptyName.charAt(1);
//			System.out.println(emptyCol);
                JButton clickButton = (JButton) e.getSource();
                String clickName = clickButton.getName();
                char clickRow = clickName.charAt(0);
                if (emptyRow == '1') {
                    System.out.println("a");
                } else {
                    System.out.println("d");
                }
//			System.out.println(clickRow);
                char clickCol = clickName.charAt(1);
//			System.out.println(clickCol);
                if (Math.abs(clickRow - emptyRow) + Math.abs(clickCol - emptyCol) == 1) {
                    emptyButton.setIcon(clickButton.getIcon());
                    clickButton.setIcon(new ImageIcon("image/" + num + "00.jpg"));
                    emptyButton = clickButton;
                }
            }
        }
    }

游戏过程中的移动以及强制调换图片。

5、性能分析与改进:
刚开始的时候还是存在着一些局限性,专一的用着一种方法,存在着一些比较浪费时间的没必要步骤。
6、描述你改进的思路:
改进的时候,就是将A*和广度以及深度优先搜索之类的,都尝试一下,然后再试着能不能结合改进。
7、展示性能分析图和程序中消耗最大的函数:
AI算法:
结对编程作业
结对编程作业
游戏程序:
结对编程作业

8、展示出项目部分单元测试代码,并说明测试的函数,构造测试数据的思路 :
部分代码:
结对编程作业
单元测试coverage:
结对编程作业
测试的函数的思路:就是在单元测试建立新的测试数据,然后通过调用同文件夹下的相关函数。
构造测试数据的思路:为了尽量保证有解,参考了逆序数的思想打乱。

(2)贴出Github的代码签入记录,合理记录commit信息:

结对编程作业

(3)遇到的代码模块异常或结对困难及解决方法:
1、问题描述:
分着写部分代码的时候,一开始没有统一商量好,导致再整合代码后,出现了一些函数调用问题。还有一些思路上的小分歧。
2、解决尝试:
再次商量确定了负责部分的内容的代码写的规范。
3、是否解决:
解决了。
4、有何收获:
交谈非常重要,尤其是开始一项合作项目之前的商量!而且交流思路的时候要越详细越好,因为很容易出岔子,或者理解错误,毕竟每个人的思路都不一样的。

(4)评价你的队友:
1、值得学习的地方:
比我有耐心,有时候敲代码敲到烦的时候,感谢她的鼓励。
2、需要改进的地方:
没有,因为一样的缺点,菜是原罪。

PSP:
结对编程作业
学习进度条:
结对编程作业