Created project 5
This commit is contained in:
BIN
Project 5/Project 5_ Turtle Maze.pdf
Normal file
BIN
Project 5/Project 5_ Turtle Maze.pdf
Normal file
Binary file not shown.
77
Project 5/Stack.py
Normal file
77
Project 5/Stack.py
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
######################################
|
||||||
|
# DCS 229 -- Stack
|
||||||
|
# Stack data structure implemented with Linked List
|
||||||
|
# Date:
|
||||||
|
# Name:
|
||||||
|
# Resources Used:
|
||||||
|
##########################################
|
||||||
|
|
||||||
|
|
||||||
|
from LinkedList import *
|
||||||
|
class EmptyError(Exception):
|
||||||
|
''' class extending Exception to better document stack errors '''
|
||||||
|
def __init__(self, message: str):
|
||||||
|
self.message = message
|
||||||
|
|
||||||
|
class Stack[T]:
|
||||||
|
''' class to implement a stack ADT using our LinkedList class'''
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
|
||||||
|
pass
|
||||||
|
def __len__(self) -> int:
|
||||||
|
''' allows the len function to be called using an ArrayStack object, e.g.,
|
||||||
|
stack = ArrayStack()
|
||||||
|
print(len(stack))
|
||||||
|
Returns:
|
||||||
|
number of elements in the stack, as an integer
|
||||||
|
'''
|
||||||
|
pass
|
||||||
|
|
||||||
|
def push(self, item: T) -> None:
|
||||||
|
''' pushes a given item of arbitrary type onto the stack
|
||||||
|
Parameters:
|
||||||
|
item: an item of arbitrary type
|
||||||
|
Returns:
|
||||||
|
None
|
||||||
|
'''
|
||||||
|
pass
|
||||||
|
|
||||||
|
def pop(self) -> T:
|
||||||
|
''' removes the topmost element from the stack and returns that element
|
||||||
|
Returns:
|
||||||
|
the topmost item, of arbitrary type
|
||||||
|
Raises:
|
||||||
|
EmptyError exception if the stack is empty
|
||||||
|
'''
|
||||||
|
pass
|
||||||
|
|
||||||
|
def peek(self) -> T:
|
||||||
|
''' returns the topmost element from the stack without modifying the stack
|
||||||
|
Returns:
|
||||||
|
the topmost item, of arbitrary type
|
||||||
|
Raises:
|
||||||
|
EmptyError exception if the stack is empty
|
||||||
|
'''
|
||||||
|
pass
|
||||||
|
|
||||||
|
def is_empty(self) -> bool:
|
||||||
|
''' indicates whether the stack is empty
|
||||||
|
Returns:
|
||||||
|
True if the stack is empty, False otherwise
|
||||||
|
'''
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
''' returns an str implementation of the Stack '''
|
||||||
|
|
||||||
|
return str(self._data)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
# add your tests here!
|
||||||
|
pass
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
||||||
250
Project 5/TurtleMaze.py
Normal file
250
Project 5/TurtleMaze.py
Normal file
@@ -0,0 +1,250 @@
|
|||||||
|
######################################
|
||||||
|
# DCS 229 -- TurtleMaze
|
||||||
|
# Utility file with the TurtleMaze class.
|
||||||
|
# Date: March 13, 2026
|
||||||
|
# Name: Prof. Andy Ricci
|
||||||
|
# Resources Used: https://runestone.academy/ns/books/published/pythonds/Recursion/ExploringaMaze.html
|
||||||
|
##########################################
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from enum import Enum
|
||||||
|
import turtle
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
class Contents(str, Enum):
|
||||||
|
''' create an enumeration to define what the visual contents of a Cell are;
|
||||||
|
using str as a "mixin" (multiple inheritance) forces all the entries to
|
||||||
|
be strings; using an Enum means no cell entry can be anything other
|
||||||
|
than the options here
|
||||||
|
'''
|
||||||
|
|
||||||
|
EMPTY = ' '
|
||||||
|
START = 'S'
|
||||||
|
GOAL = 'G'
|
||||||
|
PART_OF_PATH = 'O'
|
||||||
|
TRIED = '.'
|
||||||
|
OBSTACLE = '+'
|
||||||
|
DEAD_END = '-'
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return self.value
|
||||||
|
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
class Cell:
|
||||||
|
''' class that allows us to use Cell as a data type -- an ordered triple
|
||||||
|
of row, column, & cell contents
|
||||||
|
(see Contents class enumeration above)
|
||||||
|
'''
|
||||||
|
|
||||||
|
def __init__(self, row: int, col: int, contents: Contents):
|
||||||
|
self._contents: Contents = contents
|
||||||
|
self._parent: Cell = None # parent of this Cell during exploration
|
||||||
|
self.x = col
|
||||||
|
self.y = row
|
||||||
|
|
||||||
|
def getParent(self) -> Cell:
|
||||||
|
''' method to return the parent of this Cell object as determined during
|
||||||
|
maze exploration
|
||||||
|
Returns:
|
||||||
|
a Cell object corresponding to the cell that considered this cell
|
||||||
|
during the exploration process
|
||||||
|
'''
|
||||||
|
return self._parent
|
||||||
|
|
||||||
|
def setParent(self, parent: Cell) -> None:
|
||||||
|
''' setter method to update this Cell's parent
|
||||||
|
Parameters:
|
||||||
|
parent: a different Cell object
|
||||||
|
Raises:
|
||||||
|
ValueError if self == parent
|
||||||
|
'''
|
||||||
|
if self == parent: raise ValueError(f"a Cell cannot be its own parent")
|
||||||
|
self._parent = parent
|
||||||
|
|
||||||
|
def markOnPath(self) -> None:
|
||||||
|
''' method to identify this cell as being on the path from source
|
||||||
|
to goal
|
||||||
|
'''
|
||||||
|
self._contents = Contents.PART_OF_PATH
|
||||||
|
|
||||||
|
def isBlocked(self) -> bool:
|
||||||
|
''' Boolean method to indicate whether this cell contains a block
|
||||||
|
Returns:
|
||||||
|
True if the cell is blocked (cannot be explored), False o/w
|
||||||
|
'''
|
||||||
|
return self._contents == Contents.OBSTACLE
|
||||||
|
|
||||||
|
def isGoal(self) -> bool:
|
||||||
|
''' Boolean method to indicate whether this cell is the goal
|
||||||
|
Returns:
|
||||||
|
True if the cell is the maze goal, False o/w
|
||||||
|
'''
|
||||||
|
return self._contents == Contents.GOAL
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
''' creates and returns a string representation of this cell
|
||||||
|
Returns:
|
||||||
|
a string identifying the cell's row, col, and cell contents
|
||||||
|
'''
|
||||||
|
string = f"({self.x}, {self.y}, {self._contents}) "
|
||||||
|
if self._parent is not None:
|
||||||
|
string += f"Parent is: ({self._parent.x}, {self._parent.y})"
|
||||||
|
return string
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
''' overriding __repr__ so that printing, e.g., a list of Cell objects
|
||||||
|
(which will call __repr__ for each) will call __str__ for each, printing
|
||||||
|
nicely
|
||||||
|
Returns:
|
||||||
|
a string identifying the cell's row, col, and cell contents
|
||||||
|
'''
|
||||||
|
return self.__str__()
|
||||||
|
|
||||||
|
def __eq__(self, other: Cell) -> bool:
|
||||||
|
''' indicates whether a given other Cell is equal to this Cell
|
||||||
|
Returns:
|
||||||
|
True if this Cell and the other Cell are the same, False o/w
|
||||||
|
'''
|
||||||
|
return self.x == other.x and \
|
||||||
|
self.y == other.y
|
||||||
|
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
class TurtleMaze:
|
||||||
|
def __init__(self, mazeFileName):
|
||||||
|
rowsInMaze = 0
|
||||||
|
columnsInMaze = 0
|
||||||
|
self.maze_grid = []
|
||||||
|
mazeFile = open(mazeFileName, 'r')
|
||||||
|
rowsInMaze = 0
|
||||||
|
for line in mazeFile:
|
||||||
|
rowList = []
|
||||||
|
col = 0
|
||||||
|
for ch in line[:-1]: #
|
||||||
|
# make new cell: (row, col, contents)
|
||||||
|
cell = Cell(rowsInMaze, col, ch)
|
||||||
|
rowList.append(cell)
|
||||||
|
if ch == Contents.START:
|
||||||
|
self.startRow = rowsInMaze
|
||||||
|
self.startCol = col
|
||||||
|
self._start = cell
|
||||||
|
if ch == Contents.GOAL:
|
||||||
|
self._goal = cell
|
||||||
|
|
||||||
|
col = col + 1
|
||||||
|
rowsInMaze = rowsInMaze + 1
|
||||||
|
self.maze_grid.append(rowList)
|
||||||
|
columnsInMaze = len(rowList)
|
||||||
|
|
||||||
|
self._num_rows = rowsInMaze
|
||||||
|
self._num_cols = columnsInMaze
|
||||||
|
self.xTranslate = -columnsInMaze / 2
|
||||||
|
self.yTranslate = rowsInMaze / 2
|
||||||
|
self.t = turtle.Turtle()
|
||||||
|
self.t.shape('turtle')
|
||||||
|
self.wn = turtle.Screen()
|
||||||
|
self.wn.setworldcoordinates(-(columnsInMaze - 1) / 2 - .5, -(rowsInMaze - 1) / 2 - .5,
|
||||||
|
(columnsInMaze - 1) / 2 + .5, (rowsInMaze - 1) / 2 + .5)
|
||||||
|
|
||||||
|
|
||||||
|
def drawMaze(self):
|
||||||
|
self.t.speed(10)
|
||||||
|
self.wn.tracer(0)
|
||||||
|
for y in range(self._num_rows):
|
||||||
|
for x in range(self._num_cols):
|
||||||
|
cell = self.maze_grid[y][x]
|
||||||
|
if cell._contents == Contents.OBSTACLE:
|
||||||
|
self.drawCenteredBox(x + self.xTranslate, -y + self.yTranslate, 'orange')
|
||||||
|
self.updatePosition(self.getStart())
|
||||||
|
self.t.color('black')
|
||||||
|
self.t.fillcolor('blue')
|
||||||
|
self.wn.update()
|
||||||
|
self.wn.tracer(1)
|
||||||
|
|
||||||
|
def drawCenteredBox(self, x, y, color):
|
||||||
|
self.t.up()
|
||||||
|
self.t.goto(x - .5, y - .5)
|
||||||
|
self.t.color(color)
|
||||||
|
self.t.fillcolor(color)
|
||||||
|
self.t.setheading(90)
|
||||||
|
self.t.down()
|
||||||
|
self.t.begin_fill()
|
||||||
|
for i in range(4):
|
||||||
|
self.t.forward(1)
|
||||||
|
self.t.right(90)
|
||||||
|
self.t.end_fill()
|
||||||
|
|
||||||
|
def moveTurtle(self, x, y):
|
||||||
|
self.t.up()
|
||||||
|
self.t.setheading(self.t.towards(x + self.xTranslate, -y + self.yTranslate))
|
||||||
|
self.t.goto(x + self.xTranslate, -y + self.yTranslate)
|
||||||
|
|
||||||
|
def dropBreadcrumb(self, color):
|
||||||
|
self.t.dot(10, color)
|
||||||
|
|
||||||
|
def updatePosition(self, cell, val=None):
|
||||||
|
if val:
|
||||||
|
cell._contents = val
|
||||||
|
self.moveTurtle(cell.x, cell.y)
|
||||||
|
|
||||||
|
if val == Contents.PART_OF_PATH:
|
||||||
|
color = 'green'
|
||||||
|
elif val == Contents.TRIED:
|
||||||
|
color = 'black'
|
||||||
|
elif val == Contents.DEAD_END:
|
||||||
|
color = 'red'
|
||||||
|
else:
|
||||||
|
color = None
|
||||||
|
|
||||||
|
if color:
|
||||||
|
self.dropBreadcrumb(color)
|
||||||
|
|
||||||
|
|
||||||
|
def getStart(self) -> Cell:
|
||||||
|
''' accessor method to return the Cell object corresponding to the Maze start
|
||||||
|
Returns:
|
||||||
|
the Cell object at the Maze start location
|
||||||
|
'''
|
||||||
|
return self._start
|
||||||
|
|
||||||
|
def getGoal(self) -> Cell:
|
||||||
|
''' accessor method to return the Cell object corresponding to the Maze goal
|
||||||
|
Returns:
|
||||||
|
the Cell object at the Maze goal location
|
||||||
|
'''
|
||||||
|
return self._goal
|
||||||
|
|
||||||
|
def __getitem__(self, idx):
|
||||||
|
"""
|
||||||
|
Magic method for accessing element with square brackets []
|
||||||
|
|
||||||
|
Example usage:
|
||||||
|
|
||||||
|
maze = TurtleMaze(file)
|
||||||
|
maze[4] # the row at index 4 (the 5th row in the maze)
|
||||||
|
maze[4][0] # the first cell in the row at index 4
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self.maze_grid[idx]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
|
||||||
|
maze = TurtleMaze('maze_3.txt')
|
||||||
|
maze.drawMaze()
|
||||||
|
# print("row at index 4", maze[4])
|
||||||
|
# print("cell at index 4, 4", maze[4][4])
|
||||||
|
|
||||||
|
maze.updatePosition(maze.getStart())
|
||||||
|
print(maze.getStart())
|
||||||
|
|
||||||
|
maze.t.screen.mainloop()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
7
Project 5/maze_1.txt
Normal file
7
Project 5/maze_1.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
+++++++++
|
||||||
|
+ S ++
|
||||||
|
++++++ ++
|
||||||
|
+G+ ++
|
||||||
|
+ + + ++
|
||||||
|
++ + ++
|
||||||
|
+++++++++
|
||||||
11
Project 5/maze_2.txt
Normal file
11
Project 5/maze_2.txt
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
++++++++++++++++++++++
|
||||||
|
+ + ++ ++ +
|
||||||
|
G + ++++++++++
|
||||||
|
+ + ++ ++++ +++ ++
|
||||||
|
+ + + + ++ +++ +
|
||||||
|
+ ++ ++ + +
|
||||||
|
+++++ + + ++ + +
|
||||||
|
+++++ +++ + + ++ +
|
||||||
|
+ + + S+ + +
|
||||||
|
+++++ + + + + + +
|
||||||
|
++++++++++++++++++++++
|
||||||
3
Project 5/maze_3.txt
Normal file
3
Project 5/maze_3.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
++++++++++++++++++++++
|
||||||
|
+G S++
|
||||||
|
++++++++++++++++++++++
|
||||||
Reference in New Issue
Block a user