aboutsummaryrefslogtreecommitdiff
path: root/tictactoe/ttt
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2024-03-04 09:15:01 +0100
committerTrygve Laugstøl <trygvis@inamo.no>2024-03-04 09:15:01 +0100
commitc34d7363b61a9e00c986b79793bf7cdc03e9ea99 (patch)
tree79c9121e2bff6bc938b7b36d1195e5759b163d2c /tictactoe/ttt
parent0be77ac09408c13cc12b5953b9ac7459b549c202 (diff)
downloaderlang-workshop-c34d7363b61a9e00c986b79793bf7cdc03e9ea99.tar.gz
erlang-workshop-c34d7363b61a9e00c986b79793bf7cdc03e9ea99.tar.bz2
erlang-workshop-c34d7363b61a9e00c986b79793bf7cdc03e9ea99.tar.xz
erlang-workshop-c34d7363b61a9e00c986b79793bf7cdc03e9ea99.zip
wip
Diffstat (limited to 'tictactoe/ttt')
-rw-r--r--tictactoe/ttt/rebar.config7
-rw-r--r--tictactoe/ttt/rebar.lock1
-rw-r--r--tictactoe/ttt/src/ttt.app.src13
-rw-r--r--tictactoe/ttt/src/ttt.erl51
-rw-r--r--tictactoe/ttt/test/ttt_test.erl18
5 files changed, 90 insertions, 0 deletions
diff --git a/tictactoe/ttt/rebar.config b/tictactoe/ttt/rebar.config
new file mode 100644
index 0000000..59700d5
--- /dev/null
+++ b/tictactoe/ttt/rebar.config
@@ -0,0 +1,7 @@
+{erl_opts, [debug_info]}.
+{deps, [
+]}.
+
+{shell, [
+ {apps, [ttt]}
+]}.
diff --git a/tictactoe/ttt/rebar.lock b/tictactoe/ttt/rebar.lock
new file mode 100644
index 0000000..57afcca
--- /dev/null
+++ b/tictactoe/ttt/rebar.lock
@@ -0,0 +1 @@
+[].
diff --git a/tictactoe/ttt/src/ttt.app.src b/tictactoe/ttt/src/ttt.app.src
new file mode 100644
index 0000000..813faba
--- /dev/null
+++ b/tictactoe/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/tictactoe/ttt/src/ttt.erl b/tictactoe/ttt/src/ttt.erl
new file mode 100644
index 0000000..a9fc4d1
--- /dev/null
+++ b/tictactoe/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/tictactoe/ttt/test/ttt_test.erl b/tictactoe/ttt/test/ttt_test.erl
new file mode 100644
index 0000000..95b6bf7
--- /dev/null
+++ b/tictactoe/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).