How to handle or detect when a maze has no solution? - python

I am trying to make maze solver in python.
The parameters are as follows
y (int): Start location of y
x (int): Start location of x
The starting point is (y,x), The coordinates for the left-top, left-bottom, right-top, and right-bottom are (0,0), (N,0), (0,N), (N,N), respectively, for the maze map of size N by N.
The search function return (bool): If maze has solution or not, return True or False respectively.
The solve function returns nothing: Print out a single path solution.
I have managed to write the code and get solutions for the maze, but I have a problem when the maze has no solution. It does not stop and just goes on running infinite loops.
Below is my code
class Maze():
def __init__(self, grid):
self.grid = grid
def search(self, y, x):
self.y = y
self.x = x
if x == len(self.grid[0]) or y == len(self.grid):
print('out of maze')
return False
if self.grid[y][x] == 'F':
self.cleanup()
return True
if self.grid[y][x] != 'o' and self.grid[y][x] != ' ':
print('ran into a wall')
return False
self.grid[y][x] = ' '
if x <= len(self.grid[0])-2:
if self.grid[y][x+1] == 'o' or self.grid[y][x+1] == 'F':
print(x,y)
return self.search(y,x+1)
if y <= len(self.grid)-2:
if self.grid[y+1][x] == 'o' or self.grid[y+1][x] == 'F':
print(x,y)
return self.search(y+1,x)
if x > 1:
if self.grid[y][x-1] == 'o' or self.grid[y][x-1] == 'F':
print(x,y)
return self.search(y,x-1)
if y > 1:
if self.grid[y-1][x] == 'o' or self.grid[y-1][x] == 'F':
print(x,y)
return self.search(y-1,x)
if x > 1:
if self.grid[y][x-1] == ' ' or self.grid[y][x-1] == 'F':
print(x,y)
return self.search(y,x-1)
if y > 1:
if self.grid[y-1][x] == ' ' or self.grid[y-1][x] == 'F':
print(x,y)
return self.search(y-1,x)
if x <= len(self.grid[0])-2:
if self.grid[y][x+1] == ' ' or self.grid[y][x+1] == 'F':
print(x,y)
return self.search(y,x+1)
if y <= len(self.grid)-2:
if self.grid[y+1][x] == ' ' or self.grid[y+1][x] == 'F':
print(x,y)
return self.search(y+1,x)
print("can't find a way")
return False
def cleanup(self):
for r in range(len(self.grid)):
for c in range(len(self.grid[0])):
if self.grid[r][c] == ' ':
self.grid[r][c] = 'o'
def solve(self, y, x):
if self.search(y, x):
print("Solution")
### CODE HERE ###
else:
print('There are NO solutions')
This is my main
for i, maze_map in enumerate(maze_map_list):
maze = Maze(maze_map)
print(i+1, '-1')
maze.solve(0,0)
print(i+1, '-2')
maze.solve(4,0)
print()
and this is the grid that I am unable to work on
.
.
grid2 = ['o o o o o o'.split(' '),
'+ + o + + +'.split(' '),
'F + o o o o'.split(' '),
'o o + + + o'.split(' '),
'o o o + + o'.split(' ')]
.
.
.
maze_map_list = [grid1, grid2, grid3, grid4]

Related

If a certain letter is included in a string then its coordinate will increase or decrease

The program should ask what its first coordinates are. Then movement is asked and its answer should be with
r,R,l,L,u,U,d,D.
Coordinate are input with a comma (x,y), and then again if 'u','d','l','r' are input then the x or y axis will increase or decrease.
'u' and 'd' for the y-axis; 'r' and 'l' for the x-axis.
def program_for_grid(x,y,where):
if where == 'r' or where == 'R':
# move x upp +
for r in range(len(where)):
r == 'r' or r == 'R'
x + 1
elif where == 'l' or where == 'L':
# move x down -
for l in range(len(where)):
l == 'l' or l == 'L'
x - 1
elif where == 'u' or where == 'U':
# move y up +
for u in range(len(where)):
u == 'u' or u == 'U'
y + 1
elif where == 'd' or where == 'D':
# move y down -
for d in range(len(where)):
d == 'd' or d == 'D'
y - 1
x_axis,y_axis = input('Initial position: ').split(',')
int_x_axix = int(x_axis)
int_y_axix = int(x_axis)
movement = input('Movement: ')
grid = program_for_grid(int_x_axix,int_y_axix,movement)
print(grid)
Something like this?
def delta(movement):
"""
Parse the string for movement instructions and
return resulting relative coordinates
"""
x = 0
y = 0
for letter in movement.lower():
if letter == "d": y -= 1
elif letter == "u": y += 1
elif letter == "l": x -= 1
elif letter == "r": x += 1
else:
print("warning: skipping undefined", letter)
return x, y
x_axis,y_axis = input('Initial position: ').split(',')
int_x_axix = int(x_axis)
int_y_axix = int(y_axis)
while True:
movement = input('Movement: ')
xdelta, ydelta = delta(movement)
int_x_axix += xdelta
int_y_axix += ydelta
print(f"resulting position: ({int_x_axix},{int_y_axix})")

