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
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})")
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'))
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.
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()
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.