patternpythonMinor
Clean code and SOLID principles for a simple Python TicTacToe game
Viewed 0 times
principlessimpletictactoeandgameforpythoncodesolidclean
Problem
I recently read the book Clean Code and I also did some research on the SOLID principles. I'm looking for general feedback on if I was able to transpose the examples (written in Java) to Python while still maintaining a "Pythonic" program.
I wrote a simple TicTacToe game in Python using Tkinter as the GUI and I tried to strike a balance between readable, clean code and avoiding code cluttering with useless functions (
Having a generic BoardGUI class specializing in
The 3 modules (models, views, game) implement a minimalistic MVC design where GameApplication controls the flow and events.
The part I don't know how to handle is using polymorphism to have different levels of AI (right now the AI only checks a random empty box)
http://www.filedropper.com/tictactoe (~200 lines total)
main.py
models.py:
```
#!/usr/bin/env
from collections import namedtuple
class TicTacToeBoard():
"""
Keeps track of the status of the boxes of a standard 3x3 TicTacToe game
I don't particularly like the victory, draw and _find_lines functions, any better solutions?
"""
ROWS = 3
COLUMNS = 3
EMPTY = 0
O = 1
X = 2
def __init__(self):
self.boxes = {(column, row): namedtuple('box', 'value') \
for row in range(TicTacToeBoard.ROWS) \
I wrote a simple TicTacToe game in Python using Tkinter as the GUI and I tried to strike a balance between readable, clean code and avoiding code cluttering with useless functions (
get(), set(), isEmpty() and other 1-liners)Having a generic BoardGUI class specializing in
TicTacToeBoardGUI is my attempt at the open/close principle.The 3 modules (models, views, game) implement a minimalistic MVC design where GameApplication controls the flow and events.
The part I don't know how to handle is using polymorphism to have different levels of AI (right now the AI only checks a random empty box)
http://www.filedropper.com/tictactoe (~200 lines total)
main.py
#!/usr/bin/env
import Tkinter as tk
from game import GameApplication
def convert_images():
"""Returns a dictionary with the images converted into PhotoImages Tkinter can use"""
img_dict = {}
img_dict.update({'cross': tk.PhotoImage(file='images/cross.gif')})
img_dict.update({'circle': tk.PhotoImage(file='images/circle.gif')})
return img_dict
def main():
root = tk.Tk()
root.title('Tic-Tac-Toe v1.0')
images = convert_images()
GameApplication(root, images)
root.mainloop()
if __name__ == '__main__':
main()models.py:
```
#!/usr/bin/env
from collections import namedtuple
class TicTacToeBoard():
"""
Keeps track of the status of the boxes of a standard 3x3 TicTacToe game
I don't particularly like the victory, draw and _find_lines functions, any better solutions?
"""
ROWS = 3
COLUMNS = 3
EMPTY = 0
O = 1
X = 2
def __init__(self):
self.boxes = {(column, row): namedtuple('box', 'value') \
for row in range(TicTacToeBoard.ROWS) \
Solution
Looks to me that you want to have a box with various buttons that allows you to select, say, easy, medium, or hard. Return that and then say
Now, that's obviously the easy part, but a Tic-Tac-Toe AI is actually not at all hard:
See? This is a quick and painless AI that can beat decent players who don't know how it's made about 50-60% of the time.
EDIT: Since Tic-Tac-Toe can always be won or tied by the player that moves first, you may wish to add this into the AI by doing something like this:
if AIChoose == "Easy":
getEasyAIMove()
elif AIChoose == "Medium":
GetMedAIMove()
elif AIChoose == "Hard":
GetHardAIMove()Now, that's obviously the easy part, but a Tic-Tac-Toe AI is actually not at all hard:
def GetHardAIMove():
# first check if you're about to win. If you are, move there
# now check if your opponent is about to win. If he is, block him
# check if any of the corners are free. If they are, go to a random one of them
# check if the middle is free. If it is, go to it
#otherwise, go to a random open spot
def GetMedAIMove():
# here's where we cheat. generate a random number between 1 and 3. if its <= 2, GetHardAIMove. otherwise, go easy.
def GetEasyAIMove():
# If you're about to win, go there
# If you're about to lose, go there
# Otherwise, go to a random spot.See? This is a quick and painless AI that can beat decent players who don't know how it's made about 50-60% of the time.
EDIT: Since Tic-Tac-Toe can always be won or tied by the player that moves first, you may wish to add this into the AI by doing something like this:
def GetHardAIMove():
# if you move first:
# after making sure you or your opponent isn't about to win:
# move to a corner
# then move to the corner opposite that
# then move to a random corner
# at this point, you have either won or tied
# first check if you're about to win. If you are, move there
# now check if your opponent is about to win. If he is, block him
# check if any of the corners are free. If they are, go to a random one of them
# check if the middle is free. If it is, go to it
#otherwise, go to a random open spotCode Snippets
if AIChoose == "Easy":
getEasyAIMove()
elif AIChoose == "Medium":
GetMedAIMove()
elif AIChoose == "Hard":
GetHardAIMove()def GetHardAIMove():
# first check if you're about to win. If you are, move there
# now check if your opponent is about to win. If he is, block him
# check if any of the corners are free. If they are, go to a random one of them
# check if the middle is free. If it is, go to it
#otherwise, go to a random open spot
def GetMedAIMove():
# here's where we cheat. generate a random number between 1 and 3. if its <= 2, GetHardAIMove. otherwise, go easy.
def GetEasyAIMove():
# If you're about to win, go there
# If you're about to lose, go there
# Otherwise, go to a random spot.def GetHardAIMove():
# if you move first:
# after making sure you or your opponent isn't about to win:
# move to a corner
# then move to the corner opposite that
# then move to a random corner
# at this point, you have either won or tied
# first check if you're about to win. If you are, move there
# now check if your opponent is about to win. If he is, block him
# check if any of the corners are free. If they are, go to a random one of them
# check if the middle is free. If it is, go to it
#otherwise, go to a random open spotContext
StackExchange Code Review Q#38789, answer score: 4
Revisions (0)
No revisions yet.