TicTacToe where the computer plays random moves against itself
Some of your functions can use list comprehensions.

As you seem to know maths, you may have come across 'set-builder notation',
and that's what list comprehension are based off:

\$S = \{2 \times x | x \in \{0, 1, ..., 9\}, x^2 &gt; 3\}\$

Which in Python is:

[2 * x for x in range(10) if x ** 2 &gt; 3]


I would use it in:


find_move for an improvement in clarity.

def find_move(board, player):
    return random.choice([pos for pos in range(9) if board[pos] == 0])

write_board to use less prints. It's harder to read however.

print '\n'.join([
    ''.join([letter[row + col] for col in range(3)])
    for row in range(0, 3, 9)
])

check_winner you can make your for pos in seq one.
Using all.

for player in [1, 2]:
    for seq in winning_rows:
        if all([board[pos] == player for pos in seq]):
            return player

I'm surprised you didn't make a new_board function. Which could be:

def new_board():
    return [0 for _ in range(9)]


Alternatively, as noted by @i-live-in-a-storm-drain, if you are ok with shallow copy's you could change it to:

def new_board():
    return [0] * 9


The down-side to this is if you mutate any of the items, then you mutate all of them. For example you wouldn't want to make a 2D list with it.

&gt;&gt;&gt; a = [[0] * 3] * 3
&gt;&gt;&gt; a[0][0] = 1
&gt;&gt;&gt; a
[[1, 0, 0], [1, 0, 0], [1, 0, 0]]


Your function make_move seems, kinda pointless...
I would use board[move] = player over the function.
You should use is when comparing to singletons, None.

# Bad
if winner != None:

# Good
if winner is not None:

You could make the win conditions a list, and print from that.

win_statments = ["Player 1 (X) wins!", "Player 2 (O) wins!", "Game is a draw!"]
print win_statments[winner]

For check_winner you can use the fact 0 == False (Not 0 is False).
With Python's builtin all to check if all of them are not 0.

if not all(board):
    return None

As this is Python2 it's recommended to use xrange rather than range for almost everything.
You'll get a, minimal, speed increase in most situations.

However as noted by @Janos, you could opt to keep them as range, for an easier transition to Python3. This is as there is no xrange in Python3.
You should only need to change your prints to functions for this to work in Python3.

# Change to these:
print("Player 1 (X) wins!")

# in `make_move`
for col in range(3):
    print(letter[board[row*3+col]], end='')
print()