Last active
April 28, 2018 06:07
-
-
Save limitpointinf0/ed4f8a9861d65515a1a510e225ecd728 to your computer and use it in GitHub Desktop.
Random Tic Tac Toe Game Simulator
This file contains 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
""" | |
This script was created for the purpose of machine learning on tic-tac-toe. | |
You may extend the board to any square size. | |
the script will write to two csv files: one for predictors and the other for target | |
Special predictor Values: | |
dd - filled space from either player winning to pad the empty spaces | |
Target Variable Values: | |
1 - Player 1 has won | |
0 - Player 1 has lost | |
SM - Stalemate | |
""" | |
import itertools | |
import numpy as np | |
import random | |
import string | |
import time | |
#player has the ability to examine the board for possible moves and choose a random blank space to play on | |
class Player(): | |
def __init__(self, piece): | |
"""piece - numerical value representing that player's piece""" | |
self.piece = piece | |
def examine(self, b): | |
"""examine the board b for any empty spaces""" | |
free_space = [(i,j) for i,j in itertools.product(range(b.shape[0]), range(b.shape[1])) if b[i,j] == 0] | |
return free_space | |
def play_random(self, b, available): | |
"""make a random move from the available spaces. Should pass the output of examine as the parameter available""" | |
r = random.choice(available) | |
b[r[0], r[1]] = self.piece | |
return r | |
""" | |
The following functions are self explanatory. Checking horizontals, verticals, and diagonals for any wins. | |
b should be a square numpy array | |
side will be the length of the side of b | |
""" | |
def check_horiz(b, side): | |
win = False | |
way = 'no win' | |
for i in range(side): | |
if (list(b[i]).count(b[i][0]) == len(b[i])) & (b[i][0] != 0): | |
way = 'horizontal row {}'.format(i) | |
win = True | |
return (win, way) | |
def check_vert(b, side): | |
win = False | |
way = 'no win' | |
for i in range(side): | |
if (list(b[:,i]).count(b[0,i]) == len(b[:,i])) & (b[0,i] != 0): | |
way = 'vertical column {}'.format(i) | |
win = True | |
return (win, way) | |
def check_diag(b, side): | |
win = False | |
way = 'no win' | |
d_1 = [b[i,i] for i in range(side)] | |
d_2 = [b[i,(side-1)-i] for i in range(side)] | |
if ((d_1.count(d_1[0]) == len(d_1)) & (d_1[0] != 0)) | ((d_2.count(d_2[0]) == len(d_2)) & (d_2[0] != 0)): | |
way = 'diagonal' | |
win = True | |
return (win, way) | |
#check end game | |
def check_end(b, side): | |
"""check if the game has ended. Pass the side length of the board to side""" | |
end = True | |
for i,j in itertools.product(range(side), range(side)): | |
if b[i,j] == 0: | |
end = False | |
return end | |
def fill_blank(sequence, tup, length): | |
"""fill any blank spaces. tup is the tuple you want to fill black spaces with (use a coordinate not on the board). | |
length for the amount of spaces on the empty board. | |
""" | |
s = sequence | |
n = length - len(s) | |
if n > 0: | |
for i in range(n): | |
s.append(tup) | |
return s | |
def encode_abc(tup): | |
"""encode 2dim tuple coodinates to alphabetical code for example (1,2) == bc""" | |
return string.ascii_lowercase[tup[0]] + string.ascii_lowercase[tup[1]] | |
dummy1 = Player(1) | |
dummy2 = Player(2) | |
#set side length of the board and initialize win sequence | |
side_length = 3 | |
wins = [] | |
#run this game for 1000 iterations | |
for i in range(1000): | |
board = np.array([[0 for x in range(side_length)] for y in range(side_length)]) | |
this_game = [] | |
while True: | |
#player one moves | |
free_1 = dummy1.examine(board) | |
played_1 = dummy1.play_random(board, free_1) | |
this_game.append(played_1) | |
if sum([check_horiz(board,side_length)[0], check_vert(board,side_length)[0], check_diag(board,side_length)[0]]) >= 1: | |
wins.append(1) | |
this_game = fill_blank(this_game, (3,3), 9) | |
print(this_game) | |
print('dummy 1 wins') | |
break | |
#check if the board is filled and if there are no winners, SM: stalemate | |
end = check_end(board, side_length) | |
if end and (sum([check_horiz(board,side_length)[0], check_vert(board,side_length)[0], check_diag(board,side_length)[0]]) == 0): | |
wins.append('SM') | |
print('SM') | |
break | |
#player two moves | |
free_2 = dummy2.examine(board) | |
played_2 = dummy2.play_random(board, free_2) | |
this_game.append(played_2) | |
if sum([check_horiz(board,side_length)[0], check_vert(board,side_length)[0], check_diag(board,side_length)[0]]) >= 1: | |
wins.append(0) | |
this_game = fill_blank(this_game, (3,3), 9) | |
print(this_game) | |
print('dummy 2 wins') | |
break | |
#check if the board is filled and if there are no winners, SM: stalemate | |
end = check_end(board, side_length) | |
if end and (sum([check_horiz(board,side_length)[0], check_vert(board,side_length)[0], check_diag(board,side_length)[0]]) == 0): | |
wins.append('SM') | |
print('SM') | |
break | |
#encode tuple play sequence into alphabet code | |
ab_coords = [encode_abc(x) for x in this_game] | |
print(ab_coords) | |
with open('predictors.csv','a+') as f: | |
f.write(','.join(ab_coords)+'\n') | |
print(wins) | |
with open('target_var.csv','a+') as f: | |
f.write(','.join([str(x) for x in wins])+'\n') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment