Faster track to recognizing patterns in looping through nested sequences
I would write the loop like this:

for i, j, move in list_of_moves:
    assert(0 &lt;= i &lt; 3 and 0 &lt;= j &lt; 3 and move in 'XO')
    board[j][i] = move


or maybe:

VALID_MOVES = 'XO'
for i, j, move in list_of_moves:
    assert(0 &lt;= j &lt; len(board) and 0 &lt;= i &lt; len(board[j]) and move in VALID_MOVES)
    board[j][i] = move


depending on how general I needed the implementation to be.

Something that you might find helpful would be to step through your code in the Python debugger. Look at each line as it is executed and check that it makes sense. For example:

&gt;&gt;&gt; board = [[''] * 3 for _ in range(3)]
&gt;&gt;&gt; moves = [(1,1,'X'), (0,0,'O')]
&gt;&gt;&gt; import pdb
&gt;&gt;&gt; pdb.run("insertMoves(board, moves)")
&gt; &lt;string&gt;(1)&lt;module&gt;()
(Pdb) step
--Call--
&gt; cr32933.py(1)insertMoves()
-&gt; def insertMoves(board, list_of_moves):
(Pdb) step
&gt; cr32933.py(2)insertMoves()
-&gt; for move in list_of_moves:
(Pdb) step
&gt; cr32933.py(3)insertMoves()
-&gt; for i in range(0, 3):
(Pdb) print move
(1, 1, 'X')
(Pdb) step
&gt; cr32933.py(4)insertMoves()
-&gt; if move[0] == i:
(Pdb) print i
0
(Pdb) step
&gt; cr32933.py(3)insertMoves()
-&gt; for i in range(0, 3):
(Pdb) step
&gt; cr32933.py(4)insertMoves()
-&gt; if move[0] == i:
(Pdb) print i
1


At about this point (if not earlier) you should be saying to yourself, "why did I have to go round the loop in order to discover that move[0] has the value 1?"