How can i implement the function "check_space_taken" in python

i need to implement a function that checks if a space is taken in my tic tac toe that's being played in the terminal the problem is that i cant see how i can avoid the choosen position to get into the board if a space is taken i have alreadey made the function heres my code:
import random
board = [[' ',' ',' '],
[' ',' ',' '],
[' ',' ',' ']]
def checkwin(board):
for i in range(3):
if board[i][0] != " " and board[i][0] == board[i][1] == board[i][2]:
return True #winning row
if board[0][i] != " " and board[0][i] == board[1][i] == board[2][i]:
return True #winning column
#winning diagonals
if board[1][1] != " " and board[0][0] == board[1][1] == board[2][2]:
return True
if board[1][1] != " " and board[2][0] == board[1][1] == board[0][2]:
return True
else:
return False
def check_space_taken(board, number):
if not choose_position(board, number) == ' ':
return True
else:
return False
def choose_position(board, number):
if number <= 3:
board[0][number-1] = 'X'
elif number <= 6:
board[1][number-4] = 'X'
elif number <= 9:
board[2][number-7] = 'X'
return board, number
def computer_position(board, computer_number):
computer_number = random.randint(0,9)
if computer_number <= 3:
board[0][computer_number-1] = 'O'
elif computer_number <= 6:
board[1][computer_number-4] = 'O'
elif computer_number <= 9:
board[2][computer_number-7] = 'O'
return board, computer_number
Game_over = False
while not Game_over:
player_input = int(input('move to: '))
player_changed_board = choose_position(board, player_input)
computer_input = random.randint(0,9)
computer_changed_board = computer_position(board, computer_input)
for x in player_changed_board:
print(x)
for y in computer_changed_board:
print('computer move')
print(y)
if checkwin(board):
print('\n-----------------------Congrats you won-----------------------\n')
Game_over = True
I think this would be easier if you used x, y coordinates, but here goes:
from itertools import chain
from random import choice
def cast(x, y, base):
"""
Create a y by x matrix from a vector
"""
if x * y == len(base):
return [list(base[i*x: x+i*x]) for i in range(y)]
raise ValueError('Dimensions do not agree with base')
def flat(board):
"""
Create a 1D vector from a matrix
"""
return [*chain.from_iterable(board)]
def check_space_taken(board, number):
"""
check if a space is taken
"""
return flat(board)[number] == ' '
def empty_space_indices(board):
"""
find all empty spaces
"""
flattened = flat(board)
return [*filter(lambda x: flattened[x]==' ', range(len(flattened)))]
def play(board, number, letter):
"""
Simplify the code base by using a single function for move-making
"""
board = flat(board)
board[number] = letter
board = cast(3, 3, board)
return board
def won(board, letter):
"""
checkwin seems to have a bug
"""
for i in range(3):
if letter == board[i][0] == board[i][1] == board[i][2]:
return True
elif letter == board[0][i] == board[1][i] == board[2][i]:
return True
elif letter == board[0][0] == board[1][1] == board[2][2]:
return True
elif letter == board[2][0] == board[1][1] == board[0][2]:
return True
return False
def show(board):
"""
Neat representation of the board.
checkout the module tabulate for better options:
https://github.com/astanin/python-tabulate
"""
table = '\n'.join("{}|{}|{}".format(*row) for row in board)
table = table.join('\n' * 2)
print(table)
return table
def game_over(board):
"""
check if the board is full or there is a winner
"""
return len(empty_space_indices(board))==0 or won(board, 'x') or won(board, 'o')
def main(board=None):
"""REPL"""
if board:
show(board)
board = board if not isinstance(board, type(None)) else [
[' ',' ',' '],
[' ',' ',' '],
[' ',' ',' ']
]
player_move = None
while not game_over(board):
while not player_move in empty_space_indices(board):
player_move = int(input(f'pick a tile from {empty_space_indices(board)}:\n\t'))
board = play(board, player_move, 'x')
if not game_over(board):
computer_move = choice(empty_space_indices(board))
board = play(board, computer_move, 'o')
show(board)
main()
Warning:
I think there may be something wrong with checkwin because the following did not terminate the game:
x|o|o
|o|o
x|x|x
you can use the following to check:
def relist(table):
"""parse the table from show back into a list"""
t = table.splitlines()
return [i.split('|') for i in t]
t = """x|o|o
|o|o
x|x|x"""
rt = relist(t)
for r in rt: print(r)
print(checkwin(rt))
print(game_over(rt))
print(won(rt, 'x'))

