Python: Why are my children not creating children? - python

Here is the code: (from MAIN file)
def BestFirstSearch(startingBoard):
Q = [startingBoard]
Visited = []
while (len(Q) != 0):
Q.sort()
currentQ = Q.pop(0)
Visited.append(currentQ)
# print(currentQ)
if (currentQ.Board == currentQ.GOAL):
return True
currentQ.createChildrenBoards()
for items in currentQ.Children:
if items not in Visited:
Q.append(items)
print(len(Q))
print(currentQ)
return False
(from CLASS file):
def createChildrenBoards(self):
""" Creates the set of potential children Boards from the current Board """
row = self.X
col = self.Y
assert( (row >=0 and row < BoardClass.N)
and
(col >=0 and col < BoardClass.N) )
newChildrenBoards = []
#print(self.Board[row][col])
# UP(NORTH): slide empty (0) space up
if ( row != 0 ):
newChildBoard = self.copyCTOR()
newChildBoard.Parent = self
newChildBoard.X = row-1
newChildBoard.Y = col
holdCell = newChildBoard.Board[newChildBoard.X][newChildBoard.Y]
newChildBoard.Board[newChildBoard.X][newChildBoard.Y] = 0
newChildBoard.Board[row][col] = holdCell
newChildrenBoards.append(newChildBoard)
for puzzle in newChildrenBoards:
puzzle.computeDistanceFromGoal()
self.Children = newChildrenBoards
Here are portions of the code I'm working with. I initialized the starting board in a class that constructs the puzzle. Then in my main I would call the create children function which creates a list of children based on where you can move the zero (north being an example of how I would move 0).
The puzzle looks like this:
Goal = [ [0, 1, 2], [3, 4, 5], [6, 7, 8] ]
Puzzle = [ [3, 1, 2], [4, 7, 5], [6, 8, 0] ]
I'm not getting why the queue won't add more children from the children created from the starting board. I'm hoping that I can get feedback that will help me understand why my loop isn't registering the "grandchildren". Thank you!

Related

Why __str__(self) doesn't work when calling the print() function?

I'm diving into OOP and learning magic (or dunder) techniques. Python 3.8.8.
I created class FreqStack() with a pop() method that removes the most frequent elements and returns an updated stack.
class FreqStack():
def __init__(self, lst:list = None):
if lst is None:
self.stack = []
else:
self.stack = lst[::-1]
def push(self, el: int):
self.stack.insert(0, el)
return self.stack
def pop(self):
if len(self.stack) != 0:
hash_map = {}
for el in self.stack:
hash_map[el] = hash_map.get(el, 0) + 1
most_freq_el = max(hash_map, key=hash_map.get)
while most_freq_el in self.stack:
self.stack.remove(most_freq_el)
return self.stack
else:
return 'Stack is empty!'
def __str__(self):
return '\n|\n'.join(str(el) for el in self.stack)
I also added the dunder method str(), which, as far as I understand correctly, must return a custom string when calling the print() function.
However, the print() function in the example below, instead of returning a string, returns a list.
lst = [1, 1, 1, 5, 5, 5, 3, 3, 3, 7, 7, 9]
freq_stack = FreqStack(lst)
for i in range(6):
print(freq_stack.pop())
Output:
[9, 7, 7, 5, 5, 5, 1, 1, 1]
[9, 7, 7, 1, 1, 1]
[9, 7, 7]
[9]
[]
Stack is empty!
I googled everything related to this problem, and couldn't solve it. What am I doing wrong?
You are printing the return value of pop, not the freq_stack itself.
The __str__ method is for the freq_stack object, so you may try something like:
freq_stack.pop()
print(freq_stack)

Optimization 8-puzzle

