Trouble implementing a flood fill algorithm in python - python

I am rather new to python and am attempting to create a terminal based minesweeper clone. Everything has been going well other than implementing the flood fill algorithm. Whenever I run the flood fill it just gets stuck looping indefinitely. If anyone could help with this it would be greatly appreciated.
import random
from queue import Queue
'⚑'
fieldY = 10
fieldX = 5
validFloodFills = ['1','2','3','4','5','6','7','8','◼']
visibleField = []
internalField = []
#creates blank fields with the ◼ character
def generateField(grid, y , x):
for i in range(y):
tempList = []
for i in range(x):
tempList.append("◼")
grid.append(tempList)
#places bombs into the internal field according to the numOfBombs argument
def placeBombs(numOfBombs):
generateField(internalField, fieldY, fieldX)
placed = 0
#while loop is use becuase you cannot step an iter back with a for loop
while placed != numOfBombs:
y = random.randint(0, fieldY-1)
x = random.randint(0, fieldX-1)
if internalField[y][x] == 'X':
continue
else:
internalField[y][x] = 'X'
placed += 1
#loops through all tiles and numbers them according to the number of adjacent bombs
def placeInternalNumbers():
global fieldY
global fieldX
#loop through all tiles and check all 8 neighbours
#if neighbour is a bomb then add 1 to int
#after checking all neighbours the value of that int is assigned to that tile
for idxY, y in enumerate(internalField):
for idxX, x in enumerate(y):
#makes indexes in range
fieldY -= 1
fieldX -= 1
idxY -= 1
idxX -= 1
adjacentBomb = 0
if internalField[idxY][idxX] == 'X':
continue
#look down one
if idxY != fieldY:
if internalField[idxY+1][idxX] == 'X':
adjacentBomb += 1
#look up one
if idxY != 0:
if internalField[idxY-1][idxX] == 'X':
adjacentBomb += 1
#look right one
if idxX != fieldX:
if internalField[idxY][idxX+1] == 'X':
adjacentBomb += 1
#look left one
if idxX != 0:
if internalField[idxY][idxX-1] == 'X':
adjacentBomb += 1
#look down right
if idxY != fieldY and idxX != fieldX:
if internalField[idxY+1][idxX+1] == 'X':
adjacentBomb += 1
#look down left
if idxY != fieldY and idxX != 0:
if internalField[idxY+1][idxX-1] == 'X':
adjacentBomb += 1
#look up right
if idxY != 0 and idxX != fieldX:
if internalField[idxY-1][idxX+1] == 'X':
adjacentBomb += 1
#look up left
if idxY != 0 and idxX != 0:
if internalField[idxY-1][idxX-1] == 'X':
adjacentBomb += 1
#checks if the adjacent bombs are zero and does not update the tile if there are no adjacent bombs
if adjacentBomb == 0:
continue
internalField[idxY][idxX] = str(adjacentBomb)
#prints the field parsed to the function
def printField(field):
for i in field:
print(i)
#floodFill
def floodFill(y, x):
#TODO needs to read and compare with the internal board and then write changes to the visible board
n = len(visibleField)
m = len(visibleField[0])
if y < 0 or y >= n or x < 0 or x >= m or internalField[y][x] not in validFloodFills:
return
else:
visibleField[y][x] = internalField[y][x]
floodFill(y+1, x)
floodFill(y-1, x)
floodFill(y, x+1)
floodFill(y, x-1)
#main loop
def mainLoop():
cont = True
while cont:
printField(visibleField)
print()
printField(internalField)
print("To select a tile type 'S' then the x coordinate and y coordinate all seperated by spaces\nTo flag a tile type 'F' then the x coordinate and y coordinate all seperated by spaces")
select = input().split(' ') #TODO input validation, use length to check for multiple spaces
operator = select[0]
x = int(select[1])
y = int(select[2])
if operator == 'S':
if internalField[y][x] == 'X':
break
else:
floodFill(y, x)
continue
elif operator == 'F':
pass
#TODO more stuff on fail eg printing revealed minefield
print("You hit a bomb, better luck next time")
generateField(visibleField, fieldY, fieldX)
placeBombs(5)
placeInternalNumbers()
mainLoop()
printField(visibleField)
print()
printField(internalField)