Infix evaluation in Python

I am trying to convert the code here http://www.geeksforgeeks.org/expression-evaluation/ to python. However, I am running into some trouble and can't figure out.
class evaluateString:
def evalString(self,expression):
valueStack = []
opStack = []
i=0
while(i<len(expression)):
if(expression[i] == ' '):
continue
if(expression[i]>='0' and expression[i] <= '9'):
charNumber = [] #for storing number
while(i<len(expression) and expression[i]>='0' and expression[i] <= '9'):
charNumber.append(expression[i])
i+=1
valueStack.append(int(''.join(charNumber)))
elif (expression[i]=='('):
opStack.append(expression[i])
elif (expression[i]==')'):
while(opStack[-1]!='('):
valueStack.append(self.applyOperation(opStack.pop(),valueStack.pop(),valueStack.pop()))
opStack.pop()
elif(expression[i]=='+'or expression[i]=='-'or expression[i]=='*'or expression[i]=='/'):
while( (len(opStack)!=0) and ( self.opPrecedence(expression[i],opStack[-1]) ) ):
valueStack.append(self.applyOperation(opStack.pop(),valueStack.pop(),valueStack.pop()))
opStack.append(expression[i])
i = i + 1
while(len(opStack)!=0):
valueStack.append(self.applyOperation(opStack.pop(),valueStack.pop(),valueStack.pop()))
return valueStack.pop()
def applyOperation(self,op,a,b):
if op=='+':
return a+b
elif op=='-':
return a-b
elif op=='*':
return a*b
elif op=='/':
return a/b
else:
return 0
def opPrecedence(self,op1,op2):
if (op2 == '(' or op2 == ')'):
return False
if ((op1 == '*' or op1 == '/') and (op2 == '+' or op2 == '-')):
return False
else:
return True
a = evaluateString()
print(a.evalString("(5+7)"))
I am able to get the right numbers in the valueStack. However, there seems to be problem in the last two elseif. Can someone point me in the right direction?
I have done some fixes and it works for some operations. But I haven't tested it for all cases. Also, operations are only integers, no floats (e.g. check last output below).
class evaluateString:
def evalString(self,expression):
valueStack = []
opStack = []
i=0
while(i<len(expression)):
if(expression[i] == ' '):
continue
if(expression[i]>='0' and expression[i] <= '9'):
charNumber = [] #for storing number
j = i
while(j<len(expression) and expression[j]>='0' and expression[j] <= '9'):
charNumber.append(expression[j])
j += 1
i = (j-1)
valueStack.append(int(''.join(charNumber)))
elif (expression[i]=='('):
opStack.append(expression[i])
elif (expression[i]==')'):
while(opStack[-1]!='('):
valueStack.append(self.applyOperation(opStack.pop(),valueStack.pop(),valueStack.pop()))
opStack.pop()
elif(expression[i]=='+'or expression[i]=='-'or expression[i]=='*'or expression[i]=='/'):
while( (len(opStack)!=0) and ( self.opPrecedence(expression[i],opStack[-1]) ) ):
valueStack.append(self.applyOperation(opStack.pop(),valueStack.pop(),valueStack.pop()))
opStack.append(expression[i])
i = i + 1
while(len(opStack)!=0):
valueStack.append(self.applyOperation(opStack.pop(),valueStack.pop(),valueStack.pop()))
return valueStack.pop()
def applyOperation(self,op,a,b):
if op=='+':
return a+b
elif op=='-':
return b-a
elif op=='*':
return a*b
elif op=='/':
return b/a
else:
return 0
def opPrecedence(self,op1,op2):
if (op2 == '(' or op2 == ')'):
return False
if ((op1 == '*' or op1 == '/') and (op2 == '+' or op2 == '-')):
return False
else:
return True
a = evaluateString()
print(a.evalString("8*12")) #prints 96
print(a.evalString("(122-434)")) #prints -312
print(a.evalString("(232+12)/2")) #print 122
print(a.evalString("232/12+2")) #prints 21
In python eval() will evaluate infix expressions
print(eval("(5+7)/2"))
it will print the evaluated infix expression value as 6.

