用Python随机求解棋盘上的皇后

用Python随机求解棋盘上的皇后,python,random,n-queens,Python,Random,N Queens,我们的想法是尝试通过在棋盘的每一行中完全随机地放置皇后来解决皇后问题,并查看需要多少次重复来解决它。棋盘可以是任何大小 我的想法是创建s个列表,每个列表包含s个空字符和下划线。然后,对于每一行,随机选择一个位置来插入皇后I值,然后标记下面的所有位置并沿对角线向下,我将逐行进行,这样我就不必担心上面的行与X。如果在任何迭代中,皇后随机选择的位置与该行中任意X的位置匹配,我从头开始制作新棋盘 我有类似的东西,但它似乎卡在第19行,上面有一条注释,但它没有给我任何错误。有什么不对劲?另外,我的解决方案

我们的想法是尝试通过在棋盘的每一行中完全随机地放置皇后来解决皇后问题,并查看需要多少次重复来解决它。棋盘可以是任何大小

我的想法是创建s个列表,每个列表包含s个空字符和下划线。然后,对于每一行,随机选择一个位置来插入皇后I值,然后标记下面的所有位置并沿对角线向下,我将逐行进行,这样我就不必担心上面的行与X。如果在任何迭代中,皇后随机选择的位置与该行中任意X的位置匹配,我从头开始制作新棋盘

我有类似的东西,但它似乎卡在第19行,上面有一条注释,但它没有给我任何错误。有什么不对劲?另外,我的解决方案是否正确

from random import *


#Success flag
success = 0

#Trials counter
trials = 0


s = input ("enter board size\n")
s = int(s)
block = 1 #blockade
queen = 2 #queen
board = [[0 for x in range(s)] for y in range(s)] 

while success == 0:
    for y in range (0, s-1):
        pos = randint(0,s-1)    #line 19
        if board[y][pos] != block:
            board[y][pos] = queen
            a = 1
            for z in range (y, s-2):
                board[z + 1][pos] = block
                if pos - a >= 0:
                    board[z + 1][pos - a] = block
                if pos + a <= s-1:
                    board[z + 1][pos + a] = block
                a = a + 1
            success = 1
        else:
            success = 0


#Printing board
for y in range (0, s-1):
    print (board[y])

print ("Number of trials:\n")
print (trials)

在您尝试不同的行并且这次失败后,您必须创建一个新的空板,如果成功为0,您应该按照以下方式中断for循环

while success == 0:
    board = [[0 for x in range(s)] for y in range(s)]
    for y in range (0, s):
        pos = randint(0,s-1)    #line 19
        if board[y][pos] != block:
            board[y][pos] = queen
            for i in range(y+1, s):
                board[i][pos] = block
            success = 1
        else:
            success = 0
            break
    trials += 1
您可以按照相同的逻辑来实现对角情况

一些问题:

range函数的第二个参数表示不被访问的第一个数字,因此大多数情况下,您只需短取一个。 您需要在尝试失败时退出y上的循环:您不想继续下一行,但需要重新启动 您需要在每次尝试失败后重置电路板,或者在每次尝试之前放置 如果在多次迭代后找不到解决方案,您应该构建一些安全机制以退出,否则您将面临陷入困境的风险。对于输入1、2或3,没有解决方案。 试验次数从未增加 与其盲目地选择一个位置,你最好只从没有被阻止的可用位置中选择,否则你将进行惊人数量的试验:对于尺寸8,不进行过滤就需要10万次试验是很正常的! 请参阅更正后的代码,以及我所做更改的注释:

import random

s = input ("enter board size\n")
s = int(s)
trials = 0
block = 1
queen = 2
# add some maximum to the number of attempts
max_trials = 100000 
success = 0

# add safety measure to avoid infinite looping
while success == 0 and trials <= max_trials:
    # initialise board before every trial
    board = [[0 for x in range(s)] for y in range(s)]
    # assume success until failure
    success = 1
    # count trials
    trials += 1 
    for y in range (0, s): # use correct range
        # get the fields that are still available in this row
        available = [x for x, i in enumerate(board[y]) if i == 0]
        if len(available) == 0:
            success = 0
            # exit for loop, you want to start a next trial
            break
        # choose a random position among available spots only
        pos = available[random.randint(0, len(available)-1)]    
        board[y][pos] = queen
        a = 1
        for z in range (y+1, s): # use correct range
            board[z][pos] = block
            if pos - a >= 0:
                board[z][pos - a] = block
            if pos + a < s:
                board[z][pos + a] = block
            a = a + 1

for y in range (0, s): # use correct range
    print (board[y])

print ("Number of trials:", trials)

请参见运行于

以下是一个基于对放置皇后的坐标进行算术运算的简短解决方案:

import random, itertools

def clashes(p,q):
    a,b = p
    c,d = q
    return a == c or b == d or abs(a-c) == abs(b-d)

def solution(queens):
    #assumes len(queens) == 8
    return not any(clashes(p,q) for p,q in itertools.combinations(queens,2)) 

def randSolve():
    counter = 0
    while True:
        counter += 1
        queens = [(i,random.randint(1,8)) for i in range(1,9)]
        if solution(queens): return counter, queens

print(randSolve())
上次运行时,我得到:

(263528, [(1, 4), (2, 7), (3, 3), (4, 8), (5, 2), (6, 5), (7, 1), (8, 6)])

这意味着第一个解决方案是在263527次故障后遇到的。平均而言,在你获得成功之前,你可能会经历182360次失败。

请完成我的代码不是问题。我一直在编写代码和帖子。我希望现在好多了?看起来太复杂了。放置的皇后自然由一对数字表示,例如,第二行第三列为2,3。给定两个皇后a、b和c、d,很容易判断它们是否可以互相攻击,而不需要标记每个皇后攻击的所有方块。如果它们在同一行或同一列上,则不重要。对于对角线情况,只需计算连接皇后的直线的斜率。是+/-1吗?如果是这样,他们可以攻击。如果你真的开始随机放置皇后,直到你找到解决方案,你的程序可能不会在宇宙停止存在之前停止。您看到的是64^8=281474976710656个完全随机的皇后位置,其中只有92个是solution@IrmendeJong我认为你完全误读了这个问题,把皇后完全随机地放在了棋盘的每一行。你让我好奇。我刚刚实现了它,并且能够在几秒钟内得到解决方案。即使是随机放置8也不是没有希望的:64选择8=4426165368,将其下潜92意味着在棋盘上大约5000万个不同位置的选择中平均有1个是解决方案。