I'm junior programmer, I am trying to solve 8-puzzle problem with breadth first search, but it took too long time to solve it, i want to optimize my code.
Configuration: [[5, 4, 3], [0, 7, 2], [6, 1, 8]] is going to solve in 22.623718615 seconds,
configuration [[8, 0, 6], [5, 4, 7], [2, 3, 1]] took among 235.721346421 seconds.
I want to decrease solve time.
There is my code:
from copy import deepcopy
from collections import deque
from time import perf_counter
most_hard = [[8, 0, 6], [5, 4, 7], [2, 3, 1]] # 30 moves
class CheckPuzzle:
def __init__(self, puzzle: list):
self.puzzle = puzzle
self.len = len(puzzle)
if self.len == 3:
self.goal = [[1, 2, 3],
[4, 5, 6],
[7, 8, 0]]
elif self.len == 4:
self.goal = [[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 0]]
if not self.is_valid():
raise TypeError("Puzzle is not valid")
elif not self.is_solvable():
raise Exception("Unsolvable puzzle")
# создай ф-ию check
def sum_of_numbers(self) -> int:
return sum(self.convert_to_1d(self.goal))
def sum_of_squares(self) -> int:
return sum([i ** 2 for i in self.convert_to_1d(self.goal)])
def is_valid(self) -> bool:
sum_of_numbers = 0
sum_of_squares = 0
for row in range(self.len):
for column in range(self.len):
sum_of_numbers += self.puzzle[row][column]
sum_of_squares += (self.puzzle[row][column]) ** 2
return sum_of_numbers == self.sum_of_numbers() and sum_of_squares == self.sum_of_squares()
def convert_to_1d(self, board) -> list:
one_dimension_matrix = []
for row in range(self.len):
for column in range(self.len):
one_dimension_matrix.append(board[row][column])
return one_dimension_matrix
def inversion(self, board) -> int:
inversion = 0
one_dimension_matrix = self.convert_to_1d(board)
for index in range(len(one_dimension_matrix)):
temp = one_dimension_matrix[index]
if temp == 0 or temp == 1:
continue
for elem in one_dimension_matrix[index:]:
if elem == 0:
continue
if temp > elem:
inversion += 1
return inversion
def is_solvable(self) -> bool:
inv_of_matrix = self.inversion(self.puzzle)
inv_of_goal_matrix = self.inversion(self.goal)
return (inv_of_matrix % 2 == 0 and inv_of_goal_matrix % 2 == 0) or \
(inv_of_matrix % 2 == 1 and inv_of_goal_matrix % 2 == 1)
class Puzzle:
def __init__(self, board: list):
self.board = board
self.len = len(board)
if self.len == 3:
self.goal = [[1, 2, 3],
[4, 5, 6],
[7, 8, 0]]
elif self.len == 4:
self.goal = [[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 0]]
def print_matrix(self) -> str:
output = ''
for row in self.board:
for elem in row:
output += str(elem) + " "
output += '\n'
return output
def get_index(self, matrix, value) -> tuple:
for i in range(self.len):
for j in range(self.len):
if matrix[i][j] == value:
return i, j
def manhattan(self):
distance = 0
for i in range(self.len):
for j in range(self.len):
if self.board[i][j] != 0:
x, y = divmod(self.board[i][j] - 1, self.len)
distance += abs(x - i) + abs(y - j)
return distance
def list_of_possible_moves(self) -> list:
x, y = self.get_index(self.board, 0)
possible_moves = []
if x > 0:
possible_moves.append((x - 1, y))
if x < self.len - 1:
possible_moves.append((x + 1, y))
if y > 0:
possible_moves.append((x, y - 1))
if y < self.len - 1:
possible_moves.append((x, y + 1))
return possible_moves
def move(self, to: tuple) -> list:
moving_board = deepcopy(self.board)
x, y = self.get_index(self.board, 0)
i, j = to
moving_board[x][y], moving_board[i][j] = moving_board[i][j], moving_board[x][y]
return moving_board
def solved(self) -> bool:
return self.board == self.goal
def __str__(self) -> str:
return ''.join(map(str, self))
def __iter__(self):
for row in self.board:
yield from row
class Node:
def __init__(self, puzzle, parent=None):
self.puzzle = puzzle
self.parent = parent
if self.parent:
self.g = parent.g + 1
else:
self.g = 0
def state(self) -> str:
return str(self)
def path(self):
node, p = self, []
while node:
p.append(node)
node = node.parent
yield from reversed(p)
def solved(self) -> bool:
return self.puzzle.solved()
def pretty_print(self) -> str:
return self.puzzle.print_matrix()
def h(self) -> int:
return self.puzzle.manhattan()
def f(self) -> int:
return self.h() + self.g
def all_moves(self) -> list:
return self.puzzle.list_of_possible_moves()
def __str__(self) -> str:
return str(self.puzzle)
def make_a_move(self, to: tuple) -> list:
return self.puzzle.move(to)
class GameTree:
def __init__(self, root):
self.root = root
def solve(self):
queue = deque([Node(self.root)])
seen = set()
seen.add(queue[0].state())
while queue:
queue = deque(sorted(list(queue), key=lambda node: node.f()))
node = queue.popleft()
if node.solved():
return node.path()
for move in node.all_moves():
moved = node.make_a_move(move)
child = Node(Puzzle(moved), node)
if child.state() not in seen:
queue.append(child)
seen.add(child.state())
def main():
a = [[5, 4, 3], [0, 7, 2], [6, 1, 8]]
c = Puzzle(a)
d = GameTree(c)
tic = perf_counter()
p = d.solve()
toc = perf_counter()
step = 0
for i in p:
print(i.pretty_print())
step += 1
print(step)
print(toc-tic)
if __name__ == "__main__":
main()
Description:
The 15-puzzle (also called Gem Puzzle, Boss Puzzle, Game of Fifteen,
Mystic Square and many others) is a sliding puzzle that consists of a
frame of numbered square tiles in random order with one tile missing.
The puzzle also exists in other sizes, particularly the smaller
8-puzzle. If the size is 3×3 tiles, the puzzle is called the 8-puzzle
or 9-puzzle, and if 4×4 tiles, the puzzle is called the 15-puzzle or
16-puzzle named, respectively, for the number of tiles and the number
of spaces. The object of the puzzle is to place the tiles in order by
making sliding moves that use the empty space.
https://en.wikipedia.org/wiki/15_puzzle

