diff options
Diffstat (limited to 'ttt')
-rw-r--r-- | ttt/rebar.config | 7 | ||||
-rw-r--r-- | ttt/rebar.lock | 1 | ||||
-rw-r--r-- | ttt/src/ttt.app.src | 13 | ||||
-rw-r--r-- | ttt/src/ttt.erl | 51 | ||||
-rw-r--r-- | ttt/test/ttt_test.erl | 18 |
5 files changed, 90 insertions, 0 deletions
diff --git a/ttt/rebar.config b/ttt/rebar.config new file mode 100644 index 0000000..59700d5 --- /dev/null +++ b/ttt/rebar.config @@ -0,0 +1,7 @@ +{erl_opts, [debug_info]}. +{deps, [ +]}. + +{shell, [ + {apps, [ttt]} +]}. diff --git a/ttt/rebar.lock b/ttt/rebar.lock new file mode 100644 index 0000000..57afcca --- /dev/null +++ b/ttt/rebar.lock @@ -0,0 +1 @@ +[]. diff --git a/ttt/src/ttt.app.src b/ttt/src/ttt.app.src new file mode 100644 index 0000000..813faba --- /dev/null +++ b/ttt/src/ttt.app.src @@ -0,0 +1,13 @@ +{application, ttt, + [{description, "TTT app"}, + {vsn, "0.1.0"}, + {registered, []}, +% {mod, {myapp_app, []}}, + {applications, + [kernel, stdlib]}, + {env,[]}, + {modules, []}, + + {licenses, ["Apache-2.0"]}, + {links, []} + ]}. diff --git a/ttt/src/ttt.erl b/ttt/src/ttt.erl new file mode 100644 index 0000000..a9fc4d1 --- /dev/null +++ b/ttt/src/ttt.erl @@ -0,0 +1,51 @@ +-module(ttt). + +-export_type([ + player/0, + square/0, + board/0, + game_result/0]). + +-export([ + who_wins/1, + empty_board/0, + move/4, + format/1]). + +-type player() :: 'X' | 'O'. +-type square() :: player() | 'E'. +-type board() :: list(square()). +-type game_result() :: player() | 'draw' | 'running'. + +-define(EMPTY_BOARD, ['E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E']). + +-spec empty_board() -> board(). +empty_board() -> ?EMPTY_BOARD. + +-spec who_wins(Board :: board()) -> game_result(). +who_wins([A, A, A, _, _, _, _, _, _]) when A == 'X' orelse A == 'O' -> A; +who_wins([_, _, _, A, A, A, _, _, _]) when A == 'X' orelse A == 'O' -> A; +who_wins([_, _, _, _, _, _, A, A, A]) when A == 'X' orelse A == 'O' -> A; +who_wins([A, _, _, A, _, _, A, _, _]) when A == 'X' orelse A == 'O' -> A; +who_wins([_, A, _, _, A, _, _, A, _]) when A == 'X' orelse A == 'O' -> A; +who_wins([_, _, A, _, _, A, _, _, A]) when A == 'X' orelse A == 'O' -> A; +who_wins([A, _, _, _, A, _, _, _, A]) when A == 'X' orelse A == 'O' -> A; +who_wins([_, _, A, _, A, _, A, _, _]) when A == 'X' orelse A == 'O' -> A; +who_wins(Board) -> + case lists:member('E', Board) of + true -> running; + false -> draw + end. + +move(_, _, Row, _) when Row < 0 orelse Row > 2 -> {bad_arg}; +move(_, _, _, Col) when Col < 0 orelse Col > 2 -> {bad_arg}; +move(_, Move, _, _) when not (Move == 'X') -> {bad_arg}; +move(Board, Move, Row, Col) -> + I = Row * 3 + Col, + Updated = lists:sublist(Board, I) ++ [Move] ++ lists:nthtail(I + 1, Board), + {ok, Updated}. + +format(Board) when length(Board) == 9 -> + B = lists:map(fun(C) -> case C of 'E' -> ' '; _ -> C end end, Board), + io:format("+---+~n|~s~s~s|~n|~s~s~s|~n|~s~s~s|~n+---+~n", B); +format(_) -> "bad board". diff --git a/ttt/test/ttt_test.erl b/ttt/test/ttt_test.erl new file mode 100644 index 0000000..95b6bf7 --- /dev/null +++ b/ttt/test/ttt_test.erl @@ -0,0 +1,18 @@ +-module(ttt_test). + +-include_lib("eunit/include/eunit.hrl"). + +empty_board_test() -> + E = ttt:empty_board(), + ?assertEqual(E, ttt:empty_board()). + +moves_board_test() -> + B0 = ttt:empty_board(), + {ok, B1} = ttt:move(B0, 'X', 0, 0), + {ok, B2} = ttt:move(B1, 'X', 0, 1), + {ok, B3} = ttt:move(B2, 'X', 0, 2), + ?assertEqual(['X', 'X', 'X', 'E', 'E', 'E', 'E', 'E', 'E'], B3). + +simple_test() -> + R = ttt:who_wins(['X', 'X', 'X', 'E', 'E', 'E', 'E', 'E', 'E']), + ?assertEqual('X', R). |