Backtracking 8 Queens Python problems - python

I've started solving the 8 queens problem with backtracking in Python. Everything is nice & fine. It even printed out the first answer. However, it stuck itself on its first backtracking try.
The task sounded in that way:
Implement a Python function that solves the 8 queens puzzle. The 8 queen puzzle consists of placing 8 queens on a chess board, so that, none of the queens could capture any other. Note that queens can move orthogonally or diagonally in any direction.
You should implement a function solve() that when called, it prints the first solution of the puzzle and then it awaits for input. Once the user presses ‘enter’, the next solution is printed, and so on.
- Your program should be able to find all the solutions for the puzzle and each solution only once. '
- It should be easy to modify your program, so that, it works for different board sizes. Hints:
- In any row, there is exactly one queen. Hence, all you need to compute is the column in which each of the 8 queens can be placed.
- You should implement a recursive function solve(n) that finds a place for nth+1 the queen and then calls itself recursively for the n+1 queen (unless all the queens have been placed). It should systematically explore all the possibilities using backtracking.
- You are allowed (and encouraged) to define extra functions (other than solve() ) to improve the quality of your code if necessary.
import numpy as np
grid = np.zeros((8, 8), dtype = int)
def possible(y, n):
global solved
global grid
for i in range(0, 8):
if grid[y][i] == n:
return False
try:
for item in solved[str(y)]:
if grid[y].all() == item.all():
return False
except KeyError:
return True
return True
max_y = 7
max_x = 7
def print_grid():
global grid
for line in grid:
for square in line:
if square == 0:
print(".", end = " ")
else :
print("Q", end = " ")
print()
solved = {}
def prefilled_solved():
global solved
for i in range(0, len(grid[0])):
solved[f"{str(i)}"] = []
def solve(y=0):
global grid
global solved
while y < 8:
for x in range(0, 8):
if grid[y][x] == 0:
if possible(x, 1):
grid[y][x] = 1
solved[f"{str(y)}"].append(grid[y])
y += 1
solve(y)
#y -= 1 or y = 0 or y -=2
# backtracking - bad choice
# grid[y][x] = 0
print_grid()
print(grid)
return
input("More?")
if __name__ == '__main__':
prefilled_solved()
solve()
I've followed the #mkam advice, Now I've got the random constellation of Queen but I've got rid of recursion altogether.
```import numpy as np
grid = np.zeros((8, 8), dtype = int)
from random import randint, shuffle, choice
from itertools import permutations
constellations_drawn = []
def print_grid():
global grid
for line in grid:
for square in line:
if square == 0:
print(".", end = " ")
else :
print("Q", end = " ")
print()
solved = []
def prefilled_solved():
global solved
new_board = ['1', '2', '3', '4', '5', '6', '7', '8']
new_board_i = ''.join(new_board)
solved = permutations(new_board_i, 8)
def solve(y=0):
global grid
global solved
global constellations_drawn
list_solved = list(solved)
len_solved = len(list_solved)
board_drawn = list_solved[randint(0, len_solved-1)]
board_drawn_str = ''.join(board_drawn)
while board_drawn_str in constellations_drawn:
board_drawn = list_solved[randint(0, len_solved - 1)]
new_board_list = [int(item) for item in board_drawn]
for i, x in enumerate(new_board_list):
if grid[i-1][x-1] == 0:
grid[i-1][x-1] = 1
#y += 1
#solve(y)
#y -= 1 or y = 0 or y -=2
# backtracking - bad choice
# grid[y][x] = 0
constellations_drawn.append(board_drawn_str)
print_grid()
print(grid)
return
input("More?")
if __name__ == '__main__':
prefilled_solved()
solve()
I've merged the code of #mkam and mine. And it works. I still use numpy ndarray.
import numpy as np
from numpy.core._multiarray_umath import ndarray
def print_grid(solutions_found, board) -> None:
line: ndarray
len_board = len(board)
grid: ndarray = np.zeros((len_board, len_board), dtype=int)
for i, number in enumerate(board):
grid[i - 1][number - 1] = 1
for line in grid:
for square in line:
if square == 0:
print(".", end=" ")
else:
print("Q", end=" ")
print()
print(f'Solution - {solutions_found}')
def solve(boardsize, board=[], solutions_found=0):
if len(board) == boardsize:
solutions_found += 1
print_grid(solutions_found, board)
else:
for q in [col for col in range(1, boardsize + 1) if col not in board]:
if is_safe(q, board):
solutions_found = solve(boardsize, board + [q], solutions_found)
return solutions_found
def is_safe(q, board, x=1):
if not board:
return True
if board[-1] in [q + x, q - x]:
return False
return is_safe(q, board[:-1], x + 1)
if __name__ == '__main__':
solve(8)

This is an example of how the 8-Queens problem can be solved recursively, using a simple list to represent the board. A list such as [8, 4, 1, 3, 6, 2, 7, 5] represents the 8 rows of a chessboard from top to bottom, with a Q in the 8th column of the top row, the 4th column of the 7th row, the 1st column of the 6th row ... and the 5th column of the bottom row.
A solution is built starting with an empty board [] by placing a Q in the next row in a column position where it cannot be taken. Possible positions are columns which have not already been taken earlier (this is the for loop in function solve). For each of these possible column positions, function issafe checks whether the position is safe from being taken diagonally by the Qs already on the board. If the position is safe, the solution board is extended by another row and the solution recurses until the board is filled (len(board) == boardsize), at which point the solution count is incremented and the board is displayed.
Note that the function solve works for any size of square chessboard - the desired size is passed as a parameter to solve, and the function returns the total number of solutions found.
Hope this helps explain how the 8-Queens problem can be solved recursively WITHOUT numpy.
def display(solution_number, board):
row = '| ' * len(board) + '|'
hr = '+---' * len(board) + '+'
for col in board:
print(hr)
print(row[:col*4-3],'Q',row[col*4:])
print(f'{hr}\n{board}\nSolution - {solution_number}\n')
def issafe(q, board, x=1):
if not board: return True
if board[-1] in [q+x,q-x]: return False
return issafe(q, board[:-1], x+1)
def solve(boardsize, board=[], solutions_found=0):
if len(board) == boardsize:
solutions_found += 1
display(solutions_found, board)
else:
for q in [col for col in range(1,boardsize+1) if col not in board]:
if issafe(q,board):
solutions_found = solve(boardsize, board + [q], solutions_found)
return solutions_found
if __name__ == '__main__':
solutions = solve(8)
print(f'{solutions} solutions found')
You mention using yield - this is also possible, and will transform solve into a generator, producing one solution at a time. Your program can then use a for loop to receive each solution in turn and process it as required. The following yield solution works with Python v.3.3 onwards because it uses yield from:
def display(solution_number, board):
row = '| ' * len(board) + '|'
hr = '+---' * len(board) + '+'
for col in board:
print(hr)
print(row[:col*4-3],'Q',row[col*4:])
print(f'{hr}\n{board}\nSolution - {solution_number}\n')
def issafe(q, board, x=1):
if not board: return True
if board[-1] in [q+x,q-x]: return False
return issafe(q, board[:-1], x+1)
def solve(boardsize, board=[]):
if len(board) == boardsize:
yield board
else:
for q in [col for col in range(1,boardsize+1) if col not in board]:
if issafe(q,board):
yield from solve(boardsize, board + [q])
if __name__ == '__main__':
for solutionnumber, solution in enumerate(solve(8)):
display(solutionnumber+1, solution)
If the recursive function issafe appears confusing, here is a non-recursive version:
def issafe(q, board):
x = len(board)
for col in board:
if col in [q+x,q-x]: return False
x -= 1
return True

Related

How to store matrix list data in recursive python function?

I am trying to solve the N_Queen problem with recursive function. My codes are shown below. The problemm is that I cannot store the acceptable solution in a list. I can see that all the right answers appeared while debuging, but those answers cannot store in a list outside the recursive function. I hope the acceptable solution could be stored in a list and keep on recursion for the next right answer. But the appended solution are always changing.
By importing copy and deepcopy, I have solved the problem, yet it is still confusing. It seems that others can store pure list result without deepcopy, but my matrix list is unacceptable.
THX.
def NQueens(self, n: int) -> int:
res = []
board = [['.' for _ in range(n)] for _ in range(n)]
def backtrack(board,row):
if row == n:
res.append(board) # **this is the confusing part**
return
for col in range(n):
if not isvalid(board,row,col):
continue
board[row][col] = 'Q'
backtrack(board,row+1)
board[row][col] = '.'
def isvalid(board,row,col):
for i in range(row):
if board[i][col] == 'Q':
return False
for i in range(1,row+1):
if col - i >= 0 and board[row - i][col - i] == 'Q':
return False
for i in range(1,row+1):
if col + i < n and board[row - i][col + i] == 'Q':
return False
return True
backtrack(board,0)
return res
The problem is not that you can't save it, the problem is that after saving it you change the values of the board and they are linked so they both change so, when you finally return res, you end up returning the last state of board x times over, x beeing the times you appended it
I currently don't know hot to solve this but when i find out i'll edit or comment on this
i finally found the problem, sorry for the wait.
In the line board[row][col] = '.' there were no conditions for that, what i mean is that it will alwas happen so when you put a queen after backtracking you'll remove it without exceptions.
I changed it so it will make a return true statement if achived to place all the queens so when backtracking it will not delete them if it found a solution.
I'll leave the working code, commenting what i changed, here:
def NQueens(n: int) -> int:
board = [['.' for _ in range(n)] for _ in range(n)]
def backtrack(board,row):
#If all queens are placed then return true
if row >= n:
return True
for col in range(n):
#if it is valid place the queen and try to place the next queen on the next row
if isvalid(board,row,col):
board[row][col] = 'Q'
if backtrack(board,row+1) == True:
return True
#if placing the queen was not the way to the solution remove the queen
board[row][col] = '.'
#if the queen can't be placed in any column in this row return false
return False
def isvalid(board,row,col):
for i in range(row):
if board[i][col] == 'Q':
return False
for i in range(1,row+1):
if col - i >= 0 and board[row - i][col - i] == 'Q':
return False
for i in range(1,row+1):
if col + i < n and board[row - i][col + i] == 'Q':
return False
return True
backtrack(board,0)
return board #directly return board, res was innecesary

How to stop yielding sudoku boards, once the puzzle is solved?

This is my recursive sudoku solver. Pretty self-explanatory:
def is_valid(board, num, row, col):
# check row
for i in range(9):
if board[i][col] == num:
return False
# check column
for i in range(9):
if board[row][i] == num:
return False
# check square
square_w = (row // 3) * 3
square_h = (col // 3) * 3
for sRow in range(square_w, square_w + 3):
for sCol in range(square_h, square_h + 3):
if board[sRow][sCol] == num:
return False
return True
def solve(board):
for row in range(9):
for col in range(9):
if board[row][col] == 0:
for num in range(1, 10):
if is_valid(board, num, row, col):
board[row][col] = num
yield board
yield from solve(board)
board[row][col] = 0
yield board
return
yield board
And this is the board I am running the solver on:
bo = [
[7,8,0,4,0,0,1,2,0],
[6,0,0,0,7,5,0,0,9],
[0,0,0,6,0,1,0,7,8],
[0,0,7,0,4,0,2,6,0],
[0,0,1,0,5,0,9,3,0],
[9,0,4,0,6,0,0,0,5],
[0,7,0,3,0,0,0,1,2],
[1,2,0,0,0,7,4,0,0],
[0,4,9,2,0,6,0,0,7]
]
The problem is that when I call solve and iterate the yielded boards, the boards continue to generate even after getting the result (at the bottom most yield board in the solve function).
How can I make sure that the last value in the generator is the solved board?
There are some indentation problems in your code. At the time of writing both the return and yield from statements should be indented one level more.
To stop the generation of more boards once you have it solved, you should check that the board is solved. The code does not do this anywhere.
As you correctly indicate, the board is solved when you reach the last statement in the solve function, and the function returns there. You could use this moment to mark the board so to make it easier for the caller to also know that the board was solved. As you already mutate the same board throughout the algorithm (instead of yielding copies), I suppose you could just mutate the board once more in order to indicate it was solved. For instance, you could store a 0 in the top-left corner. This can be checked by the caller, who can then immediately return:
def solve(board):
for row in range(9):
for col in range(9):
if board[row][col] == 0:
for num in range(1, 10):
if is_valid(board, num, row, col):
board[row][col] = num
yield board
yield from solve( board) # corrected wrong indentation
if board[0][0] == 0: # was the board already solved?
return # then get out of here!
board[row][col] = 0 # better placed at this indentation
yield board # better placed at this indentation
return # corrected wrong indentation
# the board is the solution: no need to yield it as it was already yielded
board[0][0] = 0 # mark that no more boards should be yielded

NQueens - Recursive BackTracking Question

I'm currently learning BackTracking algorithms with Python and the first question everyone typically starts with is NQueens. NQueens is where you take a board of size N x N and you have to determine where to place N queens, in such an order they are not attacked by any other queen.
Example:
N = 5
['Q', 0, 0, 0, 0]
[0, 0, 'Q', 0, 0]
[0, 0, 0, 0, 'Q']
[0, 'Q', 0, 0, 0]
[0, 0, 0, 'Q', 0]
Currently, my algorithm returns ALL Possible Solutions. How do I produce ONE outcome. For instance, when N = 8, there are 92 optimal outcomes, how do I just return One Outcome instead of printing 92 separate Outcomes.
#This is our main recursive function that will determine optimal outcome
def NQueens(row,Current,N):
#this tells us when to stop
if row == N:
print("\n")
return printBoard(Current)
for choice in range(0,N):
if isValid(row,choice,Current,N):
#Place Queen in appropriate spot
Current[row][choice] = "Q"
#Go to next row
NQueens(row+1,Current,N)
Current[row][choice] = 0
return "All Solutions Found"
#This function determines whether we can put a Queen in a certain orientation on the board
def isValid(row,col,Current,N):
#check whether current state of game has queen in row/column
for i in range(0,N):
#checks column/row and sees whether a queen exists already
if Current[row][i] == "Q" or Current[i][col] == "Q":
return False
# Check upper diagonal on right side
i = row-1
j = col + 1
#Do while row is greater than 0 and column is less than N
while i >= 0 and j < N:
if Current[i][j] == "Q":
return False
i -= 1
j += 1
# Check upper diagonal on left side
#Do while row is greater than 0 and column is greater than N
i = row-1
j = col - 1
while i >= 0 and j >= 0:
if Current[i][j] == "Q":
return False
i -= 1
j -= 1
#If we pass the diagonal/row/column tests, we can then determine this is a valid move
return True
###############################################################################################################
#These functions deal with board creation and printing them in a proper format
def generateBoard(N):
#generate board based on User Input N in Main()
Board = [[0 for i in range(0,N)] for j in range(0,N)]
return Board
def printBoard(arr):
#Loop through each row to print an organized board
for row in arr:
print(row)
def main():
#ask number from user
print("What sized board would you like?"
" Please input a number higher that 3: ")
#user input used to determine size of board
N = int(input())
#generate Board that will be used
Board = generateBoard(N)
#this is the current status of the board
printBoard(Board)
print("\n")
#Runs Algorithm
print(NQueens(0,Board,N))
if __name__ == "__main__":
main()
NQueens needs to communicate to its caller that a solution has been found; a simple return True will do if that's the case. I made the following changes to your code (your previous lines are commented):
def NQueens(row,Current,N):
#this tells us when to stop
if row == N:
print("\n")
#return printBoard(Current)
return True # found a solution, say so
for choice in range(0,N):
if isValid(row,choice,Current,N):
#Place Queen in appropriate spot
Current[row][choice] = "Q"
#Go to next row
# NQueens(row+1,Current,N)
if NQueens(row+1,Current,N): # recursive call found a solution, let's stop
return True
Current[row][choice] = 0
#return "All Solutions Found"
And in main():
# ...
#Runs Algorithm
#print(NQueens(0,Board,N))
if NQueens(0,Board,N):
printBoard(Board) # found a solution, print it
I have fixed your code to have well-perfoming:
I merge this code https://www.geeksforgeeks.org/n-queen-problem-backtracking-3/ and yours to get it.
count = 1
def printOut(arrayMap):
global count
print('{}: -'.format(count))
count += 1
for i in range(0, len(arrayMap)):
print(arrayMap[i])
# This is our main recursive function that will determine optimal outcome
def NQueens(currentRow, arrayMap, matrixSize):
# this tells us when to stop
if currentRow == matrixSize:
print()
printOut(arrayMap)
return True # found a solution, say so
res = False
for col in range(0, matrixSize):
if isValid(currentRow, col, arrayMap, matrixSize):
# Place Queen in appropriate spot
arrayMap[currentRow][col] = 0
# Go to next row
# NQueens(row+1,Current,N)
res = NQueens(currentRow + 1, arrayMap, matrixSize) or res # recursive call found a solution, let's stop
arrayMap[currentRow][col] = 1
# return "All Solutions Found"
return res
# This function determines whether we can put a Queen in a certain orientation on the board
def isValid(row, col, arrayMap, matrixSize):
# check whether current state of game has queen in row/column
for i in range(0, matrixSize):
# checks column/row and sees whether a queen exists already
if arrayMap[row][i] == 0 or arrayMap[i][col] == 0:
return False
# Check upper diagonal on right side
i = row - 1
j = col + 1
# Do while row is greater than 0 and column is less than N
while i >= 0 and j < matrixSize:
if arrayMap[i][j] == 0:
return False
i -= 1
j += 1
# Check upper diagonal on left side
# Do while row is greater than 0 and column is greater than N
i = row - 1
j = col - 1
while i >= 0 and j >= 0:
if arrayMap[i][j] == 0:
return False
i -= 1
j -= 1
# If we pass the diagonal/row/column tests, we can then determine this is a valid move
return True
###############################################################################################################
if __name__ == "__main__":
# ask number from user
print("What sized board would you like?")
N = int(input('Choose your size: '))
# generate Board that will be used
Board = [[1 for i in range(0, N)] for j in range(0, N)]
count = 0
NQueens(0, Board, N)

Function to find winning line with NxN board and M pieces in a row in Python 3

I am trying to create a function that finds if a move is winning on an NxN board where the winning condition is M pieces in a row in Python 3.
I am pretty new to programming and in my specific case I am creating a Gomoku game (15x15 board with 5 pieces in a row to win). To get it working I created 6 for loops to check vertical, horizontal and 4 diagonals. See the code below for examples on the 2 options for left to right digonals. This takes way too long though when I need to loop through it many times (8) for computer to find if I can win or if it has a winning move.
end_row = 15
for j in range(11):
end_row -= 1
counter = 0
for i in range(end_row):
if board[i+j][i] == board[i+1+j][i+1] and board[i+j][i] != ' ':
counter += 1
if counter == 4:
winning_line = [(i+j-3, i-3), (i+j-2, i-2), (i+j-1, i-1), (i+j, i), (i+1+j, i+1)]
winner = True
break
else:
counter = 0
# Top left to bottom right, lower side
end_row = 15
for j in range(11):
end_row -= 1
counter = 0
for i in range(end_row):
if board[i][i+j] == board[i+1][i+1+j] and board[i][i+j] != ' ':
counter += 1
if counter == 4:
winning_line = [(i-3, i+j-3), (i-2, i+j-2), (i-1, i+j-1), (i, i+j), (i+1, i+1+j)]
winner = True
break
else:
counter = 0
# What I want to do instead, where x and y are coordinates of last move:
# Horizontal
counter = 0
for i = x - (n - 1) to x + (n - 1):
if board[i][y] == board[x][y] :
counter++
else :
counter = 0
if counter == n:
return true
The problem with the lower part of the code is that if I place a piece on e.g. position (0, 0) the program will complain when trying to reach board[-4][0] in the first looping. I will have to place lots of if statements when I get close to the edge, which is not an elegant solution.
I thought of making a 3*15 x 3*15 board instead, where the actual board is the inner 15x15 part and the rest just contains placeholders:
15x15 || 15x15 || 15x15
15x15 || board || 15x15
15x15 || 15x15 || 15x15
This to avoid getting outside of my list of lists when looping through. Not an elegant solution either, but takes less space in the code.
Any suggestions on how to solve this problem? Thank you in advance from a beginner programmer!
As #MePsyDuck mentioned in comments, you can use min and max functions to limit the range to only reference valid squares in the board matrix.
Furthermore, you could make a generic function that does the count-job on any given list of values. Then you can call that generic function four times: once for every direction (horizontal, vertical, diagonal \ and diagonal /)
Here is how that could work:
def is_win(board, n, x, y):
end_row = len(board)
color = board[x][y]
def check(values):
counter = 0
for value in values:
if value == color:
counter += 1
else:
counter = 0
if counter == n:
return True
return False
return (check([board[i][y] for i in range(max(0, x - n + 1), min(end_row, x + n))])
or check([board[x][i] for i in range(max(0, y - n + 1), min(end_row, y + n))])
or check([board[x+i][y+i] for i in range(max(-x, -y, 1 - n), min(end_row - x, end_row - y, n))])
or check([board[x+i][y-i] for i in range(max(-x, y - end_row + 1, 1 - n), min(end_row - x, y + 1, n))]))
Instead of looping from 0 to 14, just loop from 0 to (board_size - winning_length).
Here's an example for a 1-dimensional board:
BOARD_SIZE = 15
WINNING_LENGTH = 5
for x in range(BOARD_SIZE - WINNING_LENGTH):
players_here = set()
for pos in range(x, x + WINNING_LENGTH):
players_here.add(board[pos])
if len(players_here) == 1:
# Exactly 1 player occupies every position in this line, so they win

Conaway's Game of Life problems

Here is my very rough implementation of Conway's Game of Life simulation.
LIVE = 1
DEAD = 0
def board(canvas, width, height, n):
for row in range(n+1):
for col in range(n+1):
canvas.create_rectangle(row*height/n,col*width/n,(row+1)*height/n,(col+1)*width/n,width=1,fill='black',outline='green')
n = int(raw_input("Enter the dimensions of the board: "))
width = n*25
height = n*25
from Tkinter import *
import math
window=Tk()
window.title('Game of Life')
canvas=Canvas(window,width=width,height=height,highlightthickness=0)
canvas.grid(row=0,column=0,columnspan=5)
board = [[DEAD for row in range(n)] for col in range(n)]
rect = [[None for row in range(n)] for col in range(n)]
for row in range(n):
for col in range(n):
rect[row][col] = canvas.create_rectangle(row*height/n,col*width/n,(row+1)*height/n,(col+1)*width/n,width=1,fill='black',outline='green')
#canvas.itemconfigure(rect[2][3], fill='red') #rect[2][3] is rectangle ID
#print rect
f = open('filename','r') #filename is whatever configuration file is chosen that gives the step() function to work off of for the first time
for line in f:
parsed = line.split()
print parsed
if len(parsed)>1:
row = int(parsed[0].strip())
col = int(parsed[1].strip())
board[row][col] = LIVE
board[row][col] = canvas.itemconfigure(rlist[row][col], fill='red')
def surrounding(row,col):
count = 0
if board[(row-1) % n][(col-1) % n] == LIVE:
count += 1
if board[(row-1) % n][col % n] == LIVE:
count += 1
if board[(row-1) % n][(col+1) % n] == LIVE:
count += 1
if board[row % n][(col-1) % n] == LIVE:
count += 1
if board[row % n][(col+1) % n] == LIVE:
count += 1
if board[(row+1) % n][(col-1) % n] == LIVE:
count +=1
if board[(row+1) % n ][col % n] == LIVE:
count += 1
if board[(row+1) % n][(col+1) % n] == LIVE:
count += 1
print count
return count
surrounding(1,1)
def round():
board_copy = board
for row in range(n):
for col in range(n):
if surrounding(row,col) == 3:
board_copy[row][col] = LIVE
board_copy[row][col] = canvas.itemconfigure(rect[row][col],fill='red')
elif surrounding(row,col) > 3 or getNeighbors(row,col) < 2:
board_copy[row][col] = DEAD
board_copy[row][col] = canvas.itemconfigure(rect[row][col],fill='black')
board = board_copy
def start():
global alarm
alarm = window.after(500,round)
def stop():
window.after.cancel(alarm)
So I have a function to count how many surrounding squares around a certain square had the value LIVE (where LIVE = 1).
Originally, all squares were initialized to DEAD. The configuration file determines which squares are assigned the value LIVE. Made a configuration file so that the 8 squares surrounding the square at 1,1 would return a value of 8, but I am getting back a value of 0 consistently, no matter the configuration or the tested square.
UPDATE: Changed the counter to begin at 1 and the return value was 1. I'm guessing my function isn't actually counting (or reading the values of the surrounding squares on the board), but I can't see why it would not.
Also, for my step() function, I need a function that makes a copy of the board and then changes the fill on the copy depending on a count being performed on the original board. If a rectangle on the original board has 3 rectangles with the values of LIVE, then the rectangle with the same indices on the board copy will have a LIVE value and turn red. Same for DEAD, except for different case. At the end the copied board (with changes) replaces the original board so that when we run the function again, it will be based off the copy.
I'm assuming board_copy = board is sufficient in making the copy; what do I write so that on the Tkinter window, after the function is performed, the board_copy is what appears?
The format of the config file is
rownum colnum
rownum colnum
So the config file I used if I wanted to get 8 in countNeighbors function (if it worked) for the first round would be:
0 0
0 1
0 2
1 0
1 2
2 0
2 1
2 2
I'm assuming board_copy = board is sufficient in making the copy;
No, board_copy = board is not sufficient. This will just bind the name board_copy to the exact same list of list as board, i.e. everything you change in board_copy is also changed in board.
Instead, you could use the deepcopy function from the copy module:
import copy
board_copy = copy.deepcopy(board)
Or use a list-comprehension to create a deep copy of the nested list:
board_copy = [[x for x in row] for row in board]
The use of board = board_copy at the end of the method is okay, since here you just want to bind the new board to board. Note, however, that you will also need to add global board at the top of the method to access the globally defined board.
Also, note that you define both a function board (def board(...): and a global variable board (board = [...]). The latter will shadow the first, i.e. you will not be able to use the board function. You should rename the function to e.g. def draw_board(...).
There might be more problems with your code, but I can not execute it sinceit seems to be incomplete (where is start called?) and I do not know the content of 'filename'.

Categories

Resources