HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Game of Quarto in Python

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
quartogamepython

Problem

Does anyone have suggestions for how to make this code for playing a game of Quarto cleaner and more robust (beyond input error checking, which hasn't been fully fleshed out yet)?

```
# Enums for quarto.
DRAW = "D"
WIN = "W"
UNDECIDED = "U"
LOSE = "L"
TIE = "T"

class Piece():
"""
This is the piece class.
"""
attributes = None
full_name = ""
abbreviation = ""

def __init__(self, attributes):
"""
Constructor for our piece class with support for
the various pieces in the game of Quarto.
"""
self.attributes = attributes
if attributes & 0b0001:
self.full_name += "Tall"
self.abbreviation += "T"
else:
self.full_name += "Short"
self.abbreviation += "S"
if attributes & 0b0010:
self.full_name += " black"
self.abbreviation += "B"
else:
self.full_name += " white"
self.abbreviation += "W"
if attributes & 0b0100:
self.full_name += " circle"
self.abbreviation += "C"
else:
self.full_name += " square"
self.abbreviation += "Q"
if attributes & 0b1000:
self.full_name += " solid-top"
self.abbreviation += "D"
else:
self.full_name += " hollow-top"
self.abbreviation += "H"

def get_attributes(self):
"""
Returns a list of attributes.
"""
return self.attributes

def get_piece_name(self):
"""
Returns the name of the piece.
"""
return self.full_name

def get_piece_abbr(self):
"""
Returns the abbreviation of the piece.
"""
return self.abbreviation

class Board():
"""
This is the board class.
"""
pieces = []
cols_count = 4
rows_count = 4
board = None

def __init__(self):
"""
Constructor for our board class.
Ap

Solution

You do not need getters, remove all of them

You can just access an attribute of a class directly: class.attribite_name. Using @property allows adding operations before retrieving the value. (See link above for more information).

any

When you want to verify that "at least one" condition is True, any is the best way to do it.

One example:

for lst in attr_list:
    if self.shared_attributes(lst):
        return True
return False


Becomes:

return any(self.shared_attributes(lst) for lst in attr_list)


Much shorter and more abstract.

Repetition

Some logic is shared between check_win_horizontal and check_win_vertical . I suggest factoring it out to a function to reduce repetition.

Columns

The columns can be obtained with zip(* board) so you can avoid writing the logic yourself.

Repetition

self.pieces.append(Piece(0b0000))
# ...... Many more similar lines


You can use a loop to make it clear that only the number changes and to avoid code bloat. Even better would be to generate this numbers programmatically to avoid the human error of forgetting/getting wrong one of them.

Confusing / weird aliases

def gen_moves(state): return state.get_pieces_names()
def do_move(move, state): state.place_piece(move[0], move[1], move[2]); return state
def solve(state): return primitive(state)


These functions are pretty much just aliases of other functions, and in my opinion they only produce code bloat (a lot of lines of code represent no logic at all, just other names for already stated logic).

Even more confusing is that you throw away the return value of do_move when you call it, so the return statement can easily be removed so the function becomes even more similar to place_piece

Just remove these and use the originals.

Good: separation of (input and output) from logic

This is the best feature of your code. Separating the user interaction from the logic makes everything simpler and neater.

Code Snippets

for lst in attr_list:
    if self.shared_attributes(lst):
        return True
return False
return any(self.shared_attributes(lst) for lst in attr_list)
self.pieces.append(Piece(0b0000))
# ...... Many more similar lines
def gen_moves(state): return state.get_pieces_names()
def do_move(move, state): state.place_piece(move[0], move[1], move[2]); return state
def solve(state): return primitive(state)

Context

StackExchange Code Review Q#146973, answer score: 4

Revisions (0)

No revisions yet.