Yield all full root-leaf paths through tree structure in Python

I'm trying to adapt this answer in two ways:
I want to make the traverse function a class method, and
I want a call to traverse to yield the list of all root-to-leaf paths (list of lists) in the tree
First change was trivial, second one I'm struggling with. Here's my class definition:
class createnode:
""" thanks to https://stackoverflow.com/a/51911296/1870832"""
def __init__(self,nodeid):
self.nodeid=nodeid
self.child=[]
def __str__(self):
print(f"{self.nodeid}")
def traverse(self, path = []):
path.append(self.nodeid)
if len(self.child) == 0:
#print(path)
yield path
path.pop()
else:
for child in self.child:
child.traverse(path)
path.pop()
I construct a tree with:
ROOT_NODE = 0
root = createnode(ROOT_NODE)
lvl1 = [createnode(1), createnode(2), createnode(3)]
root.child += lvl1
root.child[0].child += [createnode(4), createnode(5)]
root.child[1].child += [createnode(6), createnode(7)]
root.child[2].child += [createnode(8), createnode(9)]
Desired output for printing all full root-leaf paths (e.g. w/ code below)
paths = root.traverse()
for p in paths:
print(p)
is:
[0, 1, 4]
[0, 1, 5]
[0, 2, 6]
[0, 2, 7]
[0, 3, 8]
[0, 3, 9]
You need to look into a recursive generator.
I have corrected your setup code:
class createnode:
""" thanks to https://stackoverflow.com/a/51911296/1870832"""
def __init__(self,nodeid):
self.nodeid=nodeid
self.child=[]
def __str__(self):
print(f"{self.nodeid}")
def traverse(self, path = None):
if path is None:
path = []
path.append(self.nodeid)
if len(self.child) == 0:
yield path
path.pop()
else:
for child in self.child:
yield from child.traverse(path)
path.pop()
ROOT_NODE = 0
root = createnode(ROOT_NODE)
children = [createnode(32), createnode(5)]
root.child += children
paths = root.traverse()
for p in paths:
print(p)
Output:
[0, 32]
[0, 5]
I don't have any experience with yield yet but I'd do it like this:
class createnode:
""" thanks to https://stackoverflow.com/a/51911296/1870832"""
def __init__(self,nodeid):
self.nodeid=nodeid
self.child=[]
def __str__(self):
print(f"{self.nodeid}")
def traverse(self, path = []):
path.append(self.nodeid)
if len(self.child) == 0:
print(path)
path.pop()
else:
for child in self.child:
child.traverse(path)
path.pop()
ROOT_NODE = 0
root = createnode(ROOT_NODE)
lvl1 = [createnode(1), createnode(2), createnode(3)]
root.child += lvl1
root.child[0].child += [createnode(4), createnode(5)]
root.child[1].child += [createnode(6), createnode(7)]
root.child[2].child += [createnode(8), createnode(9)]
root.traverse()
[0, 1, 4]
[0, 1, 5]
[0, 2, 6]
[0, 2, 7]
[0, 3, 8]
[0, 3, 9]