Python input statement

I have created a battleship like game, and have it all completed except for one detail.
I have the following input statement:
x, y = input("Enter two numbers here: ").split()
with the 2 numbers being entered corresponding to the players chosen coordinates. I also need to be able to handle the entry of 'q' or 'h' for the quit or help options. However, since i am taking two variables from this statement when only a q or h is entered i get the error that the statement needs 2 elements to unpack, which makes sense. Any pointers on how to get around this?
import random, math
class oceanTreasure:
def __init__(self):
self.board = self.board()
self.found = 0
self.left = 3
self.sonarsLeft = 20
self.chests= []
self.chest()
def board(self):
board = []
for x in range(16): # the main list is a list of 60 lists
board.append([])
for y in range(61): # each list in the main list has 15 single-character strings.
board[x].append('~')
return board
def chest(self):
chest1 = [random.randint(0,60), random.randint(0,15)]
chest2 = [random.randint(0,60), random.randint(0,15)]
chest3 = [random.randint(0,60), random.randint(0,15)]
self.chests = [chest1, chest2, chest3]
def getChestsLeft(self):
return self.found
def getChests(self):
return self.chests
def getTreasuresLeft(self):
return self.left
def getSonarsLeft(self):
return self.sonarsLeft
def dropSonar(self,x,y):
ySonar = ['a','b','c','d','e','f','g']
whichAxis, axis = self.checkDistance(x,y)
if whichAxis == True:
sonar = axis
if whichAxis == 'xaxis':
sonar = axis
elif whichAxis == 'yaxis':
sonar = ySonar[axis-1]
elif whichAxis == None:
sonar = axis
self.board[int(y)][int(x)] = sonar
self.sonarsLeft -=1
return axis
def checkDistance(self,x,y):
closest = self.chests[0]
distance = 100
for chest in self.chests:
temp = math.sqrt(math.pow((chest[0]-int(x)),2) + math.pow((chest[1]-int(y)),2))
if temp < distance:
closest = chest
distance = temp
xaxis =math.fabs((closest[0] - int(x)))
yaxis = math.fabs((closest[1]-int(y)))
if yaxis == 0 and xaxis == 0:
self.chests.remove(closest)
self.found +=1
self.left -=1
return True, 'X'
elif xaxis <= 9 and yaxis <=5 :
if yaxis == 0 :
return 'xaxis',int(math.fabs(xaxis))
if xaxis == 0 :
return 'yaxis',int(math.fabs(yaxis))
if min(xaxis//2,yaxis) ==(xaxis//2) :
return 'xaxis', int(math.fabs(xaxis))
elif min(xaxis//2,yaxis) == (yaxis) or xaxis == 0 :
return 'yaxis', int(math.fabs(yaxis))
else: return None,0
def drawBoard(self):
firstLine = ' '
for i in range(1,7):
firstLine += (' '*9) + str(i)
print(firstLine)
secondLine = ' '
secondLine += ('0123456789' *6)
print(secondLine)
print()
i = 0
for i in range(0,16):
boardRow = ''
for x in range(0,61):
boardRow += str(self.board[i][x])
if i < 10:
print(str(i) +' ' + str(boardRow) + str(i))
if i >= 10:
print(str(i) +' ' + str(boardRow) + str(i))
print()
print(secondLine)
print(firstLine)
device = 'devices'
if self.sonarsLeft ==1:
device = 'device'
print('You have %s sonar %s availabe. You have found %s treasures and have %s left' %(self.sonarsLeft, device, self.found, self.left))
ocean = oceanTreasure()
ocean.drawBoard()
gameOver = False
instructionsList = ['This is a treasure hunting game.' , 'You begin the game with 20 sonar devices available (each device has a range of 9 units in the x axis and 5 in the y axis).','When you place a device, if an "O" is displayed that means there are no chests in range.', 'If a number from 1-9 is displayed, the closest chest is within n units away on the X axis.', 'If a letter from a-e is displayed, the closest chest is n units away on the Y axis (a =1, b =2 and so on...).', 'The game ends when you run out of sonar devices, all the treasure is found or you enter "q" to quit.', 'Thanks for playing and happy hunting!']
while ocean.getTreasuresLeft() != 0 and ocean.getSonarsLeft() >0 and gameOver == False:
response = False
coordinate = False
while response == False:
inputString = input("Enter two numbers seperated by a space (X Y): ")
if inputString == 'q':
gameOver = True
response = True
elif inputString == 'h':
for instruction in instructionsList:
print(instruction)
response = True
else:
try:
x,y = inputString.split()
assert int(x) <=60 and int(y) <=15
response = True
coordinate = True
except AssertionError:
print('Please enter a valid move')
if gameOver == True:
break
#whichAxis, axis =ocean.checkDistance(x,y)
#print(axis)
if coordinate == True:
axis = ocean.dropSonar(x,y)
ocean.drawBoard()
if axis == 'X':
print('Congratulations, you have found a treasure!')
if ocean.getTreasuresLeft() == 0:
print('Congratulations, you found all the treasure')
elif ocean.getSonarsLeft() == 0:
print('Sorry, you ran out of sonar devices, the remaining chests were: %s ' % str(ocean.getChests()))
How about separating the tests to be a little clearer:
input_string = input("Enter two numbers here: ")
if input_string == 'q':
do_quit()
elif input_string == 'h':
do_help()
else:
x,y = input_string.split()
That way you can test for your special cases, and process the x and y if they are not found.
may be this, for example:
a = input("text")
b = a.split()
if len(b) == 1:
if b[0] == 'q':
return
elif b[0] == 'h':
print 'it is help ... '
elif len(b) == 2:
# process for two inputted numbers
You can just separate the input:
# get the input
ipt = input("Enter two numbers here: ")
# check if your option is entered
if ipt == 'q' or ipt == 'h':
# do something
else:
x,y = ipt.split()

python maze recurrsion not recurssing

I'm trying to solve a maze recursively and I can get it to go where I want it to (check to make sure it can go a way and then to mark it as been there) but for some reason when it runs into a dead end, it does not recursively go back to an open place to check another path. Is there anything wrong with the way I'm using recursion?
class maze(object):
def __init__(self, maze):
self.maze = maze
self.maze2d = []
n = 0
i = 0
for row in self.maze:
self.maze2d.append([])
print(row)
for col in row:
self.maze2d[i].append(col)
i += 1
print(self.maze2d)
def find_start(self):
x = 0
y = 0
for row in self.maze2d:
for index in row:
if index == "S":
self.maze2d[x][y] = index
return x,y
y += 1
x += 1
y = 0
return -1
def mazeSolver(self,x,y,path):
if self.maze2d[x][y] == "E":
return True
else:
if self.maze2d[x] != 0:
if self.maze2d[x+1][y] == ".":
self.maze2d[x+1][y] = "_"
self.mazeSolver(x+1,y,path + "S")
if self.maze2d[x] < len(self.maze2d):
if self.maze2d[x-1][y] == ".":
self.maze2d[x-1][y] = "_"
self.mazeSolver(x-1,y,path + "N")
if y < len(self.maze2d[x]):
if self.maze2d[x][y+1] == ".":
self.maze2d[x][y+1] = "_"
self.mazeSolver(x,y+1,path + "E")
if self.maze2d[y] != 0:
if self.maze2d[x][y-y] == ".":
self.maze2d[x][y-1] = "_"
self.mazeSolver(x,y-1,path + "W")
and where I'm calling the function and the maze itself:
from eachstep import *
maze1 = []
maze1.append("S..*..")
maze1.append("*...*.")
maze1.append("..*..E")
var1 = maze(maze1)
x,y = var1.find_start()
var1.mazeSolver(x,y,"")
I changed your mazeSolver function with this. And I print the path at the end:
def mazeSolver(self,x,y,path):
if self.maze2d[x][y] == '.':
self.maze2d[x][y] = "_"
if self.maze2d[x][y] == "E":
print path
return True
else:
if x < len(self.maze2d)-1:
if self.maze2d[x+1][y] in ['.','E']:
self.mazeSolver(x+1,y,path + "S")
if x > 0:
if self.maze2d[x-1][y] in ['.','E']:
self.mazeSolver(x-1,y,path + "N")
if y < len(var1.maze2d[x])-1:
if self.maze2d[x][y+1] in ['.','E']:
self.mazeSolver(x,y+1,path + "E")
if y > 0:
if self.maze2d[x][y-y] in ['.','E']:
self.mazeSolver(x,y-1,path + "W")
>>> var1.mazeSolver(x,y,"")
ESEESEE
>>>> var1.maze2d
[['S', '_', '_', '*', '.', '.'],
['*', '_', '_', '_', '*', '.'],
['_', '_', '*', '_', '_', 'E']]
Your code will never reach the end, since it only visits locations with the value ., and the end has the value E.

Categories