Related

how to select a value referring to the last repeated item in a list

I have 5 columns ( NO = index of vehicle / LEADER = index of the vehicle of the front / SEC = instant in seconds / X = position of the vehicle)
Some vehicles stop ( X stay the same for a while) and I want to get the exact time it starts to move again. Then, calculate the difference between their instant and their respective 'leader' vehicle.
I made a code but it has so many bugs
OBS: Some vehicles never stop or stop,but never return to move. I want to remove them too.
Here's my code:
dados = pd.read_excel('teste-reaction_001.xlsx')
n=dados["NO"].unique()
final=np.zeros(1)
for i in n:
botao = 0
array_aux=dados[dados["NO"] == i ]["X"]
df = pd.DataFrame(array_aux)
aux=df.diff().to_numpy()
count1 = 0
aux1 = []
for j in aux:
if j == 0:
botao = 1
elif j != 0 and botao == 1:
aux1=np.where(aux==j)[0]
aux1=aux1[np.where(aux1>=count1)[0]]
break
else :
botao = 0
count1 = count1 + 1
aux2=dados["SEC"][dados[dados["NO"]==i]["SEC"].index[aux1]].values[0]
final=np.append(final,aux2)
tr=np.zeros(1)
for i in n:
aux=dados[dados["NO"] == i ]["LEADER"].unique()[0]
aux1=np.where(dados["NO"].unique()==i)[0]
aux2=np.where(dados["NO"].unique()==aux)[0]
if aux2>-1:
aux3=final[int(aux1)]-final[aux2]
else:
aux3 = "s"
tr=np.append(tr,aux3)
columns = ["N", "TR"]
tabela = np.array([dados["NO"].unique(), tr[1:]])
res = pd.DataFrame(data=tabela.T,index=np.arange(len(tabela.T)), columns=columns)

My A-star implementation seems very slow, need advice and help on what I am doing wrong

