diff --git a/test_ttt.py b/test_ttt.py index 4f12211..58b8c7f 100644 --- a/test_ttt.py +++ b/test_ttt.py @@ -2,15 +2,17 @@ import ttt + + class TestTTT( unittest.TestCase ): def test_1(self): self.assertEqual( 0, 0 ) # pass - self.assertEqual( 1, 0 ) # fail + #self.assertEqual( 1, 0 ) # fail something = board = None - self.assertEqual( something, ttt.game_state( board ) ) + #self.assertEqual( something, ttt.game_state( board ) ) # all built in test functions # from: https://docs.python.org/2/library/unittest.html @@ -27,3 +29,47 @@ def test_1(self): # self.assertNotIn(a, b) a not in b 2.7 # self.assertIsInstance(a, b) isinstance(a, b) 2.7 # self.assertNotIsInstance(a, b) not isinstance(a, b) 2.7 + def test_fin_win(self): + + win = [ 'x', 'o', '.', + 'x', 'o', '.', + 'x', '.', '.' ] + + win2 = [ 'x', 'o', '.', + 'x', 'o', 'x', + '.', 'o', '.' ] + + self.assertEqual(ttt.find_win(win), ttt.GameStates.x_wins) + self.assertEqual(ttt.find_win(win2), ttt.GameStates.o_wins) + + def test_game_states(self): + invalid_1 = [ 'x', 'x', 'x', + 'o', 'o', 'o', + '.', '.', '.' ] + + self.assertEqual(ttt.game_state(invalid_1), ttt.GameStates.invalid) + + def test_game_draw(self): + draw_1 = [ 'x', 'x', 'o', + 'o', 'o', 'x', + 'x', 'o', 'x' ] + + self.assertEqual(ttt.game_state(draw_1), ttt.GameStates.draw) + def test_game_unfinished(self): + unfinished_1 = [ 'x', 'x', '.', + 'o', 'o', '.', + '.', '.', '.' ] + + self.assertEqual(ttt.game_state(unfinished_1), ttt.GameStates.unfinished) + def test_game_unfinished_2(self): + unfinished_1 = [ 'x', '.', '.', + '.', '.', '.', + '.', '.', '.' ] + + def test_game_unvalid_2(self): + invalid_1 = [ 'o', '.', '.', + '.', '.', '.', + '.', '.', '.' ] + self.assertEqual(ttt.game_state(invalid_1), ttt.GameStates.invalid) +if __name__ == "__main__": + unittest.main() diff --git a/ttt.py b/ttt.py index 46467ea..09bde15 100644 --- a/ttt.py +++ b/ttt.py @@ -5,18 +5,78 @@ board is a list of 9 elements from ['x','o','.']. '.' means empty spot. """ +WIN_COMBOS = [ + (0,1,2), + (3,4,5), + (6,7,8), + (0,3,6), + (1,4,7), + (2,5,8), + (0,4,8), + (2,4,6) +] + import types class GameStates(object): - """ - there are lots of ways to accomplish an enum like object - this is the one we're going with since it's simple - """ - invalid = 0 - unfinished = 1 - x_wins = 2 - o_wins = 3 - draw = 4 + """ + there are lots of ways to accomplish an enum like object + this is the one we're going with since it's simple + """ + invalid = 0 + unfinished = 1 + x_wins = 2 + o_wins = 3 + draw = 4 + +def change_numeric(board): + return [ 0 if z == '.' else z for z in [ 1 if y == 'o' else y for y in [ -1 if x=='x' else x for x in board ]]] + +def find_win(board): + board_n = change_numeric(board) + for board_combo in WIN_COMBOS: + a,b,c = board_combo + sum_threes = sum([board_n[a], board_n[b], board_n[c]]) + if sum_threes != 0: + if sum_threes == -3: + return GameStates.x_wins + elif sum_threes == 3: + return GameStates.o_wins + return None + +def is_playing(board): + board_n = change_numeric(board) + if sum(board_n) == 0 or sum(board_n) == -1: + return True + else: + return False + +def is_invalid(board): + board_n = change_numeric(board) + if sum(board_n) != -1: + return True + else: + return False + +def is_finished(board): + if '.' not in board: + return True + else: + return False def game_state(board): - return states # you decide what should get returned here + win_status = find_win(board) + + if not win_status: + if is_playing(board): + if not is_finished(board): + return GameStates.unfinished + elif is_finished(board) and is_playing(board): + return GameStates.draw + else: + return GameStates.invalid + else: + if is_invalid(board): + return GameStates.invalid + else: + return win_status