Here's the code..it's the same thing.. created by
PHP Code:
#!/usr/bin/python
import random
class TicTacToe(object):
"""A TicTacTow class
"""
MID = ((1, 1),) #middle square
SIDE = ((0, 1), (1, 0), (1, 2), (2, 1)) #side squares
CORN = ((0, 0), (0, 2), (2, 0), (2, 2)) #corner squares
def __init__(self, comp_first, comp_chr='X', player_chr='O'):
"""Starts up the class
Parameters: comp_first - Decides who goes first, True for the computer
or False for the player.
comp_chr - The symbol used for the computer. Should be a
single length string.
player_chr - The symbol used for the player. Should be a
single length string.
"""
self._grid = {} #keys: 2-tuple coords, values: comp_chr or player_chr
self._computer = comp_chr
self._player = player_chr
self._branch = "" #the branch that that is being played
#(corner='a', edge='b', center='c')
self._last_move = 0 #The last move played by the computer. Values are
#0, 1, 2, 3, and 5
self._comp_first = comp_first #Records who went first. True is
#computer went first, False is player
#went first.
def get_first_move(self):
"""Returns: The playing field grid with the computer's first move.
This method should only be called if the object was created with
comp_first=True, and then only once at the start"""
if self._last_move == 0 and self._comp_first:
first_move = self._comp_move()[0]
self._last_computer_move = first_move
self._grid[first_move] = self._computer
return self._grid
else:
print "RAISE ERROR"
def submit(self, move):
"""Submits a move.
Returns: A tuple containing the _grid dictionary (including the
computer's new move) and a string value indicating a win-tie situation.
Values for the string are 'win', and 'tie' (there is no lose value
since the computer never loses :P).
"""
self._grid[move] = self._player
self._last_player_move = move
if self._comp_first: #computer went first
new_move, win_tie_value = self._comp_move()
self._last_computer_move = new_move
self._grid[new_move] = self._computer
else: #player went first
if self._last_move == 4:
#On the last move, the computer shouldn't generate a response
#If the player is able to make a last move, it will always be
#a tie, because the computer cannot lose.
win_tie_value = "tie"
else:
new_move, win_tie_value = self._player_move()
self._last_computer_move = new_move
self._grid[new_move] = self._computer
return (self._grid, win_tie_value)
def _win(self):
"""Checks to see if the computer can win on the next turn.
Returns: The coordinates in a tuple if the win can take place.
Otherwise, None is returned.
"""
pass
def _two_line(self, win_or_block):
"""Checks to see if the computer should block or take a win. This
happens if there is two of the same piece in a line and the other
spot in the line is blank.
Parameters: win_or_block - Decides if the algorithm looks for a
possible win or a block that needs to take
place. 'win' and 'block' are the only
possible values.
Returns: The coordinates in a tuple if the block should take place or
the win can take place. Otherwise, None is returned.
"""
seq = [(((0,0),(1,0),(2,0)), ((0,1),(1,1),(2,1)), ((0,2),(1,2),(2,2))),
(((0,0),(0,1),(0,2)), ((1,0),(1,1),(1,2)), ((2,0),(2,1),(2,2))),
(((0,2),(1,1),(2,0)), ((0,0),(1,1),(2,2)))] #line 1 - rows
#line 2 - column
for line_type in seq: #line 3 - diagonals
for member in line_type:
piece_counter = 0 #counts the pieces in the row/column/diag
empty_counter = 0 #counts the empty places
for x, y in member:
if (x, y) not in self._grid.keys():
empty_counter += 1
return_x = x
return_y = y
else:
if win_or_block == 'win':
if self._grid[x, y] == self._computer:
piece_counter += 1
elif win_or_block == 'block':
if self._grid[x, y] == self._player:
piece_counter += 1
if piece_counter == 2 and empty_counter == 1:
return (return_x, return_y)
return None #returns None if no blocks have been found
def _comp_move(self):
"""Returns the best move for the computer to make next if the compter
went first initially.
The moves are done according to the logic tree. In the tree X is the
computer and O is the player.
|
1 X-corner
_____________________|__________________________
| | |
O-corner O-edge O-center
| | |
2 X-corner(a) X-center(b) X-caddy_corner(c)
| | _______|________
| | | |
O-block O-block O-corner O-edge
| _____|_____ | |
| | | | ....|....
3 X-corner X-block X-corner X-corner .X-block.
not_bordered .........
"""
status = None #default value for status
#first checks if there are any winning moves
if self._two_line("win") != None:
square = self._two_line("win")
status = "win"
else:
#this is the first move
if self._last_move == 0:
square = self._rnd_corner()
self._last_move = 1
#this is the second move
elif self._last_move == 1:
if self._last_player_move in self.CORN:
self._branch = 'a'
square = self._rnd_corner()
elif self._last_player_move in self.SIDE:
self._branch = 'b'
square, = self.MID
elif self._last_player_move in self.MID:
self._branch = 'c'
x, y = self._last_computer_move
square = (2 - x, 2 - y)
self._last_move = 2
#this is the third move
elif self._last_move == 2:
if self._branch == 'a':
square = self._rnd_corner()
elif self._branch == 'b':
if self._two_line("block") != None:
square = self._two_line("block")
else:
possible_corners = []
for corner in self.CORN:
if corner not in self._grid.keys():
possible_corners.append(corner)
for x, y in possible_corners:
if (x, 1) not in self._grid.keys() and
(1, y) not in self._grid.keys():
square = x, y
elif self._branch == 'c':
if self._last_player_move in self.CORN:
square = self._rnd_corner()
elif self._last_player_move in self.SIDE:
square = self._two_line("block")
self._last_move = 3
#This is move 4 & 5. It is only executed in response to a c-branch
else: #draw
square = self._two_line("block")
if self._last_move == 4:
status = "tie"
self._last_move += 1
return (square, status)
def _player_move(self):
"""Returns the best move for the computer to make next if the player
went first initially.
The moves are done according to the logic tree. In the tree X is the
computer and O is the player. Dotted lines indicates repition after
the first run through.
__________________________|_______
|(a) |(b)
O-center O-not_center
| |
1 X-corner X-center
| _________________|__________________
.........|........ | | |
. O-any-move . O-1edge,1corner O-both-edge O-both-corner
. ____|___ . ___|____ ___|____ ____|___
. | | . | | | | | |
. | | . | | both-edges one-edge | |
. | | . | |brder-corner brder-corner| |
. | | . |(ba) |(bb) |(bc) |(bd) |(be) |(bf)
2 .X-block X-corner. X-block X-caddy X-cornered X-edge X-block X-edge
.................. | corner square | | |
....|... ....|... ...|.... | ...|.... ...|....
.block/. .block/. .block/. O-block .block/. .block/.
.random. .random. .random. | .random. .random.
........ ........ ........ | ........ ........
3 X-corner-next
to-X-edge
"""
status = None #default value of status is None
#first checks if there are any winning moves
if self._two_line("win") != None:
square = self._two_line("win")
status = "win"
else:
#this is the first move
if self._last_move == 0:
if self._last_player_move in self.MID:
square = self._rnd_corner()
self._branch = 'a'
else:
square, = self.MID
self._branch = 'b'
self._last_move = 1
#this is the second move
elif self._last_move == 1:
if self._branch == 'a':
if self._two_line("block") != None:
square = self._two_line("block")
else:
square = self._rnd_corner()
elif self._branch == 'b':
side_count = 0
corner_count = 0
for x, y in self._grid.keys():
if self._grid[x, y] == self._player:
if (x, y) in self.SIDE:
side_count += 1
elif (x, y) in self.CORN:
corner_count += 1
if side_count == 1 and corner_count == 1:
if self._two_line("block") != None:
square = self._two_line("block")
self._branch = "ba"
else:
for x, y in self.CORN:
if (x, y) in self._grid.keys():
if self._grid[x, y] == self._player:
square = (2 - x, 2 - y)
self._branch = "bb"
elif side_count == 2:
side_pieces = []
for x, y in self.SIDE:
if (x, y) in self._grid.keys():
side_pieces.append((x, y))
x1, y1 = side_pieces[0]
x2, y2 = side_pieces[1]
if abs(x1 - x2) == 1:
if x1 != 1:
new_x = x1
else:
new_x = x2
if y1 != 1:
new_y = y1
else:
new_y = y2
square = (new_x, new_y)
self._branch = "bc"
else:
square = self._rnd_side()
self._branch = "bd"
elif corner_count == 2:
if self._two_line("block") != None:
square = self._two_line("block")
self._branch = "be"
else:
square = self._rnd_side()
self._branch = "bf"
self._last_move = 2
#this is the third move
elif self._last_move == 2:
#branch 'a'
if self._branch == 'a':
if self._two_line("block") != None:
square = self._two_line("block")
else:
square = self._rnd_corner()
#all other branches
elif self._branch in ("ba", "bb", "bc", "be", "bf"):
if self._two_line("block") != None:
square = self._two_line("block")
else:
square = self._rnd_square()
#branch "bd"
elif self._branch == "bd":
possible = []
last_x, last_y = self._last_computer_move
for x, y in self.CORN:
if x == last_x or y == last_y:
possible.append((x, y))
square = random.choice(possible)
self._last_move = 3
#this is the fourth move
elif self._last_move == 3:
if self._two_line("block") != None:
square = self._two_line("block")
else:
square = self._rnd_square()
self._last_move = 4
return (square, status)
def _rnd_side(self):
"""Returns: a tuple containing the coordinates to a random side edge
that has yet to be taken.
"""
while True:
x, y = random.choice(self.SIDE)
if (x, y) not in self._grid.keys(): break
return (x, y)
def _rnd_corner(self):
"""Returns: a tuple containing the coordinates to a random corner
that has yet to be taken.
"""
while True:
x, y = random.choice(self.CORN)
if (x, y) not in self._grid.keys(): break
return (x, y)
def _rnd_square(self):
"""Returns: a tuple containing the coordinates to a random square
that has yet to be taken.
"""
possible = []
for x in range(3):
for y in range(3):
if (x, y) not in self._grid.keys():
possible.append((x, y))
return random.choice(possible)
def string_grid(grid):
"""Creates a string version of a 3x3 Tic Tac Toe grid.
Parameters: grid - the grid that is to be created
Returns: a string representation of grid.
"""
output_string = "\n"
for y in range(3):
for x in range(3):
if (x, y) in grid.keys():
output_string += grid[x, y] + " "
else:
output_string += '- '
output_string += '\n'
return output_string
def get_input(tictactoe_obj):
"""Gets input from the user about which position they wish to put their
piece. Entered corespond with the following positions: 7 8 9
4 5 6
tictactoe_obj is the current game being played. 1 2 3
Returns: A tuple containing the coordinates of the piece.
"""
while True:
#Gets a set of coordinates
while True:
valid_num = False
user_input = raw_input("Please enter a number between 1 and 9:\n")
if user_input in ('1', '2', '3', '4', '5', '6', '7', '8', '9'):
valid_num = True
x = (int(user_input) - 1) % 3
y = 2 - (int(user_input) - 1) // 3
coord = (x, y)
else:
print "Invalid answer"
if valid_num: break
#makes sure the coordinates aren't already taken
if coord not in tictactoe_obj._grid.keys():
taken = False
else:
taken = True
print "That place is already taken"
if not taken: break
return coord
if __name__ == '__main__':
#initialises score counters (there is no player_wins because
computer_wins = 0 #the player cannot win)
ties = 0
#prints instructions
print "****************************************"
print "* *"
print "* Tic Tac Toe 1.0.0 *"
print "* *"
print "****************************************"
print " "
print "Tic Tac Toe is released under the "
print "GPL (c) 2008 Peter Stace. "
print " "
print "Instructions: "
print "When entering a place to put a piece, "
print "use the number pad to enter a number "
print "between 1 and 9. The position on the "
print "number on the number pad coresponds to "
print "the square as follows: "
print " "
print " 7 | 8 | 9 "
print " ---+---+--- "
print " 4 | 5 | 6 "
print " ---+---+--- "
print " 1 | 2 | 3 "
print " "
print "The computer is X and the player is O "
print " "
computer_first = False
while True:
computer_first = not computer_first
#says who will go first
current_game = TicTacToe(computer_first)
if computer_first:
print "\nComputer goes first"
print string_grid(current_game.get_first_move())
else:
print "\nPlayer goes first"
#plays the game
while True:
grid, status = current_game.submit(get_input(current_game))
print string_grid(grid)
if status != None:
if status == "win":
print "The computer has won\n"
computer_wins += 1
elif status == "tie":
print "You have tied against the computer\n"
ties += 1
print """Score:\n\nComputer: %s\nPlayer: 0\nTies: %s\n"""
% (computer_wins, ties)
if status != None: break
#finds out if the player wants to play again
while True:
answer = raw_input("Would you like to play again? y/n ")
if answer not in ('y', 'n'):
print "Please answer y or n"
valid_answer = False
else:
valid_answer = True
if valid_answer == True: break
if answer == 'n': break