Sudoku solver perfomance issues when implemented in a pygame-application

Yesterday I created an sudoku solver using backtracking, which, works like its supposed to without performance issues. I decided to create an pygame application, which you with your mouse and keyboard can fill in the cells, and then press the "solve" button to finish the puzzle. I copy pasted the exact code from the Solver-algorithm to the pygame application (which is found in the Solver-class).
In the pygame application you can fill in cells and solve the puzzle most of the times, so it works as its supposed to. However, on more hard puzzles as the one found below, I encounter CPU issues, causing the application to use all of my CPU and eventually crash (im on a Mac OS. HighS system with I5):
Puzzle from telegraph
To sum up my problem:
The sudoku solver algorithm works fine when not called from within the pygame application, (the telegraph puzzle is solved in 2.s roughly), but when called from within the pygame application, it can solve easy puzzles, but the harder ones causes the application to crash due to overuse of CPU.
Heres a picture of the initial setup that causes the crash:
Code is found below:
class Sudoku():
def __init__(self):
self.W,self.H = (600,600)
pygame.init()
pygame.mixer.quit()
self.screen = pygame.display.set_mode((self.W+200,self.H))
self.clock = pygame.time.Clock()
self.board = Board()
self.focused = None
self.solve = Button((0,140,0),650,200,100,50,"Solve")
self.solver = Solver(self.board.sudoku)
self.run()
### Takes care of pygame events from mouse and keyboard
def events(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.quit()
if event.type == pygame.MOUSEBUTTONUP:
self.focused = self.getCellFromMousePos(pygame.mouse.get_pos())
if self.solve.isOver(pygame.mouse.get_pos()):
self.solver.solve()
if event.type == pygame.KEYDOWN:
print("key")
if self.focused!=None:
try:
self.board.set_value(self.focused[0],self.focused[1],int(event.unicode))
except:
pass
## Calls paint functions from working units (button, board)
def paint(self):
self.screen.fill((255,229,204))
self.board.paint(self.screen,self.W,self.H)
self.solve.draw(self.screen)
pygame.display.flip()
## Main loop
def run(self):
self.running = True
while self.running:
self.dt = self.clock.tick(60)/1000
self.update()
## Update called from main loop
def update(self):
self.events()
self.paint()
## Set value on board (Unused)
def set_value(self,row,col,value):
self.board.set_value(row,col,value)
## Get a cell (0-9,0-9) from the mouse position.
def getCellFromMousePos(self,coord):
return (math.floor(coord[0]/(self.W/9)),math.floor(coord[1]/(self.H/9)))
class Board():
def __init__(self):
self.sudoku = [ [0]*9 for _ in range(9) ]
self.font = pygame.font.SysFont('comicsans',81)
## Takes a preset board as input - NOT USED
def set_preset(self,board):
if len(board)==9 and len(board[1])==9:
for row in board:
for cell in row:
if board[row][cell]>9 or board[row][cell]<0:
return None
self.sudoku = board
## Sets value in a cell
def set_value(self,row,col,value):
if self.value_is_valid(value):
self.sudoku[row][col] = value
## Check if an value is valid
def value_is_valid(self,value):
if int(value)<=9 and int(value)>=0:
return True
return False
## Paints grid and numbers to pygame.screen
def paint(self,screen,width,height):
## DRAW background board itself:
for row in range(10):
k = row*(height/9)
pygame.draw.line(screen,(0,0,0),(0,k),(width,k))
for col in range(10):
k = col*(width/9)
pygame.draw.line(screen,(0,0,0),(k,0),(k,height))
## Draw numbers:
for r in range(9):
for c in range(9):
value = self.sudoku[r][c]
if value != 0:
text = self.font.render(str(value),2,(0,0,0))
screen.blit(text,((width/9)*r+(text.get_width()/2),(height/9)*c))
## Just a button.
class Button:
def __init__(self,color,x,y,width,heigth,text):
self.x = x
self.y = y
self.width = width
self.heigth = heigth
self.text = text
self.color = color
def draw(self,window):
pygame.draw.rect(window,self.color,(self.x,self.y,self.width,self.heigth))
if self.text!="":
font = pygame.font.SysFont('comicsans',61)
text = font.render(self.text,2,(0,0,0))
window.blit(text,(self.x+(self.width/2 - text.get_width()/2), self.y + (self.heigth/2 -text.get_height()/2)))
def isOver(self,pos):
if pos[0] > self.x and pos[0]< (self.x+self.width):
if pos[1]> self.y and pos[1]< self.y+self.heigth:
return True
return False
## Solving algorithm
class Solver:
def __init__(self,board):
self.sudoku = board
def valid(self,row,column,value):
original = self.sudoku[row][column]
self.sudoku[row][column] = value
validity = self.duplicates()
self.sudoku[row][column] = original
return not validity
## Checks if an array contains duplicates
def arrayContainsDuplicates(self,array):
if len(array) == len(set(array)):
return False
return True
## Trims an array from empty spaces (0's)
def trimarray(self,array):
trimmed = []
for cell in array:
if cell != 0:
trimmed.append(cell)
return trimmed
## Finds the next empty cell. Used for backtracking.
def find_empty(self):
for i in range(len(self.sudoku)):
for j in range(len(self.sudoku[i])):
if self.sudoku[i][j] == 0:
return (i,j)
return None
## Checks if the board contains any duplicates in rows, blocks and columns.
def duplicates(self):
for row in self.sudoku:
if self.arrayContainsDuplicates(self.trimarray(row)):
return True
for col in map(list,zip(*self.sudoku)):
if self.arrayContainsDuplicates(self.trimarray(col)):
return True
blocks=[[self.sudoku[int(m//3)*3+i][(m%3)*3+j] for i in range(3) for j in range(3)] for m in range(9)]
for block in blocks:
if self.arrayContainsDuplicates(self.trimarray(block)):
return True
return False
## Backtrakcing solving algorithm.
def solve(self):
find = self.find_empty()
if not find:
return True
else:
row,col = find
for i in range(1,10):
if self.valid(row,col,i):
self.sudoku[row][col] = i
if self.solve():
return True
else:
self.sudoku[row][col] = 0
s = Sudoku()
Try this solver:
known = [ [8,0,0, 0,0,0, 0,0,0],
[0,0,3, 6,0,0, 0,0,0],
[0,7,0, 0,9,0, 2,0,0],
[0,5,0, 0,0,7, 0,0,0],
[0,0,0, 0,4,5, 6,0,0],
[0,0,0, 1,0,0, 0,3,0],
[0,0,1, 0,0,0, 0,6,8],
[0,0,8, 5,0,0, 0,1,0],
[0,9,0, 0,0,0, 4,0,0]
]
import random
groups = [ p//27*3+p%9//3 for p in range(81) ]
colNums = [ set(range(1,10)) for _ in range(9) ]
rowNums = [ set(range(1,10)) for _ in range(9) ]
grpNums = [ set(range(1,10)) for _ in range(9) ]
sudoku = [ [0]*9 for _ in range(9) ]
for pos in range(81):
row,col,group = pos//9,pos%9,groups[pos]
fixed = known[row][col]
if fixed:
sudoku[row][col] = fixed
colNums[col].discard(fixed)
rowNums[row].discard(fixed)
grpNums[group].discard(fixed)
pos = 0
availables = [ None for _ in range(81)]
while pos < 81:
row,col,group = pos//9,pos%9,groups[pos]
number = sudoku[row][col]
fixed = known[row][col]
if number != 0 and not fixed:
sudoku[row][col] = 0
colNums[col].add(number)
rowNums[row].add(number)
grpNums[group].add(number)
if availables[pos] is None:
availables[pos] = {fixed} if fixed else colNums[col] & rowNums[row] & grpNums[group]
if availables[pos]:
number = fixed or min(availables[pos])
if not fixed:
sudoku[row][col] = number
colNums[col].discard(number)
rowNums[row].discard(number)
grpNums[group].discard(number)
availables[pos].discard(number)
pos += 1
else:
availables[pos] = None
pos -= 1
if pos < 0 : break
if pos < 81:
print("FAILED!")
else :
for r,line in enumerate(sudoku):
print(*[line[i:][:3] for i in range(0,9,3)],"\n"*(r%3==2))
It finds a solution in 0.15 sec (excluding printing time):
[8, 4, 9] [2, 7, 1] [3, 5, 6]
[2, 1, 3] [6, 5, 4] [8, 7, 9]
[6, 7, 5] [8, 9, 3] [2, 4, 1]
[3, 5, 2] [9, 6, 7] [1, 8, 4]
[1, 8, 7] [3, 4, 5] [6, 9, 2]
[9, 6, 4] [1, 8, 2] [7, 3, 5]
[7, 2, 1] [4, 3, 9] [5, 6, 8]
[4, 3, 8] [5, 2, 6] [9, 1, 7]
[5, 9, 6] [7, 1, 8] [4, 2, 3]
Note: it will take up to 4 seconds to figure out that there are no solution if the case may be. This means that the worst case scenario for an extremely complex problem would be less than 4 seconds. The world's supposedly hardest was solved in 0.11 seconds )

variables for different objects of same type made in constructor all referencing the same object

this is my first time posting here and also I'm new to Python,so please be patient with me if I'm something wrong! I've seen a similar question to this but couldn't see a clear solution. This must have a simple solution but it has frustrated me all day.
I'm trying to make multiple objects of the class 'Slot' inside the constructor
of the class 'Board'. After each object is made, I'm appending it to a list.
Finally I'm going through each object in list and calling 'getHandles' method, which should
output their unique results. Instead the results of last slot object made are displayed.
Board class constructor :
class Board:
slots = []
def __init__(self):
slot1 = Slot(1); self.slots.append(slot1);
slot2 = Slot(2); self.slots.append(slot2);
slot3 = Slot(3); self.slots.append(slot3);
slot4 = Slot(4); self.slots.append(slot4);
slot5 = Slot(5); self.slots.append(slot5);
slot6 = Slot(6); self.slots.append(slot6);
slot7 = Slot(7); self.slots.append(slot7);
slot8 = Slot(8); self.slots.append(slot8);
slot9 = Slot(9); self.slots.append(slot9);
print("\nprinting slot objects in list 'slot'\n");
counter = 0;
while counter < len(self.slots):
print("slot number :"+str(self.slots[counter].getPosition()));
print("slot value :"+str(self.slots[counter].getHandles()));
counter +=1;
slot class constructor :
#Slot class constructor
def __init__(self,n):
self.setPosition(n);
positions = coords.getLargeGridPosition(n);
self.U[2] = positions[1]; self.D[2] = positions[2];
self.L[2] = positions[3]; self.R[2] = positions[4];
print("made slot object : "+str(self.getPosition()));
print("handle values: ");
self.getHandles();
print(" - ");
def getHandles(self):
print(" U:"+str(self.U)+" D:"+str(self.D)+" L:"+str(self.L)+" R:"+str(self.R));
This is what I get when I make a 'Board' object :
1st part out output (making slots and appending in Board constructor):
>>> b = Board()
made slot object : 1
handle values:
U:[1, 2, 2] D:[2, 1, 20] L:[3, 4, 10] R:[4, 3, 12]
-
made slot object : 2
handle values:
U:[1, 2, 5] D:[2, 1, 23] L:[3, 4, 13] R:[4, 3, 15]
-
made slot object : 3
handle values:
U:[1, 2, 8] D:[2, 1, 26] L:[3, 4, 16] R:[4, 3, 18]
-
made slot object : 4
handle values:
U:[1, 2, 29] D:[2, 1, 47] L:[3, 4, 37] R:[4, 3, 39]
-
and so on for all nine objects.
2nd part out output (calling getHandle method for each object in list) :
printing slot objects in list 'slot'
slot number :1
U:[1, 2, 62] D:[2, 1, 80] L:[3, 4, 70] R:[4, 3, 72]
slot value :None
slot number :2
U:[1, 2, 62] D:[2, 1, 80] L:[3, 4, 70] R:[4, 3, 72]
slot value :None
slot number :3
U:[1, 2, 62] D:[2, 1, 80] L:[3, 4, 70] R:[4, 3, 72]
slot value :None
slot number :4
U:[1, 2, 62] D:[2, 1, 80] L:[3, 4, 70] R:[4, 3, 72]
slot value :None
slot number :5
U:[1, 2, 62] D:[2, 1, 80] L:[3, 4, 70] R:[4, 3, 72]
and so on for all 9 objects appended to list. How can I make the variables slot1/slot2
refer to individual objects made?
I've tried passing the board object to slot constructor, and making slot constructor pass 'self' back to Board object. still the results for a single object are outputted for all.
I'd appreciate any help. Thank you.
[edit] full code of the file : hope the indenting comes out right
import coords;
#store hanndle position values
class Slot: #slot class<------------------------------------------------
U = [1,2,"gridPosition"] #1 up
D = [2,1,"gridPosition"] #2 down
L = [3,4,"gridPosition"] #3 left
R = [4,3,"gridPosition"] #4 right
handles = [U,D,L,R] #handles 0/1/2/3
tileValue = 0; #value 0 - 8
tilePosition = 0; #slot 1 - 9
overallStrain = 0; # |0-->+
#Slot class constructor
def __init__(self,n):
self.setPosition(n);
positions = coords.getLargeGridPosition(n);
self.U[2] = positions[1]; self.D[2] = positions[2];
self.L[2] = positions[3]; self.R[2] = positions[4];
print("made slot object : "+str(self.getPosition()));
print("handle values: ");
self.getHandles();
print(" - ");
def getHandles(self):
print(" U:"+str(self.U)+" D:"+str(self.D)+" L:"+str(self.L)+" R:"+str(self.R));
#set/get position of slot(1-9)
def setPosition(self,position):
self.tilePosition = position;
def getPosition(self):
return self.tilePosition;
#set/get tile value
def setTileValue(self,value):
self.TileValue = value;
def getTileValue(self):
return self.TileValue;
#get handle(n) position value
def getHandle(self,number):
return self.handles[number]
#get overall strain of tile
def getTotalStrain(self):
return self.totalStrain;
#calculate total strain from strains of handles
#def calculateOverallStrain(self):#<---------------
#for handle in handles:
#if
#get linked tile,
class Board: #Boardclass<------------------------------------------------
slots = []
def __init__(self):
slot1 = Slot(1); self.slots.append(slot1);
slot2 = Slot(2); self.slots.append(slot2);
slot3 = Slot(3); self.slots.append(slot3);
slot4 = Slot(4); self.slots.append(slot4);
slot5 = Slot(5); self.slots.append(slot5);
slot6 = Slot(6); self.slots.append(slot6);
slot7 = Slot(7); self.slots.append(slot7);
slot8 = Slot(8); self.slots.append(slot8);
slot9 = Slot(9); self.slots.append(slot9);
print("\nprinting slot objects in list 'slot'\n");
counter = 0;
while counter < len(self.slots):
print("slot number :"+str(self.slots[counter].getPosition()));
print("slot value :"+str(self.slots[counter].getHandles()));
counter +=1;
#set tiles
def setTiles(self,state):
counter = 0;
for slot in self.slots:
slot.setTileValue(state[counter]);
counter +=1;
def getStrain(self,slot):
tileValue = self.slots[slot].getTileValue();
print("tile value:"+str(tileValue));
print("handles:");
self.slots[slot].getHandles();
if tileValue != 0:
linkedTiles = coords.getLinked(tileValue);
print(str(linkedTiles));
counter = 0;
for l in linkedTiles:#for each linked tile
if l != 0: #if not empty link
linkedTileSlot = [];#slot linked tile is set in
for slot in self.slots:
linkedTileValue = slot.getTileValue();
print(str(linkedTileValue));
if l == linkedTileValue:#found slot with linked tile
print("yes");
linkedTileSlot = slot; break;
ownHandle = slot.getHandle(counter);
print("own handle : "+str(ownHandle));
linkingHandle = linkedTileSlot.getHandle(ownHandle[1]-1);
print("linking handle : "+str(linkingHandle));
positions = [ownHandle[2],linkingHandle[2]]
print(str(positions));
counter += 1;
As Pavel says in the comments, anything defined at the class level is a class variable, shared between all instances. You need to define those variables within __init__ by assigning them to self:
class Slot: #slot class<------------------------------------------------
def __init__(self,n):
self.U = [1,2,"gridPosition"] #1 up
self.D = [2,1,"gridPosition"] #2 down
self.L = [3,4,"gridPosition"] #3 left
self.R = [4,3,"gridPosition"] #4 right
self.handles = [U,D,L,R] #handles 0/1/2/3
self.tileValue = 0; #value 0 - 8
self.tilePosition = 0; #slot 1 - 9
self.overallStrain = 0; # |0-->+
You should also know that there are quite a few examples of extremely unidiomatic Python here. For example, the entire Board init should simply be:
def __init__(self):
self.slots = [Slot(i+1) for i in range(10)]
print("\nprinting slot objects in list 'slot'\n");
for slot in self.slots:
print("slot number :%s" % slot.getPosition());
print("slot value :%d" slot.getHandles());
Also, it's discouraged to define getters and setters unless there is a very good reason, which you don't have here since you're just accessing the variable. You should assign to and return self.position and so on.

Categories