Toto Briac
Toto Briac

Reputation: 936

Making a function in an "if" only take action when a condition is true

I am coding a simple maze game. I've created a Player class with a move method -- but whenever I want to check if the move is in the available paths list, it does run the move method and changes my character position.

class Player :

    def __init__ (self, position):
        self.position = position

    def move (self, direction):
        if direction == "right":    self.position[0] += 1
        elif direction == "left":   self.position[0] -= 1
        elif direction == "up":     self.position[1] -= 1
        elif direction == "down":   self.position[1] += 1
        return self.position

maze_paths = [[0,0], [1,0]]
mac = Player([0,0])
direction = 'left'

if mac.move(direction) in maze_paths:
    print('ok')
else:
    print('No way!')

print('Final position is: %r' % (mac.position))

The output I expect is:

No way!
Final position is: [0, 0]

...because the move left shouldn't be allowed with the maze as it's defined. However, what we have instead is:

No way!
Final position is: [-1, 0]

...with the move happening even though it shouldn't be allowed.

Upvotes: 0

Views: 153

Answers (2)

Charles Duffy
Charles Duffy

Reputation: 296049

As @TimRichardson suggested in the comments, the act of calculating state should be split out from the act of changing state. Functional programming languages are built to make this easy, but Python isn't one -- so you need to jump through some hoops.

Consider splitting move into two methods, like the calculate_move and do_move shown below:

class Player:
    def calculate_move(self, direction):
        """Calculate where we would be if we moved in a direction"""
        emulated_position = self.position[:]  # make a copy
        if direction == "right":    emulated_position[0] += 1
        elif direction == "left":   emulated_position[0] -= 1
        elif direction == "up":     emulated_position[1] -= 1
        elif direction == "down":   emulated_position[1] += 1
        return emulated_position

    def do_move(self, direction):
        """Actually move in the given direction"""
        self.position = self.calculate_move(direction)

maze_paths = [[0,0], [1,0]]
mac = Player([0,0])
direction = 'left'

if mac.calculate_move(direction) in maze_paths:
    mac.do_move(direction)
    print('ok')
else:
    print('No way!')

print('Final position is: %r' % mac.position)

...which properly emits as output:

No way!
Final position is: [0, 0]

Upvotes: 3

grimur82
grimur82

Reputation: 169

Create a meningful separate validate function like. Did this on my phone.

def validateMove(direction):

      if direction == "right":
             return self.position[0] + 1 in self.maze_paths
      if direction == "down":
             return self.position[1] + 1 in self.maze_paths
      if direction == "left":
             return self.position[0] - 1 in self.maze_paths
      if direction =="up":
             return self.position[1] - 1 in self.maze_paths
      return false

Upvotes: 0

Related Questions