My tests of my implementations of Dijkstra and A-Star have revealed that my A-star implementation is approximately 2 times SLOWER. Usually equivalent implementations of Dijkstra and A-star should see A-star beating out Dijkstra. But that isn't the case here and so it has led me to question my implementation of A-star. So I want someone to tell me what I am doing wrong in my implementation of A-star.
Here is my code:
from copy import deepcopy
from math import inf, sqrt
import maze_builderV2 as mb
if __name__ == '__main__':
order = 10
space = ['X']+['_' for x in range(order)]+['X']
maze = [deepcopy(space) for x in range(order)]
maze.append(['X' for x in range(order+2)])
maze.insert(0, ['X' for x in range(order+2)])
finalpos = (order, order)
pos = (1, 1)
maze[pos[0]][pos[1]] = 'S' # Initializing a start position
maze[finalpos[0]][finalpos[1]] = 'O' # Initializing a end position
mb.mazebuilder(maze=maze)
def spit():
for x in maze:
print(x)
spit()
print()
mazemap = {}
def scan(): # Converts raw map/maze into a suitable datastructure.
for x in range(1, order+1):
for y in range(1, order+1):
mazemap[(x, y)] = {}
t = [(x-1, y), (x+1, y), (x, y-1), (x, y+1)]
for z in t:
if maze[z[0]][z[1]] == 'X':
pass
else:
mazemap[(x, y)][z] = [sqrt((pos[0]-z[0])**2+(pos[1]-z[1])**2),
sqrt((finalpos[0]-z[0])**2+(finalpos[1]-z[1])**2)] # Euclidean distance to destination (Heuristic)
scan()
unvisited = deepcopy(mazemap)
distances = {}
paths = {}
# Initialization of distances:
for node in unvisited:
if node == pos:
distances[node] = [0, sqrt((finalpos[0]-node[0])**2+(finalpos[1]-node[1])**2)]
else:
distances[node] = [inf, inf]
while unvisited != {}:
curnode = None
for node in unvisited:
if curnode == None:
curnode = node
elif (distances[node][0]+distances[node][1]) < (distances[curnode][0]+distances[curnode][1]):
curnode = node
else:
pass
for childnode, lengths in mazemap[curnode].items():
# Length to nearby childnode - G length, Euclidean (Heuristic) length from curnode to finalpos - H length
# G length + H length < Euclidean length to reach that childnode directly + Euclidean length to finalpos from that childnode = Better path found, update known distance and paths
if lengths[0] + lengths[1] < distances[childnode][0] + distances[childnode][1]:
distances[childnode] = [lengths[0], lengths[1]]
paths[childnode] = curnode
unvisited.pop(curnode)
def shortestroute(paths, start, end):
shortestpath = []
try:
def rec(start, end):
if end == start:
shortestpath.append(end)
return shortestpath[::-1]
else:
shortestpath.append(end)
return rec(start, paths[end])
return rec(start, end)
except KeyError:
return False
finalpath = shortestroute(paths, pos, finalpos)
if finalpath:
for x in finalpath:
if x == pos or x == finalpos:
pass
else:
maze[x[0]][x[1]] = 'W'
else:
print("This maze not solvable, Blyat!")
print()
spit()
For those who find my code too messy and can't bother to read the comments I added to help with the reading... Here is a gist of my code:
Creates a mazemap (all the coordinates and its connected neighbors along with their euclidean distances from that neighboring point to the start position (G Cost) as well as to the final position (H Cost)... in a dictionary)
start position is selected as the current node. All distances to other nodes is initialised as infinity.
For every node we compare the total path cost i.e is the G cost + H cost. The one with least total cost is selected as then next current node. Each time we select new current node, we add that node to a dictionary that keeps track of through which node it was reached, so that it is easier to backtrack and find our path.
Process continues until current node is the final position.
If anyone can help me out on this, that would be great!
EDIT: On account of people asking for the maze building algorithm, here it is:
# Maze generator - v2: Generates mazes that look like city streets (more or less...)
from copy import deepcopy
from random import randint, choice
if __name__ == "__main__":
order = 10
space = ['X']+['_' for x in range(order)]+['X']
maze = [deepcopy(space) for x in range(order)]
maze.append(['X' for x in range(order+2)])
maze.insert(0, ['X' for x in range(order+2)])
pos = (1, 1)
finalpos = (order, order)
maze[pos[0]][pos[1]] = 'S' # Initializing a start position
maze[finalpos[1]][finalpos[1]] = 'O' # Initializing a end position
def spit():
for x in maze:
print(x)
blocks = []
freespaces = [(x, y) for x in range(1, order+1) for y in range(1, order+1)]
def blockbuilder(kind):
param1 = param2 = 0
double = randint(0, 1)
if kind == 0:
param2 = randint(3, 5)
if double:
param1 = 2
else:
param1 = 1
else:
param1 = randint(3, 5)
if double:
param2 = 2
else:
param2 = 1
for a in range(blockstarter[0], blockstarter[0]+param2):
for b in range(blockstarter[1], blockstarter[1]+param1):
if (a+1, b) in blocks or (a-1, b) in blocks or (a, b+1) in blocks or (a, b-1) in blocks or (a, b) in blocks or (a+1, b+1) in blocks or (a-1, b+1) in blocks or (a+1, b-1) in blocks or (a-1, b-1) in blocks:
pass
else:
if a > order+1 or b > order+1:
pass
else:
if maze[a][b] == 'X':
blocks.append((a, b))
else:
spaces = [(a+1, b), (a-1, b), (a, b+1), (a, b-1)]
for c in spaces:
if maze[c[0]][c[1]] == 'X':
break
else:
maze[a][b] = 'X'
blocks.append((a, b))
for x in range(1, order+1):
for y in range(1, order+1):
if (x, y) in freespaces:
t = [(x+1, y), (x-1, y), (x, y+1), (x, y-1)]
i = 0
while i < len(t):
if maze[t[i][0]][t[i][1]] == 'X' or (t[i][0], t[i][1]) == pos or (t[i][0], t[i][1]) == finalpos:
del t[i]
else:
i += 1
if len(t) > 2:
blockstarter = t[randint(0, len(t)-1)]
kind = randint(0, 1) # 0 - vertical, 1 - horizontal
blockbuilder(kind)
else:
pass
# rch = choice(['d', 'u', 'r', 'l'])
b = 0
while b < len(blocks):
block = blocks[b]
t = {'d': (block[0]+2, block[1]), 'u': (block[0]-2, block[1]),
'r': (block[0], block[1]+2), 'l': (block[0], block[1]-2)}
rch = choice(['d', 'u', 'r', 'l'])
z = t[rch]
# if z[0] > order+1 or z[1] > order+1 or z[0] < 1 or z[1] < 1:
# Decreased chance of having non solvable maze being generated...
if z[0] > order-2 or z[1] > order-2 or z[0] < 2+2 or z[1] < 2+2:
pass
else:
if maze[z[0]][z[1]] == 'X':
if randint(0, 1):
set = None
if rch == 'u':
set = (z[0]+1, z[1])
elif rch == 'd':
set = (z[0]-1, z[1])
elif rch == 'r':
set = (z[0], z[1]-1)
elif rch == 'l':
set = (z[0], z[1]+1)
else:
pass
if maze[set[0]][set[1]] == '_':
# Checks so that no walls that block the entire way are formed
# Makes sure maze is solvable
sets, count = [
(set[0]+1, set[1]), (set[0]-1, set[1]), (set[0], set[1]+1), (set[0], set[1]-1)], 0
for blyat in sets:
while blyat[0] != 0 and blyat[1] != 0 and blyat[0] != order+1 and blyat[1] != order+1:
ch = [(blyat[0]+1, blyat[1]), (blyat[0]-1, blyat[1]),
(blyat[0], blyat[1]+1), (blyat[0], blyat[1]-1)]
suka = []
for i in ch:
if ch not in suka:
if maze[i[0]][i[1]] == 'X':
blyat = i
break
else:
pass
suka.append(ch)
else:
pass
else:
blyat = None
if blyat == None:
break
else:
pass
else:
count += 1
if count < 1:
maze[set[0]][set[1]] = 'X'
blocks.append(set)
else:
pass
else:
pass
else:
pass
b += 1
mazebuilder(maze, order)
spit()
Sorry for leaving this out!
Just at a quick glance, it looks like you don't have a closed set at all?? Your unvisited structure appears to contain every node in the map. This algorithm is not A* at all.
Once you fix that, make sure to change unvisited from a list to a priority queue also.

