class Minobot:
def __init__(self):
self.x,self.y = 0, 0
self.angle = 90
def forward(self, d):
angle = radians(90-self.angle)
nx, ny = self.x + d * cos(angle), self.y + d * sin(angle)
self.x, self.y = nx, ny
def right(self):
self.angle += 90
def left(self):
self.angle -= 90
def coordinates(self):
return round(self.x, 1), round(self.y, 1)
def manhattan_distance(self):
return int(abs(round(self.x, 1))+abs(round(self.y, 1)))
def cancel(self):
????
Now I need to add another method to this class that cancels the last method called. For example: a.forward(2) => a.right() => a.cancel() This would set the Minobot before the a.right() is used.
You cannot cancel the last action unless you store it.
If you store the last action, you can invert it. Since you know the reverse action once you take an action, you can just store the reverse action directly.
Let your Minibot
instance have a .reverse_action
attribute which is a tuple of the method to call and arguments to pass.
So
def left(self):
# Note how methods can just be stored in variables.
self.reverse_action = (self.right, ())
...
def forward(self, distance):
# Forward is its own reverse with a negative distance.
self.reverse_action = (self.forward, (-distance,))
def revert_last(self):
if self.reverse_action:
(method, args) = self.reverse_action
method(*args) # Call the stored method, passing stored args.
self.reverse_action = None # Used it up.
This has an obvious downside of being able to only revert one last action. If you store a list of reverse actions for each action you take, you can .pop()
from it and revert actions as long as there are any stored reverse actions in the list.
You can store only last several actions if you're taking great many actions and are memory-constrained. (Terms to google up: "Undo buffer", "Circular buffer", "Event sourcing".)
Another approach would be storing the previous state, that is, coordinates, heading, etc. Undoing the last action would be then just switching to the previous state:
def save_state(self):
self.previous_state = (self.x, self.y, self.angle)
# Or: self.previous_states_list.append(...)
def restore_previous_state(self):
(self.x, self.y, self.angle) = self.previous_state
# Or: ... = self.previous_states_list.pop()
def left(self):
self.save_state()
...
This approach is free from rounding errors, etc. It takes more memory, though, especially as your state grows large, and when you want to save an entire history of previous states.
Rather than saving the reversing action as other answers have suggested, you can save all the properties, and cancel
can restore them.
class Minobot:
def __init__(self):
self.x,self.y, self.oldx, self.oldy = 0, 0
self.angle, self.oldangle = 90
def forward(self, d):
self.oldx, self.oldy = self.x, self.y
angle = radians(90-self.angle)
nx, ny = self.x + d * cos(angle), self.y + d * sin(angle)
self.x, self.y = nx, ny
def right(self):
self.oldangle = self.angle
self.angle += 90
def left(self):
self.oldangle = self.angle
self.angle -= 90
def coordinates(self):
return round(self.x, 1), round(self.y, 1)
def manhattan_distance(self):
return int(abs(round(self.x, 1))+abs(round(self.y, 1)))
def cancel(self):
self.angle, self.x, self.y = self.oldangle, self.oldx, self.oldy
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With