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.')
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Mar 12, 2013 at 11:42
\$\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.

answered Mar 12, 2013 at 12:23
\$\endgroup\$
1
\$\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':
answered Mar 12, 2013 at 12:51
\$\endgroup\$
-1
\$\begingroup\$

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

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

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.