How to move my character on my generated board?

A few days ago a started making my simple board game. First of all, I generate a board for the game. It looks like this:
the gameboard generated for 13x13
Secondly, I place my character on the board, which is 'A':
The player placed
I made a dice for it which generates numbers from 1 to 6.
My goal right now is to get the 'A' character moving around by the dice on the '*' symbols, until it gets at the top left corner:
I need to get here by the dice
So here is my code that I tried:
import math
import random
import os
board= []
def generator(boardsize):
for row in range(boardsize+1):
brow = []
for column in range(boardsize+1):
if row == column == 0:
brow.append(' ')
elif row==0:
brow.append(str(column-1)[-1])
elif column==0:
brow.append(str(row-1)[-1])
elif ((math.ceil(boardsize/2)-1 )<= column) and(column <= (math.ceil(boardsize/2)+1)) or ((math.ceil(boardsize/2)-1 )<= row) and(row <= (math.ceil(boardsize/2)+1)):
if row == 1 or column == 1 or row == boardsize or column == boardsize:
brow.append('*')
else:
if row == (math.ceil(boardsize/2)) and column == (math.ceil(boardsize/2)):
brow.append('X')
elif row == (math.ceil(boardsize/2)) or column == (math.ceil(boardsize/2)):
brow.append('D')
else:
brow.append('*')
else:
brow.append(' ')
board.append(brow)
return board
def print_table(x):
os.system('cls')
for x in board:
print(' '.join(x))
number_from_dice= []
def dice():
min = 1
max = 6
x = random.randint(min, max)
number_from_dice[:]= [x]
return number_from_dice
def player1(x):
generator(x)
prev_char_y = 1
prev_char_x = math.ceil(x/2)+1
char_y= 1
char_x= math.ceil(x/2)+1
board[char_y][char_x] = "A"
print_table(x)
dice()
f = number_from_dice[0]
for i in range(f):
if(char_y<x):
if (board[char_y+1][char_x]) == '*':
char_y= char_y +1
board[char_y][char_x] = "A"
board[prev_char_y][prev_char_x] = '*'
prev_char_x = char_x
prev_char_y = char_y
print_table(x)
else:
if(char_x!=x):
char_x2 = char_x
if (board[char_y][char_x+1]=='*'):
char_x = char_x +1
board[char_y][char_x] = "A"
board[prev_char_y][prev_char_x] = '*'
prev_char_x = char_x
prev_char_y = char_y
print_table(x)
else:
if (board[char_y+1][char_x]) == '*':
char_y= char_y +1
board[char_y][char_x] = "A"
board[prev_char_y][prev_char_x] = '*'
prev_char_x = char_x
prev_char_y = char_y
print_table(x)
else:
if (board[char_y][char_x2-1]) == '*':
char_x2 = char_x2 -1
board[char_y][char_x2] = "A"
board[prev_char_y][prev_char_x] = '*'
prev_char_x = char_x2
prev_char_y = char_y
print_table(x)
else:
if (board[char_y+1][char_x2]) == '*':
char_y = char_y +1
board[char_y][char_x2] = "A"
board[prev_char_y][prev_char_x] = '*'
prev_char_x = char_x2
prev_char_y = char_y
print_table(x)
print('Number from dice: ', end='')
print(f)
player1(13)
Does the technic I used have potential? Or is it too complicated? How would you do it?
Just in a generic sense you've made it overly complicated.
Consider this - the board, as far as movement is concerned, is just a set of ordered spaces.
But right now you have information about how the board is created as part of the player code.
Best to separate this, and you will find that things get simpler.
Instead, have the player simply track it's progress, in other words, what numbered space is it on.
Then you can generate the board and, knowing the space numbers, you can see if it matches the player location.
And then take it one step further (and simpler still) and just draw the board on a 2D array, and then output that, instead of trying to figure out the board as you go line-by-line.

