How do I have something be "skipped" over on the last iteration?

65 Views Asked by At

So I creating the simple small project of Tic Tac Toe in python

Tic Tac Toe board in text with a, b, and c identifying columns and 0, 1, and 2 identifying rows

(Same board in text form):

     a   b   c

0    - | - | -

    -----------
1    - | - | -

    -----------
2    - | - | -

When I try to do this with just loops I get artifacts like "|" at end of rows and "---------" below row 2 when it's only supposed to be below rows 0 and 1. I was able to circumvent this with if statements, but I wonder if there is a better way.

I originally had

def print_board():
    print("     a   b   c")
    print("")
    print("0    " + coords[columns[0]][rows[0]] + " | " + coords[columns[1]][rows[0]] + " | " + coords[columns[2]][rows[0]])
    print("   -------------")
    print("1    " + coords[columns[0]][rows[1]] + " | " + coords[columns[1]][rows[1]] + " | " + coords[columns[2]][rows[1]])
    print("   -------------")
    print("2    " + coords[columns[0]][rows[2]] + " | " + coords[columns[1]][rows[2]] + " | " + coords[columns[2]][rows[2]])

This is the best design for this I could come up with, and it works.

def print_board():
    print("     a   b   c", end="\n\n")
    for r in range(3):
        print(str(r) + "    ", end="")
        for c in range(3):
            print(coords[columns[c]][rows[r]], end="")
            if c != 2:
                print(" | ", end="")
        print("\n")
        if r != 2:
            print("   -------------")

However, I feel like this could be better. Specifically I want to get rid of the if statements but get the same result. So I am wondering if I can skip parts of a loop on the last iteration?

2

There are 2 best solutions below

0
c p On BEST ANSWER

You can use the join function (https://docs.python.org/3/library/stdtypes.html#str.join) to insert separators only between the elements of a list, in this way you can avoid all the if statements:

def print_board():
    print("     a   b   c", end="\n\n")
    rows = [0, 1, 2]
    columns = ["a", "b", "c"]

    rows_formatted = []
    for r in rows:
        row_elements = []
        for c in columns:
            row_elements.append(coords[c][r])
        rows_formatted.append(f"{r}    {' | '.join(row_elements)}\n")
    print("   -------------\n".join(rows_formatted))

# Example usage:
coords = {
    "a": ["X", "O", "X"],
    "b": ["O", "X", "O"],
    "c": ["X", "O", "X"]
}

print_board()

Example output:

     a   b   c

0    X | O | X
   -------------
1    O | X | O
   -------------
2    X | O | X
2
Elerium115 On

You can do it in one line, with nested list comprehensions and joining them using the cols and rows separators.

values = [
  ["X", "X", "X"],
  ["X", "X", "X"],
  ["X", "X", "X"]
]

def print_board():
    print("\n  ----------\n".join([str(row) + "  " + " | ".join([val for val in values[row]]) for row in range(3)]))
    
print_board()

0  X | X | X
  ----------
1  X | X | X
  ----------
2  X | X | X

But this is a case where too pythonic is not much pythonic. Too obscure.

In a lot of cases, the first and/or last cases of a loop have to be considered a special cases and treated separately.

In this example, I print the first row as a special case, then in the loop I print first the separator and then the value.

You could print value and then separator and treat the last row as a special case, that would be the same approach.

For the columns I use a different approach: Construct the string as a comprehension list that I then convert to a string using | as a join element.

This is of course one approach to do it, but it's not uncommon in problems to treat the first or last elements separately as special cases.

values = [
  ["X", "X", "X"],
  ["X", "X", "X"],
  ["X", "X", "X"]
]

def print_board():
    # print the first row as a separate case
    print("0    " + " | ".join([val for val in values[0]]))
    
    for row in range(1, 3):
        print("   -------------")
        print(f"{row}    {' | '.join([val for val in values[row]])}")
    
print_board()


0    X | X | X
   -------------
1    X | X | X
   -------------
2    X | X | X