enumerate() produces index-and-value pairs while iterating an iterable. By default, counting starts at 0; use start=1 when display positions should begin at 1. section 21.2.2 section 21.4
Numbering an empty board
>>> board = 'XX.O.O...' >>> list(enumerate(board)) [(0, 'X'), (1, 'X'), (2, '.'), (3, 'O'), (4, '.'), (5, 'O'), (6, '.'), (7, '.'), (8, '.')] >>> list(enumerate(board, start=1)) [(1, 'X'), (2, 'X'), (3, '.'), (4, 'O'), (5, '.'), (6, 'O'), (7, '.'), (8, '.'), (9, '.')] Unpack each pair directly in a loop: `for i, char in enumerate(board, start=1)`. A list comprehension then replaces empty cells with their numbered positions while preserving X and O. section 21.2.2
def format_board(board):
"""Format the board"""
cells = [str(i) if c == '.' else c for i, c in enumerate(board, start=1)] #1
bar = '-------------'
cells_tmpl = '| {} | {} | {} |'
return '\n'.join([
bar,
cells_tmpl.format(*cells[:3]), bar, #2
cells_tmpl.format(*cells[3:6]), bar,
cells_tmpl.format(*cells[6:]), bar
])
See enumerate() used inside format_board() to create numbered cells for a printable grid. section 21.2.2


