How It Works

The first thing this version does is to create a matrix called win_list, which lists all eight ways the game can be won. I could have used row-column coordinates such as “(0,0), (0,1), (0,2),” representing the top row, but for Tic-Tac-Toe, it’s easier to use cell numbers 1 through 9, at this point, and then translate into row-column coordinates as needed.

The ways of winning the game are therefore summarized by the following combinations. In detecting win conditions, the program is only interested in these combinations of cells.

win_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [1, 4, 7], [2, 5, 8], [3, 6, 9], [1, 5, 9], [3, 5, 7]]

The test_win function takes a coordinate pair—(r, c), which is expressed in zero-based indexes—and produces a cell number from 1 to 9.

cell_n = r * 3 + c + 1    #Get cell num. 1 to 9.

We need to find winning combinations that contain this cell number. The variable x refers to a member of win_list: that is, each x is a three number combo such as [1, 2, 3] or [4, 5, 6] that refers to one Tic-Tac-Toe combination. From this list of lists (win_list), we build my_win_list, a group of lists to be tested. In other words, look at each of the lists inside win_list (itself a list of winning combinations); append a list onto my_win_list if and only if it contains cell_n, the cell number.

my_win_list = []
    for x in win_list:
        if cell_n in x:
            my_win_list.append(x)

This means the following: if, for example, the cell number is 1, we want to find all the Tic-Tac-Toe combinations that include 1. So we get the following list of lists, by (in effect) saying, “Save all lists from win_list in my_win_listthat contain the number 1.” [[1, 2, 3], [1, 4, 7], [1, 5, 9]]

As another example, if the cell number is 5, we want to find all the Tic-Tac-Toe combinations that include the cell number 5. So, we get the following list of lists by saying, “Use all lists from win_list that contain the number 5.” [[4, 5, 6], [2, 5, 8], [1, 5, 9], [3, 5, 7]]

Each of these three-element lists is then passed to the test_ways function. That function returns the number of Xs, Os, and blanks in the combination passed to it. If three Xs or three Os are found, then there is a winner. Congratulate the winner and terminate!

For example, if positions 1, 5, and 9 all contain an X, then the X player wins. These positions are converted to matrix elements (0, 0), (1, 1), and (2, 2); then we detect how many Xs and Os are at these positions.

The test_way function does the actual counting of letters, looking for three of the same kind. First, it builds up a list called letters_list, which contains individual characters X, O, and ., found in the corresponding matrix squares. The count method makes it easy to return the three counts—the number of Xs, the number of Os, and the number of dots. A typical return value might be 1, 1, 1, which means that one of each type of letter was found.

def test_way(cell_list):
    letters_list = []
    # Create list of the form ['X', '.', 'O']
    for cell_n in cell_list:
        r = (cell_n - 1) // 3
        c = (cell_n - 1) % 3
        letters_list.append(mat[r][c])
    num_x = letters_list.count('X') # How many X's?
    num_o = letters_list.count('O') # How many O's?
    num_blanks = letters_list.count('.')
    return num_x, num_o, num_blanks

A return value of 3, 0, 0 would mean three Xs were found. A return value of 0, 3, 0 would mean that three Os were found. Clearly, when three Xs or three Os are found in any winning combination—such as in the list [1, 2, 3]—someone has won the game.

Last updated

Was this helpful?