python八皇后

1.计算冲突
之前有疑惑的地方:
state是一个元组,储存每一行的皇后的列索引
计算下一个皇后和当前的皇后是否冲突,在同一列上,列差为0,在斜杠上列差的绝对值等于下一行减去当前行,如果满足这两点则返回true,否则返回false

def conflict(state, nextColumn):
    nextRow = rows = len(state)  
    for row in range(rows): 
        column = state[row]
        if abs(column - nextColumn) in (0, nextRow - row):
            """
                如果差值等于0,两个皇后在同一列, 则代表冲突, 返回True;
                如果列的差值等与行的差, 两个皇后在对角线上, 则代表冲突, 返回True;
            """
            return True
    return False

2.生成皇后的位置,这里传入两个参数,一个是空的皇后的列索引,还有就是皇后的数量
循环皇后在列上的位置,0-7,
通过传入state(即皇后的列索引/位置)和当前皇后的pos即位置,去计算是否冲突,如果不冲突则进入下一步,
判断是否是最后一个皇后即len(state)==num-1(是否已经有7个列索引了),如果是最后一个皇后,因为已经判断过冲突了,所以剩下的就是结果了,这个语句也是递归的出口
如果不是最后一个皇后,则进入else,第一层的queens已经生成了一个皇后的位置,则这时候传入新的state和num去调用queens,知道调用到最后一个皇后,就会触发递归的回操作,最后再pos+result就是全部皇后的列索引/位置

def queens(num, state=()):
    """
    采用生成器的方式来产生每一个皇后的位置,并用递归来实现下一个皇后的位置。
    num: 皇后的数量
    state: 标记已经排好的每个皇后的位置
    """
    for pos in range(num):  # 八皇后的数量N=0, 1, 2, 3, 4, 5, 6 , 7 你要在哪一列放置皇后
        # 如果不冲突,则递归构造棋盘。
        if not conflict(state, pos):  # 回溯法的体现
            # 如果棋盘状态state已经等于num-1,即到达倒数第二行,而这时最后一行皇后又没冲突,直接yield,打出其位置(pos, )
            if len(state) == num - 1:  # state=()
                yield (pos,)
            else:  # (0, )
                for result in queens(num, state + (pos,)):
                    yield (pos,) + result

3.打印皇后
def prettyprint(solution):
“”"
友好展示: 为了直观表现棋盘,用X表示每个皇后的位置
“”"

def line(pos, length=len(solution)): 
    return ' . ' * (pos) + ' x ' + ' . ' * (length - pos - 1)

for pos in solution:
    print(line(pos))

4.测试

if __name__ == '__main__':
    solutions = queens(8)
    for index, solution in enumerate(solutions):
        print("第%d种解决方案:" % (index + 1), solution)
        prettyprint(solution)
        print('*' * 100)

完整代码

#计算冲突,计算当前皇后之前的每一个皇后的列索引是否冲突,即是否在一列上或者一个斜线上
def conflict(state,nextcolumn):
    nextrow=rows=len(state)
    for row in range(rows):   #遍历每一个皇后
        column=state[row]   #获得每一个皇后的列索引
        if abs(nextcolumn-column) in (0,nextrow-row):  #计算是否冲突
            return True
    return False

#生成皇后
def queens(num,state=()):   #state是用来存放所有皇后的列索引的即位置
    for pos in range(num):   #pos是皇后的每个列索引位置
        if not conflict(state,pos):    #计算这个皇后的位置跟之前的皇后的位置是否冲突
            if len(state)==num-1:   # 如果state的长度等于num-1,说明已经有num-1个皇后的位置了,
                                    # 现在已经在生成最后一个皇后的位置了,并且这个位置跟之前皇后的位置还不冲突,
                                    # 可以直接生成这个pos即最后一个皇后的列索引/位置
                yield (pos,)  #这个分支是递归出口
            else:               #如果不是最后一个皇后则运行else分支
                for result in queens(num,state+(pos,)):  #因为已经经过了冲突计算,说明这个皇后的列索引与之前的皇后的列索引不冲突,
                                                        # 添加到state里,再传递更新后的state去遍历下一个皇后
                    yield (pos,)+result

#绘制棋盘
def prettyprint(solution):
    def line(pos,length=len(solution)):
        return '.'*pos+'X'+'.'*(length-pos-1)
    for pos in solution:
        print(line(pos))

#测试
if __name__=='__main__':
    solutions=queens(4)
    for index,solution in enumerate(solutions):
        print('第%d种解法:'%(index+1),solution)
        prettyprint(solution)
        print('*'*100)

在这里插入图片描述

把所有步骤都用类封装起来,这样调用的时候就更加简便了

#封装类的方法解决八皇后的问题
class Solution:
    def solve(self,num):
        self.state=()
        for  solution in self.queen(self.state,num):
            self.printqueen(solution,num)
    def conflict(self,state,nextcolumn):   #冲突计算
        rows=nextrows=len(state)
        for row in range(rows):
            column=state[row]
            if abs(column-nextcolumn) in (0,nextrows-row):
                return True
        return False
    def queen(self,state,num):   #生产皇后
        for pos in range(num):  #该皇后的列索引
            if not self.conflict(state,pos):
                if  len(state)==num-1:
                   yield (pos,)
                else:
                    for result in  self.queen(state+(pos,),num):
                        yield (pos,)+result
    def printqueen(self,solution,num):   #打印棋盘
        print(solution)
        for row in  range(num):
            line=""
            for column in range(num):
                if solution[row]==column:
                    line+="Q\t"
                else:
                    line+="*\t"
            print(line,"\n")
        print("\n")
    print("*"*100)

s=Solution()
solutions=s.solve(4)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值