Recursion - The Eight Queens Problem

1 Introduction

8x8 board with 8 pieces.
They cannot be on the same line. (horizontal, diagonal)

Play online: https://www.novelgames.com/en/queens/

2, JS implementation

let size = 8
let count = 0
loopTo([], 0)
function loopTo(arr, v) {
    
    
	if (arr.length === size) {
    
    
		console.log(++count + "[" + arr.toLocaleString() + "]")
		loopBack(arr)
	} else if (canPut(arr, v)) {
    
    
		arr.push(v)
		loopTo(arr, 0)
	} else if (v < size - 1) {
    
    
		loopTo(arr, v + 1)
	} else {
    
    
		setTimeout(() => {
    
    
			loopBack(arr)
		}, 1)
	}
}
function loopBack(arr) {
    
    
	let v = arr.pop()
	while (v !== undefined && v >= size - 1) {
    
    
		v = arr.pop()
	}
	if (v === undefined) {
    
    
		console.log("无解")
	} else {
    
    
		loopTo(arr, v + 1)
	}
}
function canPut(arr, v) {
    
    
	for (let m = 0; m <= arr.length - 1; m++) {
    
    
		if (arr[m] === v) {
    
    
			return false
		} else if (arr.length - m === v - arr[m]) {
    
    
			return false
		} else if (arr.length - m === arr[m] - v) {
    
    
			return false
		}
	}
	return true
}

Effect: Count to 92, and then there is no other solution.

insert image description here

3. Detailed implementation

Verify the validity of the results

Compare the length of the result.
Two-level traversal, comparing the position of the pawn with all the previous pawns.

function checkResult(arr) {
    
    
	if (arr.length !== size) {
    
    
		return false
	}
	for (let i = 1; i < size; i++) {
    
    
		for (let j = 0; j < i; j++) {
    
    
			if (arr[i] === arr[j]) {
    
    
				return false
			} else if (Math.abs(i - j) === Math.abs(arr[i] - arr[j])) {
    
    
				return false
			}
		}
	}
	return true
}

Verify that it is possible to join the array

True if the position matches, false if it doesn't.

function canPut(arr, v) {
    
    
	for (let m = 0; m <= arr.length - 1; m++) {
    
    
		if (arr[m] === v) {
    
    
			return false
		} else if (Math.abs(arr.length - m) === Math.abs(v - arr[m])) {
    
    
			return false
		}
	}
	return true
}

go back

If the maximum value is not satisfied, it will roll back.

No element means no solution.

The size of the top element of the stack reaches the maximum value and continues to roll back.
Otherwise, add one and try again.

function loopBack(arr) {
    
    
	if (arr.length === 0) {
    
    
		console.log("无解")
		return
	}
	let v = arr.pop()
	if (v >= size - 1) {
    
    
		loopBack(arr)
	} else {
    
    
		loopTo(arr, v + 1)
	}
}

main loop

The timer is added to avoid stack overflow. . .
(Odd uses added!)

If it is long enough, it means it is full.
output, and then fall back.

If you can get in, get in. Then continue.
If it cannot be entered, the judgment value will be returned if it is too large, and it will be incremented by one if it is not large.

function loopTo(arr, v) {
    
    
	setTimeout(() => {
    
    
		if (arr.length === size) {
    
    
			console.log(++count + "[" + arr.toLocaleString() + "]" + checkResult(arr))
			loopBack(arr)
		} else if (canPut(arr, v)) {
    
    
			arr.push(v)
			loopTo(arr, 0)
		} else if (v < size - 1) {
    
    
			loopTo(arr, v + 1)
		} else {
    
    
			loopBack(arr)
		}
	}, 1)
}

Extra: More Queens

Nine Queens.

insert image description here

Guess you like

Origin blog.csdn.net/qq_37284843/article/details/123860105