PDA

View Full Version : [SOLVED] Python - Simple Tic-Tac-Toe Game



azurepancake
September 19th, 2008, 08:48 PM
I've been learning Python through a book titled, "Python Programming: For the Absolute Beginner" and I am currently in the chapter dealing with functions.

The last exercise of the chapter is to create a text-based, Tic-Tac-Toe game where a human competes against the computer. So I walked through the code, learned how it worked (at least, I thought I did) and copied the code, line-for-line into Gedit.

When I thought I was done, I executed the program and ran into a couple semantical issues that I am yet to resolve. So, I come to the great minds of the Ubuntu forums for assistance!

First, here is the code:




X = "X"
O = "O"
EMPTY = " "
TIE = "TIE"
NUM_SQUARES = 9

def display_instruct():
print \
"""
Welcome to the greatest intellectual challenge of all time: Tic-Tac-Toe.
This will be a showdown between your human brain and my silicon processor.

You will make your move known by entering a number, 0 - 8. The number
will correspond to the board position as illustrated:

0 | 1 | 2
-----------
3 | 4 | 5
-----------
6 | 7 | 8

Prepare your self, human. The ultimate battle is about to begin. \n
"""
def ask_yes_no(question):
response = None
while response not in ("y", "n"):
response = raw_input(question).lower()
return response

def ask_number(question, low, high):
response = None
while response not in range(low, high):
response = int(raw_input(question))
return response

def pieces():
go_first = ask_yes_no("Do you require the first move? (y/n): ")
if go_first == "y":
print "\nThen take the first move. You will need it."
human = X
computer = O
else:
print "\nYour bravery will be your undoing... I will go first."
computer = X
human = O
return computer, human

def new_board():
board = []
for square in range(NUM_SQUARES):
board.append(EMPTY)
return board

def display_board(board):
print "\n\t", board[0], "|", board[1], "|", board[2]
print "\t", "---------"
print "\t", board[3], "|", board[4], "|", board[5]
print "\t", "---------"
print "\t", board[6], "|", board[7], "|", board[8], "\n"

def legal_moves(board):
moves = []
for square in range(NUM_SQUARES):
if board[square] == EMPTY:
moves.append(square)
return moves

def winner(board):
WAYS_TO_WIN = ((0, 1, 2),
(3, 4, 5),
(6, 7, 8),
(0, 3, 6),
(1, 4, 7),
(2, 5, 8),
(0, 4, 8),
(2, 4, 6))

for row in WAYS_TO_WIN:
if board[row[0]] == board[row[1]] == board[row[2]] != EMPTY:
winner = board[row[0]]
return winner

if EMPTY not in board:
return TIE
return None

def human_move(board, human):
legal = legal_moves(board)
move = None
while move not in legal:
move = ask_number("Where will you move? (0 - 8): ", 0, NUM_SQUARES)
if move not in legal:
print "\nThat square is already occupied, foolish human. Choose another.\n"
print "Fine..."
return move

def computer_move(board, computer, human):
board = board[:]
BEST_MOVES = (4, 0, 2, 6, 8, 1, 3, 5, 7)
print "I shall take square number",

# if computer can win, take that move
for move in legal_moves(board):
board[move] = computer
if winner(board) == computer:
print move
return move
board[move] = EMPTY

# if human can win, block that move
for move in legal_moves(board):
board[move] = human
if winner(board) == human:
print move
return move
board[move] = EMPTY

# since no one can win on next move, pick best open square
for move in BEST_MOVES:
if move in legal_moves(board):
print move
return move

def next_turn(turn):
if turn == X:
return 0
else:
return X

def congrat_winner(the_winner, computer, human):
if the_winner != TIE:
print the_winner, "won!\n"
else:
print "It's a tie!\n"
if the_winner == computer:
print "As I predicted, human, I am triumphant once more. \n" \
"Proof that computers are superior to humans in all regards.\n"

elif the_winner == human:
print "No, no! It cannot be! Somehow you tricked me, human. \n" \
"But never again! I, the computer, so swears it\n!"

elif the_winner == TIE:
print "You were most lucky, human, and somehow managed to tie me. \n" \
"Celebrate today... for this is the best you will ever achieve.\n"

def main():
display_instruct()
computer, human = pieces()
turn = X
board = new_board()
display_board(board)

while not winner(board):
if turn == human:
move = human_move(board, human)
board[move] = human
else:
move = computer_move(board, computer, human)
board[move] = computer
display_board(board)
turn = next_turn(turn)
the_winner = winner(board)
congrat_winner(the_winner, computer, human)

main()


When you execute the program, everything goes well until you start to put your 'X' or 'O' on the board. Every round it says "None won!" and when you have three of your marks in a row, the program does not render it as a win. It will recognize the game as a tie though, once all slots are filled.

Also, the computer does not seem to be intelligently placing it's marks on the board, like I have it programmed to do (computer_move function).

Sorry if my code is hard-to-read due to lack of comments. If you need me to clear up on anything, please ask!

If anyone can give me a hand with this, I'd forever be in your debt. I've gone over the books code several times and just can't get this working!

Thanks!

azurepancake
September 19th, 2008, 09:49 PM
Found the problem..

Incorrect Code:



def main():
display_instruct()
computer, human = pieces()
turn = X
board = new_board()
display_board(board)

while not winner(board):
if turn == human:
move = human_move(board, human)
board[move] = human
else:
move = computer_move(board, computer, human)
board[move] = computer
display_board(board)
turn = next_turn(turn)
the_winner = winner(board)
congrat_winner(the_winner, computer, human)



Correct Code:



def main():
display_instruct()
computer, human = pieces()
turn = X
board = new_board()
display_board(board)

while not winner(board):
if turn == human:
move = human_move(board, human)
board[move] = human
else:
move = computer_move(board, computer, human)
board[move] = computer
display_board(board)
turn = next_turn(turn)
the_winner = winner(board)
congrat_winner(the_winner, computer, human)


Code would only execute when the 'else' statement was true.