#476 · Games and puzzles · Expert · 250 XP · about 50 min
A computer that never makes a mistake is playing tic-tac-toe, on the usual 3 by 3 board or on a bigger 4 by 4 one. board is a list of n strings of length n (n is 3 or 4), with 'X', 'O' and '.' for an empty square. X always moves first, so X is to move when both players have the same number of marks, and O is to move otherwise. A player wins by filling a whole row, a whole column or one of the two long diagonals with their mark; the game is a draw when the board fills up with no winner.
Both players play perfectly:
Moves are counted for both players together, up to the end of the game. Write best_move(board) that returns a tuple ((row, col), result) for the player to move: the square to play, and how the game ends with perfect play, 'win', 'draw' or 'loss' from that player's point of view. If several squares are equally good (the same result and, for a win or a loss, the same number of moves until the end), return the first of them in reading order: the smallest row, then the smallest column.
best_move(['XX.', 'OO.', '...']) # returns ((0, 2), 'win') best_move(['XO.', '.X.', '...']) # returns ((2, 2), 'loss') best_move(['...', '...', '...']) # returns ((0, 0), 'draw')
On the first board X wins at once by completing the top row. On the second, O is lost, but blocking the diagonal at (2, 2) makes the game last longest. On the empty board every first move leads to a draw, so the top left corner is returned.
First solves only, ranked by stars and then time.