Conaway's Game of Life problems - python

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'.

Related

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)

Backtracking 8 Queens Python problems

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

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

Make Robot Walk Path in Python [duplicate]

This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 5 years ago.
So this problem was given as an end of the class quiz. I didnt have time to test it out so I tried re-writting it and testing. However for some reason its not working the way I want it and I dont know why.
So you've got a nxn grid given as lists. A robot with an initial starting point given as a tuple. And the path the robot will travel given as "N", "S", "E", "W" within a list.
so input would be something like
make_grid(starting_point, path, size_of_grid)
make_grid((0,0),["S","E","S","S"],4)
with an output like
[".","_","_","_"],[".",".","_","_"],["_",".""_""_"],["_",".""_""_"]
where the "." is the robots starting point and traveled path. The "_" are the untraveled areas of the grid. And if it hits the border it stays in the exact same spot.
My problem is the result is that it marks the whole column as a traveled path with a period
def check(coord ,size):
if ((coord<0) or (coord>size)):
return True
else:
return False
def make_grid(start, path, size):
n = 0
row = []
while (n < size):
row.append("_")
n += 1
n = 1
grid = [row]
while ( n < size):
grid.append(row)
n +=1
x = start[0]
y = start[1]
grid[x][y] = "."
n = 0
while (n < len(path)):
if (path[n] == "N"):
x -= 1
if (check(x,size)):
x += 1
elif (path[n] == "E"):
y += 1
if (check(y,size)):
y -= 1
elif (path[n] == "S"):
x +=1
if (check(x,size)):
x -=1
elif (path[n] == "W"):
y -=1
if (check(y,size)):
y += 1
grid[x][y] = "."
n += 1
n = 0
while (n < size):
print grid[n]
n += 1
Your initialization of each row in grid is setting each row to the same list. So any change to an element in grid will change every row (since they are all the same list). You need to set each element of grid to a separate object. Something like:
grid = []
for i in range(size):
grid.append([])
for j in range(size):
grid[i].append('_')
I'm sure a more experienced Python programmer can come up with a more compact initialization.

Conway's Game of Life with Python

I took a liking to Conway's Game of Life and began to try and write it in python. At this moment I have yet to write any code for the borders of the program so I am just asking for help with what I have right now. I seem to have trouble when initialization a "blinker" formation. Instead of oscillating like it should, it seems to turn itself into a cube.
#File: gameoflife.py
#Description: This is a basic "life" simulation that follows three distinct rules:
#1.Any live cell with fewer than two live neighbours dies
#2.Any live cell with two or three live neighbours lives
#3.Any live cell with more than three live neighbours dies
#4.Any dead cell with exactly three live neighbours becomes a live cell
#A neighbor is deemed as any cell directly horizantal/vertical/diagonal
#meaning there are 9 neighbors to a cell at any time
from graphics import *
import random
from time import sleep
def initial(D,M,win):
#Creates the white board background
for i in range (11):
m = [] # rectangle list
for j in range (11):
rec = Rectangle(Point(6 + 4 * i, 6 + 4 * j), Point(10 + 4 * i, 10 + 4 * j))
D[i][j] = 0
rec.setFill("white")
rec.draw(win)
m.append(rec)
M.append(m)
def check(x,y,D):
#Checks all 9 adjacent neihbors to see if "alive" and checks this number
#means the cell should stay alive(1), die(0), or if already dead come
#back alive(2)
counter = 0
if D[x+1][y] == 1:
counter += 1
if D[x-1][y] == 1:
counter += 1
if D[x][y+1] == 1:
counter += 1
if D[x][y-1] == 1:
counter +=1
if D[x+1][y+1] == 1:
counter+=1
if D[x+1][y-1] == 1:
counter+= 1
if D[x-1][y-1] == 1:
counter += 1
if D[x-1][y+1] == 1:
counter +=1
if counter<2 or counter>3:
return 0
if counter == 2:
return 1
if counter == 3:
return 2
def main():
win = GraphWin("Game of Life", 700, 600)
win. setCoords(0, 0, 70, 60)
#Initialize two dimesion arrays.
#D records color of grids, M records rectangles
D = []
M = []
C = []
#initialize the grids to create all "white"
for i in range(11):
d = []
c = []
for j in range(11):
d.append(0)
c.append(0)
D.append(d)
C.append(c)
initial(D,M,win)
#Initialzes three "alive" units
D[5][5],D[4][5] ,D[6][5]= 1,1,1
C[5][5],C[4][5] ,C[6][5]= 1,1,1
M[5][5].setFill("Black")
M[4][5].setFill("Black")
M[6][5].setFill("Black")
#Contiually checking
while True:
#Purposfully not checking the "Borders" of the array
for i in range (len(D)-1):
for j in range(len(D[i])-1):
#If the cell is alive
if D[i][j] == 1:
#If the cell should die
if check(i,j,D) == 0:
sleep(1)
#Sets a temporary list to white
C[i][j] = 0
#Fills the cell white
M[i][j].setFill("White")
#if the cell is dead
if D[i][j] == 0:
#If the cell should be revived
if check(i,j,D) == 2:
sleep(1)
#Sets a temporary list to black
C[i][j] = 1
#Fills the cell black
M[i][j].setFill("Black")
#Sets the main list = to the temporary list
D = C
main()
You will need to swap D and C, and not just assign C to D. As it stands now, D and C will be referring to the same list after the first iteration.
Here is a simple algorithm to do Conway's Game of Life in python using a numpy array of arbitrary 2D size:
import numpy
# this function does all the work
def play_life(a):
xmax, ymax = a.shape
b = a.copy() # copy grid & Rule 2
for x in range(xmax):
for y in range(ymax):
n = numpy.sum(a[max(x - 1, 0):min(x + 2, xmax), max(y - 1, 0):min(y + 2, ymax)]) - a[x, y]
if a[x, y]:
if n < 2 or n > 3:
b[x, y] = 0 # Rule 1 and 3
elif n == 3:
b[x, y] = 1 # Rule 4
return(b)
# replace (5, 5) with the desired dimensions
life = numpy.zeros((5, 5), dtype=numpy.byte)
# place starting conditions here
life[2, 1:4] = 1 # a simple "spinner"
# now let's play
print(life)
for i in range(3):
life = play_life(life)
print(life)
This is not very efficient, but will certainly get the job done. Replace print(life) with whatever graphical calls you prefer.

Categories

Resources