Created
April 11, 2016 02:15
-
-
Save ana0/9aaa29450a36bb2c384ff2cca681023f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import random | |
class Board(object): | |
def __init__(self): | |
self.board = [[" "," "," "], [" "," "," "], [" "," "," "]] | |
def print_board(self): | |
topstr = " a b c" | |
linestr = " +-----+-----+-----+" | |
rowstr = "%s | %s | %s | %s |" | |
print topstr | |
for i, row in enumerate(self.board): | |
print linestr | |
print rowstr % (i, self.board[i][0], self.board[i][1], | |
self.board[i][2]) | |
print linestr | |
def set_position(self, position, char): | |
self.board[position[0]][position[1]] = char | |
return True | |
def look_for_win(self): | |
for i in range(len(self.board)): | |
# Check each row | |
if (self.board[i][0] == self.board[i][1] == self.board[i][2] | |
and self.board[i][0].isalpha()): | |
return self.board[i][0] | |
# Check each column | |
elif (self.board[0][i] == self.board[1][i] == self.board[2][i] | |
and self.board[0][i].isalpha()): | |
return self.board[0][i] | |
# Check diagonals | |
if (self.board[0][0] == self.board[1][1] == self.board[2][2] | |
and self.board[0][0].isalpha()): | |
return self.board[0][0] | |
if (self.board[0][2] == self.board[1][1] == self.board[2][0] | |
and self.board[0][2].isalpha()): | |
return self.board[0][2] | |
return False | |
def check_empty_spaces(self): | |
for row in self.board: | |
for i in row: | |
if i == " ": | |
return True | |
return False | |
class Game(object): | |
def __init__(self): | |
# Boolean triggers the outer game loop | |
self.playing_game = True | |
self.game_type = False | |
def set_game_type(self): | |
# At the moment, the game will force you to play a human | |
print "Would you like to play against another human or the computer?" | |
answer = raw_input("Type 'h' for human and 'c' for computer\n") | |
if answer.strip().lower() == "h": | |
print "You've chosen to play a human!\n" | |
self.game_type = "h" | |
elif answer.strip().lower() == "c": | |
print "You've chosen to play the computer!\n" | |
self.game_type = "c" | |
else: | |
print "I'm sorry that doesn't seem to be one of the options\n" | |
def set_players(self): | |
while not self.game_type: | |
self.set_game_type() | |
player_o = Player() | |
player_o.get_player_name("o") | |
if self.game_type == "c": | |
player_x = ComputerPlayer() | |
player_x.say_hello() | |
return [player_x, player_o] | |
player_x = Player() | |
player_x.get_player_name("x") | |
return [player_x, player_o] | |
def goes_first(self, players): | |
first = random.choice(players) | |
print "\nPlayer %s will go first" % first.name | |
not_first = [i for i in players if i != first] | |
players = [first, not_first[0]] | |
return players | |
def win(self, playing): | |
print "Congratilations %s, you won!" % playing.name | |
print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!" | |
return True | |
def tie(self): | |
print "The game is a tie!" | |
print "One of you should make more mistakes next time!" | |
def game_loop(self): | |
players = self.set_players() | |
board = Board() | |
players = self.goes_first(players) | |
board.print_board() | |
winner = board.look_for_win() | |
while not winner: | |
players[0].turn(board) | |
board.print_board() | |
winner = board.look_for_win() | |
if winner: | |
congratulations = self.win(players[0]) | |
break | |
elif not board.check_empty_spaces(): | |
self.tie() | |
break | |
players = [players[1], players[0]] | |
replay = self.play_again() | |
while not replay: | |
self.play_again() | |
def play_again(self): | |
answer = raw_input("Would you like to play again? 'y' or 'n'\n") | |
if answer.strip().lower() == "y": | |
print "Let's play again!" | |
return True | |
elif answer.strip().lower() == "n": | |
print "Ok, goodbye!" | |
self.playing_game = False | |
return True | |
else: | |
print "I'm sorry that doesn't seem to be one of the options" | |
return False | |
def tutorial(): | |
print "Welcome to tictactoe! Would you like to hear the instructions?" | |
answer = raw_input("Type 'y' or 'n' and then press Enter\n") | |
if answer.strip().lower() == "y": | |
print "This is the board:" | |
test_board = Board() | |
test_board.print_board() | |
print "You can declare a move by typing the name of the row and column" | |
print "For example typing, '0a' would place your marker like this:" | |
test_board.set_position((0,0),"x") | |
test_board.print_board() | |
print "When you have three marks in a row, you win!\n" | |
return True | |
elif answer.strip().lower() == "n": | |
print "ok!\n" | |
return True | |
else: | |
print "I'm sorry that doesn't seem to be one of the options\n" | |
return False | |
class Player(object): | |
def __init__(self): | |
self.name = "" | |
self.marker = "" | |
def get_player_name(self, mark): | |
name = raw_input("Player %s enter your name\n" % mark) | |
self.name = name | |
self.marker = mark | |
def parse_position(self, position, board): | |
# Sort the input string | |
# This is so players can enter their row, column in any order | |
row =[c for c in position if c in "012"] | |
column = [c.lower() for c in position if c in "abcABC"] | |
# Was it a valid input? | |
if len(row) != 1 or len(column) != 1: | |
print "That doesn't seem to be a valid position\n" | |
return False | |
# Translate list/letter input to ints | |
row, column = int(row[0]), column[0] | |
if column == "a": | |
column = 0 | |
elif column == "b": | |
column = 1 | |
else: | |
column = 2 | |
# Make sure the space is empty | |
if board.board[row][column] != " ": | |
print "Sorry that spot is already taken\n" | |
return False | |
return (row, column) | |
def turn(self, board): | |
move = raw_input("Player %s make your move!\n" % self.name) | |
valid_position = self.parse_position(move, board) | |
while not valid_position: | |
move = raw_input("Player %s make your move!\n" % self.name) | |
valid_position = self.parse_position(move, board) | |
board.set_position(valid_position, self.marker) | |
class ComputerPlayer(object): | |
def __init__(self): | |
self.hellostr = "\n'Hi I'm the computer, I'll be playing as 'x''\n" | |
self.name = "Computer" | |
self.marker = "x" | |
self.opponent = "o" | |
def say_hello(self): | |
print self.hellostr | |
def get_possible_moves(self, b): | |
possible_moves = [] | |
priority = 0 | |
for column, row in enumerate(b.board): | |
for i, row in enumerate(row): | |
if b.board[i][column] != " ": | |
continue | |
else: | |
possible_moves.append((i,column)) | |
return possible_moves | |
def check_row(self, b, move, char): | |
count = 0 | |
for i in range(len(b.board)): | |
if (move[0],i) != move and b.board[move[0]][i] == char: | |
count += 1 | |
return count | |
def check_column(self, b, move, char): | |
count = 0 | |
for i in range(len(b.board)): | |
if (i,move[1]) != move and b.board[i][move[1]] == char: | |
count += 1 | |
return count | |
def check_diagonal_one(self, b, move, char): | |
count = 0 | |
if move[0] == move[1]: | |
for m in [(0,0),(1,1),(2,2)]: | |
if m != move and b.board[m[0]][m[1]] == char: | |
count += 1 | |
return count | |
def check_diagonal_two(self, b, move, char): | |
count = 0 | |
if move[0]+move[1] == len(b.board)-1: | |
for m in [(0,2),(1,1),(2,0)]: | |
if m != move and b.board[m[0]][m[1]] == char: | |
count += 1 | |
return count | |
def prioritize(self, board, move, char): | |
priority = [] | |
priority.append(self.check_row(board, move, char)) | |
priority.append(self.check_column(board, move, char)) | |
priority.append(self.check_diagonal_one(board, move, char)) | |
priority.append(self.check_diagonal_two(board, move, char)) | |
return priority | |
def check_for_win_in_one(self, board, moves, char): | |
for move in moves: | |
can_win = self.prioritize(board, move, char) | |
if 2 in can_win: | |
return move | |
return False | |
def can_checkmate(self, board, moves, char): | |
for move in moves: | |
checkmate = self.prioritize(board, move, char) | |
if checkmate.count(1) >= 2: | |
checkmate = self.prioritize(board, move, " ") | |
if checkmate.count(1) >= 2: | |
return move | |
return False | |
def best_move(self, board): | |
moves = self.get_possible_moves(board) | |
if len(moves) == 1: | |
return moves[0] | |
if len(moves) >= 8: | |
rand = random.choice([(0,0),(0,2),(2,0),(2,2),(1,1),(1,1)]) | |
while rand not in moves: | |
rand = random.choice([(0,0),(0,2),(2,0),(2,2),(1,1),(1,1)]) | |
return rand | |
if self.check_for_win_in_one(board, moves, self.marker): | |
return self.check_for_win_in_one(board, moves, self.marker) | |
if self.check_for_win_in_one(board, moves, self.opponent): | |
return self.check_for_win_in_one(board, moves, self.opponent) | |
if self.can_checkmate(board, moves, self.marker): | |
return self.can_checkmate(board, moves, self.marker) | |
if self.can_checkmate(board, moves, self.opponent): | |
return self.can_checkmate(board, moves, self.opponent) | |
rand = random.choice([(0,1),(1,0),(2,1),(1,2),(1,1)]) | |
while rand not in moves: | |
rand = random.choice([(0,1),(1,0),(2,1),(1,2),(1,1)]) | |
return rand | |
def turn(self, b): | |
move = self.best_move(b) | |
b.set_position(move, self.marker) | |
def run(): | |
play_instructions = tutorial() | |
while not play_instructions: | |
play_instructions = tutorial() | |
game = Game() | |
while game.playing_game: | |
game.game_loop() | |
if __name__ == "__main__": | |
run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment