简体   繁体   中英

Python “The Knight's Tour” backtracking code not working

Having watched the Computerphile video on backtracking, I've decided to attempt to implement this algorithm for a different problem. My code seems to work up until depth ~48 when it starts to endlessly iterate through depth 46-53. It is not a problem of memory, as for a 6x6 table it gets stuck similarly around depth 20.

table = np.zeros((8, 8)) - 1
table[0, 0] = 0
knightDOWN = [1, 2, 2, 1, -1, -2, -2, -1]
knightRIGHT = [2, 1, -1, -2, -2, -1, 1, 2]
depth = 0
def correctmove(move, startROW, startCOL):
    newROW = startROW + knightDOWN[move]
    newCOL = startCOL + knightRIGHT[move]
    if newROW < 0 or newROW > 7:
        return False
    if newCOL < 0 or newCOL > 7:
        return False
    if table[newROW, newCOL] != -1:
        return False
    return True

def goBoard(startROW, startCOL, nummove):
    if depth == 64:
        print(table)
        exit()
    for x in range(0, 8):
        if correctmove(x, startROW, startCOL):
            print(table[startROW, startCOL])
            startROW += knightDOWN[x]
            startCOL += knightRIGHT[x]
            table[startROW, startCOL] = nummove
            nummove += 1
            goBoard(startROW, startCOL, nummove)
            table[startROW, startCOL] = -1
            startROW -= knightDOWN[x]
            startCOL -= knightRIGHT[x]
            nummove -= 1
    return
goBoard(0, 0, 0)

The code is basically supposed to check whether it can go with the knight to some new position, do it until it cannot move forward anymore and at this point the part of code after recursion call resets it back again. After seeing sample tables it seems to correctly create those first 50 or so tries but gets stuck on those and iterates over and over.

This should take a long time, and backtrack a lot, as you're using a brute force algorithm that needs to exhaust a lot of possibilities.

In your code I don't see where depth is incremented though it's redundant with nummove which should start at 1, not 0, as you've already made move 0. I reworked your code to return a result, rather than print and exit , removed numpy , rewriting it in straight Python instead, and simplified it a bit -- undoing fewer steps:

KNIGHT_MOVES = [(1, 2), (2, 1), (2, -1), (1, -2), (-1, -2), (-2, -1), (-2, 1), (-1, 2)]

table = [[-1] * 8 for _ in range(8)]

table[0][0] = 0

def correctmove(row, col):
    return 0 <= row <= 7 and 0 <= col <= 7 and table[row][col] == -1

def goBoard(startROW, startCOL, nummove):
    if nummove == 64:
        return table

    for down, right in KNIGHT_MOVES:
        row = startROW + down
        col = startCOL + right

        if correctmove(row, col):
            print(nummove)

            table[row][col] = nummove
            result = goBoard(row, col, nummove + 1)

            if result:
                return result

            table[row][col] = -1

    return None

print(*goBoard(0, 0, 1), sep='\n')

After about 2 1/3 minutes, it produces the following (slightly hand reformatted):

[ 0, 37, 58, 35, 42, 47, 56, 51]
[59, 34,  1, 48, 57, 50, 43, 46]
[38, 31, 36, 41,  2, 45, 52, 55]
[33, 60, 39, 26, 49, 54,  3, 44]
[30,  9, 32, 61, 40, 25, 22, 53]
[17, 62, 27, 10, 23, 20, 13,  4]
[ 8, 29, 18, 15,  6, 11, 24, 21]
[63, 16,  7, 28, 19, 14,  5, 12]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM