9
\$\begingroup\$

I wrote a two player Noughts and Crosses game in Python 3, and came here to ask how I can improve this code.

import random
cell = ['1', '2', '3', '4', '5', '6', '7', '8', '9']
board = '\n\t ' + cell[0] + ' | ' + cell[1] + ' | ' + cell[2] + '\n\t-----------\n\t ' + cell[3] + ' | ' + cell[4] + ' | ' + cell[5] + '\n\t-----------\n\t ' + cell[6] + ' | ' + cell[7] + ' | ' + cell[8]
def owin(cell):
    return cell[0] == cell[1] == cell[2] == 'O' or cell[3] == cell[4] == cell[5] == 'O' or cell[6] == cell[7] == cell[8] == 'O' or cell[0] == cell[3] == cell[6] == 'O' or cell[1] == cell[4] == cell[7] == 'O' or cell[2] == cell[5] == cell[8] == 'O' or cell[0] == cell[4] == cell[8] == 'O' or cell[2] == cell[4] == cell[6] == 'O'
def xwin(cell):
    return cell[0] == cell[1] == cell[2] == 'X' or cell[3] == cell[4] == cell[5] == 'X' or cell[6] == cell[7] == cell[8] == 'X' or cell[0] == cell[3] == cell[6] == 'X' or cell[1] == cell[4] == cell[7] == 'X' or cell[2] == cell[5] == cell[8] == 'X' or cell[0] == cell[4] == cell[8] == 'X' or cell[2] == cell[4] == cell[6] == 'X'
def tie(cell):
    return cell[0] in ('O', 'X') and cell[1] in ('O', 'X') and cell[2] in ('O', 'X') and cell[3] in ('O', 'X') and cell[4] in ('O', 'X') and cell[5] in ('O', 'X') and cell[6] in ('O', 'X') and cell[7] in ('O', 'X') and cell[8] in ('O', 'X')
print('\tNOUGHTS AND CROSSES\n\t\tBy Lewis Cornwall')
instructions = input('Would you like to read the instructions? (y/n)')
if instructions == 'y':
    print('\nEach player takes turns to place a peice on the following grid:\n\n\t 1 | 2 | 3\n\t-----------\n\t 4 | 5 | 6\n\t-----------\n\t 7 | 8 | 9\n\nBy inputing a vaule when prompted. The first to 3 peices in a row wins.')
player1 = input('Enter player 1\'s name: ')
player2 = input('Enter player 2\'s name: ')
print(player1 + ', you are O and ' + player2 + ', you are X.')
nextPlayer = player1
while not(owin(cell) or xwin(cell)) and not tie(cell):
    print('This is the board:\n' + board)
    if nextPlayer == player1:
        move = input('\n' + player1 + ', select a number (1 - 9) to place your peice: ')
        cell[int(move) - 1] = 'O'
        board = '\n\t ' + cell[0] + ' | ' + cell[1] + ' | ' + cell[2] + '\n\t-----------\n\t ' + cell[3] + ' | ' + cell[4] + ' | ' + cell[5] + '\n\t-----------\n\t ' + cell[6] + ' | ' + cell[7] + ' | ' + cell[8]
        nextPlayer = player2
    else:
        move = input('\n' + player2 + ', select a number (1 - 9) to place your peice: ')
        cell[int(move) - 1] = 'X'
        board = '\n\t ' + cell[0] + ' | ' + cell[1] + ' | ' + cell[2] + '\n\t-----------\n\t ' + cell[3] + ' | ' + cell[4] + ' | ' + cell[5] + '\n\t-----------\n\t ' + cell[6] + ' | ' + cell[7] + ' | ' + cell[8]
        nextPlayer = player1
if owin(cell):
    print('Well done, ' + player1 + ', you won!')
elif xwin(cell):
    print('Well done, ' + player2 + ', you won!')
else:
    print('Unfortunately, neither of you were able to win today.')
input('Press <enter> to quit.')
\$\endgroup\$

3 Answers 3

4
+50
\$\begingroup\$

Some notes:

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

Try to be less verbose: cell = "123456789".split() or cell = [str(n) for n in range(1, 10)]. Anyway, conceptually it's very dubious you initialize the board with its number instead of its state. Also, cell is not a good name, it's a collection, so cells.

board = '\n\t ' + cell[0] + ...

Don't write such a long lines, split them to fit a sound max width (80/100/...). Anyway, here the problem is that you shouldn't do that manually, do it programmatically (grouped from itertools):

board = "\n\t-----------\n\t".join(" | ".join(xs) for xs in grouped(cell, 3)) 

return cell[0] == cell1 == cell[2] == 'O' or cell[3] == cell[4] == cell[5] == 'O' or cell[6] == cell[7] == cell[8] == 'O' or cell[0] == cell[3] == cell[6] == 'O' or cell1 == cell[4] == cell[7] == 'O' or cell[2] == cell[5] == cell[8]== 'O

Ditto, use code:

groups = grouped(cell, 3)
any(all(x == 'O' for x in xs) for xs in [groups, zip(*groups)])

Note that you are not checking if a cell has already a piece.

\$\endgroup\$
0
\$\begingroup\$

Do not repeat code for each player. Instead, create functions with appropriate parameters. For example, instead of if owin(cell): you could have a win function that can be used like

if win(cell, 'O'):

or

if win(cell) == 'O':
\$\endgroup\$
-1
\$\begingroup\$

You should change input to raw_input so that its automatically passed as a string.

\$\endgroup\$
2
  • 2
    \$\begingroup\$ this appears to be python3, so that doesn't apply. \$\endgroup\$ Mar 12, 2013 at 17:46
  • 1
    \$\begingroup\$ I am using Python 3, so raw_input should not be used \$\endgroup\$ Mar 12, 2013 at 17:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.