结对编程作业

结对编程作业


1.1 博客及项目链接;分工

组员 主要任务
谢鑫杰 算法及其代码编写以及相关部分博客
魏祖文 对算法一窍不通,UI、原型制作及其他部分博客等

队伍id:16

作者博客:https://www.cnblogs.com/xie37/p/13843644.html

队友博客:https://www.cnblogs.com/magnetic/p/13843580.html

项目地址:https://github.com/magnetic233/team16-031802431

2.1 - 原型设计

[2.1.1]本次结对作业参考部分小游戏的界面,字体通过艺术字改造,做了个金玉其外败絮其内的封面

[2.1.2]原型模型采用Axure Rp设计 已经上传HTML原型

[2.1.3]结队过程:
舍友结队

[2.1.4]遇到的困难及解决方法:(4分)

到处都是知识盲区,依托CSDN,百度,菜鸟教程等一切对此次作业有帮助的网站以及寻求身边的大佬和工具人们的帮助

2.2 - AI与原型设计实现(20分)

[2.2.1]代码实现思路: (10分)

数字华容道的本质是八数码问题,这里使用A*

	A*(A-Star)算法是一种静态路网中求解最短路径最有效的直接搜索方法,也是许多其他问题的常用启发式算法。
注意——是最有效的直接搜索算法,之后涌现了很多预处理算法(如ALT,CH,HL等等),在线查询效率是A*算法的数千甚至上万倍。
公式表示为: f(n)=g(n)+h(n),
	其中, f(n) 是从初始状态经由状态n到目标状态的代价估计,
	g(n) 是在状态空间中从初始状态到状态n的实际代价,
	h(n) 是从状态n到目标状态的最佳路径的估计代价。
	(对于路径搜索问题,状态就是图中的节点,代价就是距离)
h(n)的选取
	保证找到最短路径(最优解的)条件,关键在于估价函数f(n)的选取(或者说h(n)的选取)。
我们以d(n)表达状态n到目标状态的距离,那么h(n)的选取大致有如下三种情况:
1.如果h(n)< d(n)到目标状态的实际距离,这种情况下,搜索的点数多,搜索范围大,效率低。但能得到最优解。
2.如果h(n)=d(n),即距离估计h(n)等于最短距离,那么搜索将严格沿着最短路径进行, 此时的搜索效率是最高的。
3.如果 h(n)>d(n),搜索的点数少,搜索范围小,效率高,但不能保证得到最优解。

关键代码

class State:
    # h(n) 将付出的代价
    h = lambda self: 0

    def __init__(self, digits, depth, pa):
        # 数位
        self.digits = digits
        # 父状态
        self.pa = pa
        # 深度 g(n)已付出的代价
        self.depth = depth
        # 估价函数
        self.f = self.__f()

    # 交换zero位和next位的数
    def get_digits(self, zero, next):
        digits = list(self.digits)
        digits[zero] = digits[next]
        digits[next] = 0
        return digits

    # 获取可移动的下一个digits
    def next_digits(self):
        zero = [i for i, v in enumerate(self.digits) if v == 0][0]
        if int(zero / 3) != 0:
            yield self.get_digits(zero, zero-3)
            # w
        if int(zero / 3) != 2:
            yield self.get_digits(zero, zero+3)
            # s
        if zero % 3 != 0:
            yield self.get_digits(zero, zero-1)
            # a
        if zero % 3 != 2:
            yield self.get_digits(zero, zero+1)
            # d

    # 获取下一个可转换状态(父状态不在内)
    def next_state(self):
        for d in self.next_digits():
            if not self.pa or d != self.pa.digits:
                yield State(d, self.depth + 1, self)

    # 计算估价函数f(n) = g(n) + h(n)
    def __f(self):
        return self.depth + State.h(self) * 2

    # 更换h(x)
    @staticmethod
    def change_h(h):
        State.h = h
        pass

    def __eq__(self, other):
        return self.digits == other.digits

    def __str__(self):
        res = 'depth = %d, f(x) = %d\n' % (self.depth, self.f)
        for i in range(3):
            res += str(self.digits[i*3: (i+1)*3]) + '\n'
        return res

class EightDigits:
    global ss
    def __init__(self, s ):
        # 初始状态
        self.s = State(s, 0, None)
        # 目标状态
        self.e = ss
        self.open = []
        self.close = []
        self.open.append(self.s)

    # 判断奇偶排列
    def isOdd(self, digits):
        num = 0
        for i in range(9):
            if digits[i] == 0:
                continue
            for j in range(i + 1, 9):
                if digits[j] == 0:
                    continue
                if digits[i] > digits[j]:
                    num += 1
        return num % 2 == 1

    # A*算法
    def A(self):
    	# 判断可不可解
        if self.isOdd(self.s.digits) != self.isOdd(self.e):
            return None
        num = 0
        while self.open:
            front = min(self.open, key=lambda x: x.f)
            self.open.remove(front)
            num += 1
            #print(front)
            if front.digits == self.e:
            	# 搜索次数
                #print("-" * 10 + str(num) + "-" * 10 + '\n')
                return front
            self.close.append(front)
            for next in front.next_state():
                if next in self.open:
                    for i, o in enumerate(self.open):
                        if next == o:
                            if next.f < o.f:
                                self.open[i] = next
                        break
                elif next in self.close:
                    for c in self.close:
                        if next == c:
                            if next.f < c.f:
                                self.close.remove(c)
                                self.open.append(next)
                        break
                else:
                    self.open.append(next)
        return None
    
    @staticmethod
    def show(state):
        global list0
        if state.pa:
            EightDigits.show(state.pa)
        #print(state)
        list0.append(state)
        

# h函数1 代价为所有数恢复原有状态所移动距离的代价总和
def p(s):
    e = ss
    digits = s.digits
    res = 0
    for i in range(9):
        for j, v in enumerate(digits):
            if v == e[i]:
                t = abs(i - j)
                res += int(t / 3) + t % 3
                break
    return res


# h函数2 代价为不在正确位置的数的数量
def w(s):
    e = ss
    digits = s.digits
    return len([i for i in range(9) if e[i] != digits[i]])

[2.2.3]遇到的代码模块异常或结对困难及解决方法。(4分)

​ python的换行缩进以及格式控制需要极大的注意,互相调用的时候要注意参数

[2.2.4]评价你的队友。(2分)

  • 值得学习的地方

    很有耐心

  • 需要改进的地方

    思想江化

[2.2.5]提供此次结对作业的PSP和学习进度条(每周追加),示例如下(2分)

时间 本周代码(行) 累计的代码(行) 本周学习时间(小时) 累计学习时间(小时) 重要成长
1 35 35 1 1 方法
2 270 305 4 5 初代图形界面
3 439 744 8 13 各种debug
4 620 1364 7 20 代码整合

3.1 - 原型设计实现

原型设计实现本地版:从1-35字符中随机生成棋盘允许用户进行游玩

开始界面:

游戏界面:

还原与打乱:

**还原:可以还原到原图状态 **

打乱:如果嫌不够乱或者无从下手可以多打乱几次

放弃思考=放弃思考

(听说有人解不出,没错就是我)

一个简单的游戏说明:

posted @ 2020-10-19 22:45  XC9  阅读(117)  评论(0编辑  收藏  举报