I mainly write code for data analysis so don't think about or use OOP at all on the day job. I thought I'd have a go at a simple Monty Hall simulation in an object-oriented style to figure out how it works - specifically I based it on this: https://www.reddit.com/r/dailyprogrammer/comments/n94io8/20210510_challenge_389_easy_the_monty_hall_problem/ Appreciate this project has been done to death but I just want to get a bit of feedback on whether I 'get' OOP or not. Having written a lot of code in a procedural style, I found it quite confusing. Note that the strategies in the `strategise` method are from the link above. If an unrecognised name is used, it just picks a second door randomly. What I specifically struggled with are things like: - What should be an object? There were lots of things that could have been. Doors, maybe a game show host, maybe the prizes... in the end I kept it simple but that was only after a few iterations and getting stuck. - Am I using the classes/methods correctly when running the simulation? Would you surface more of the methods rather than using a 'wrapper' method like I've done with `Contestant.play_the_game`? - The `strategise` method is a bit of a mess. Is there a better way of implementing this that isn't just a load of `if...else`? Any other thoughts/criticisms on general style and anything else are welcome - I don't generally code in Python either so this was all very new. My class definitions are in a file called monthHall.py: ``` import random class MontyHall: def __init__(self): '''The Monty Hall game! Three doors, 2 goats, one car.''' self.doors = {1: "goat", 2: "goat", 3: "goat"} prize_door = random.randint(1, 3) self.doors[prize_door] = "car" def check_door(self, door_number): '''Checks what is behind a given door.''' return self.doors[door_number] def first_reveal(self, door_number): '''Takes a door number picked by the contestant and opens one of other doors with a goat.''' doors = [1, 2, 3] doors.remove(door_number) prizes = list(map(self.check_door, doors)) if "car" in prizes: del doors[prizes.index("car")] door = random.choice(doors) return door def second_reveal(self, door_number): '''Takes the contestant's second pick and reveals their prize.''' prize = self.check_door(door_number) return prize class Contestant: def __init__(self, name): '''A contestant to play the Monty Hall game.''' self.name = name self.wins = [] self.second_door = 0 if self.name in ["Alice", "Bob", "Frank", "Gina"]: self.first_door = 1 else: self.first_door = random.choice([1, 2, 3]) def strategise(self, doors): '''Picks a second door. If the contestant name is not recognised, it just picks randomly.''' if self.name in ["Alice", "Dave"]: self.second_door = self.first_door elif self.name in ["Bob", "Erin"]: self.switch_doors(doors) elif self.name == "Frank": if 2 in doors: self.second_door = 2 else: self.second_door = self.first_door elif self.name == "Gina": if not self.wins: self.second_door = self.first_door else: if self.wins[-1]: if self.second_door != self.first_door: self.switch_doors(doors) else: if self.second_door != self.first_door: self.second_door = self.first_door else: self.switch_doors(doors) else: self.second_door = random.choice(doors) def switch_doors(self, doors): '''Switches doors for the second contestant pick.''' doors.remove(self.first_door) self.second_door = doors[0] def first_pick(self, competition): '''Pass the first door choice to the competition to open one of the other doors, and then pick a strategy.''' open_door = competition.first_reveal(self.first_door) doors = [1, 2, 3] doors.remove(open_door) self.strategise(doors) def second_pick(self, competition): '''Pass the second door choice to the competition to reveal the prize!''' prize = competition.second_reveal(self.second_door) if (prize == "car"): self.wins.append(1) else: self.wins.append(0) def play_the_game(self, competition): '''Play the game.''' self.first_pick(competition) self.second_pick(competition) ``` And I run the simulation like this: ``` from montyHall import * def main(): alice = Contestant("Alice") bob = Contestant("Bob") carol = Contestant("Carol") dave = Contestant("Dave") erin = Contestant("Erin") frank = Contestant("Frank") gina = Contestant("Gina") for i in range(1000): for contestant in [alice, bob, carol, dave, erin, frank, gina]: competition = MontyHall() contestant.play_the_game(competition) for contestant in [alice, bob, carol, dave, erin, frank, gina]: print(contestant.name + " win rate: " + str(100 * sum(contestant.wins)/len(contestant.wins)) + "%") if __name__ == "__main__": main() ```