brainfuck intepreter printing out wrong

I recently decided to try to code "yet another" brainfuck interpreter, but I have a problem. It prints out the wrong numbers, when it should put our hello,world!. Does anyone know why this is happening? Thanks in advance! I cannot figure out why it's doing this. Please help! I am only a beginner. Sorry for the bad coding style, but please don't change the whole thing. I would rather recieve tips.
from copy import copy
import sys
def brainfuckintepreter(program):
# find pairs of brackets
brackets = {}
bbrackets = {}
def findmatchingclosingbracket(ctr):
level = 0
if program[ctr] == '[':
while True:
if program[ctr] == '[':
level += 1
elif program[ctr] == ']':
level -= 1
if level == 0:
return ctr
break
ctr += 1
def findmatchingopeningbracket(ctr):
level = 0
if program[ctr] == ']':
while True:
if program[ctr] == '[':
level -= 1
elif program[ctr] == ']':
level += 1
if level == 0:
return ctr
break
ctr -= 1
"""
ctr = 0
for a in program:
if a == '[':
f = copy(findmatchingclosingbracket(ctr))
brackets[ctr] = f
bbrackets[f] = ctr
ctr += 1
print(brackets)
print(bbrackets)
"""
# running the program
tape = [0] * 3000
pointer = 1500
counter = 0
results = ""
valid = True
while counter != len(program) and valid:
a = program[counter]
# move right
if a == '>':
if pointer == len(tape) - 1:
tape.append(0)
pointer += 1
# move left
elif a == '<':
if pointer == 0:
raise ValueError("On index ", counter, ", the program tried to move to -1 on the tape")
valid = False
return valid
else:
pointer -= 1
# increment
elif a == '+':
if tape[pointer] == 255:
tape[pointer] = 0
else:
tape[pointer] += 1
# decrement
elif a == '-':
if tape[pointer] == 0:
tape[pointer] = 255
else:
tape[pointer] -= 1
# output character
elif a == '.':
t = chr(tape[pointer])
results += t
print(t, end='')
# input character
elif a == ',':
tape[pointer] = ord(sys.stdin.read(1))
# opening bracket
elif a == '[':
if tape[pointer] == 0:
pointer = findmatchingclosingbracket(pointer)
# closing bracket
elif a == ']':
if tape[pointer] != 0:
pointer = findmatchingopeningbracket(counter)
counter += 1
"""
for b in tape:
if b != 0:
print(b)
"""
brainfuckintepreter('++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.')
Edit:
I changed my code after some revisions, but same problem.
Your loops are the problem.
level = 0
while level > 0:
...
That loop will never be entered. The condition is immediately false (you're setting level to 0, right before checking if it is greater than 0).
You could change that to a do..while loop instead of a while loop (make a while true loop and check the condition at the end to decide whether to break out of the loop or not) and start checking at the current pointer position (include the current [ or ]), not at the next character after it.
Also here:
if tape[pointer] == 0:
pointer = findmatchingclosingbracket(pointer)
you should be passing and updating the program counter, not the tape pointer on the second line. And likewise for the other one just below it.

Python text game - Cant exit a while loop

this is the main code:
import MainMod
print("Welcome!")
print("Note: In this games you use wasd+enter to move!\nYou press 1 key and then enter,if you press multiple kets it wont work.\nYou will always move by 5 meters.")
CurrentRoom = 1
#Limits work this way!1st and 2nd number are X values(1st is <---- limit,2nd is ---> limit)
#3rd and 4th are y values(1st is v limit,2nd is ^ limit)
# X and Y are coordinates; 0,0 is the starting point of every room
while True:
if CurrentRoom ==1:
print("This is room 1")
MainMod.roomlimits = [-15 , 15, -15 , 15]
MainMod.doorloc1 = [-15,10,15]
MainMod.doorloc2 = [15,-2,2]
while CurrentRoom == 1:
MainMod.MainLel()
if MainMod.door1 == 1:
print("DAMN SON")
CurrentRoom = 2
break
elif MainMod.door2 == 1:
print("Plz no")
CurrentRoom = 3
break
while CurrentRoom == 2:
MainMod.MainLel()
and this is the MainMod module is :
x = 0
y = 0
roomlimits = 0
doorloc1=0
doorloc2=0
door1 = 0
door2 = 0
direct = 0
def MainLel():
global direct
movementinput()
movement(direct)
doorcheck()
def movement(dir):
global x,y,roomlimits,door1,door2,doorloc1,doorloc2
if dir == "w":
y += 5
if y > roomlimits[3]:
y = roomlimits[3]
print("Youre current coordinates are x:",x," y:",y)
elif dir == "s":
y -= 5
if y < roomlimits[2]:
y = roomlimits[2]
print("Youre current coordinates are x:",x," y:",y)
elif dir == "d":
x += 5
if x > roomlimits[1]:
x = roomlimits[1]
print("Youre current coordinates are x:",x," y:",y)
elif dir == "a":
x -= 5
if x < roomlimits[0]:
x = roomlimits[2]
print("Youre current coordinates are x:",x," y:",y)
def movementinput():
global direct
while True:
direct = input("")
if direct in ("w","a","s","d","W","A","D","S"):
break
else:
print("You failure.")
def doorcheck():
global x,y,doorloc1,doorloc2,door1,door2
if x == doorloc1[0] and doorloc1[1] <= y <= doorloc1[2]:
door1 = 1
elif y == doorloc2[0] and doorloc2[1] <= x <= doorloc2[2]:
door2 = 1
else:
door1,door2 = 0,0
Im using a module instead of classes because i dont know how to use classes yet,anyways,what happens in the program is that if i am in the door location,it simply prints "DAMN SON" and doesnt break out of the Room loop,any help? EDIT NOTE: I added the break statement later on to try if it would help,sadly it didnt,i am also a bit tired so im guessing i made a logic mistake somewhere,thanks in advance for help.
Final edit: The code was functional all along,i was just testing it incorrectly!Thanks for the awnsers,ill close this question now.
Since I could not imagine it didn't work, I added two markers (print commands), to room 1 and 2:
while CurrentRoom == 1:
print("one")
mod.MainLel()
and
while CurrentRoom == 2:
print("two")
mod.MainLel()
This is what happened:
Youre current coordinates are x: -5 y: 15
one
a
Youre current coordinates are x: -10 y: 15
one
a
Youre current coordinates are x: -15 y: 15
DAMN SON
two
a
Youre current coordinates are x: -15 y: 15
two
It turned out to be working fine. The break is redundant however. The loop will break anyway, since the condition becomes False.

Categories

Resources