@morganlaco
class ConnectFour::Game
def play
while continue_game
get_move
handle_move
end
display_result
end
# ...
end
ConnectFour::Game.new.play
defmodule ConnectFour do
def start(_type, _args) do
state = ConnectFour.initial_state
do_turn(state)
end
def do_turn(state) do
ConnectFour.IO.display_board(state[:board])
res = with \
{:ok, move} <- ConnectFour.IO.get_move(state[:turn]),
{:ok, new_board} <- \
ConnectFour.Board.update_board(state[:board], move, state[:turn]),
do:
new_state(state, new_board)
case res do
# ...
new_state ->
if ConnectFour.WinChecker.check(new_state[:board]) do
ConnectFour.IO.do_win(new_state)
else
do_turn(new_state)
end
end
end
ConnectFour.start
# Ruby
array = [1, 2, 3]
(1..3).each do |i|
array[i] = array[i] * 2
end
# Elixir
def do_fun_things(x) do
# Do them thangs
do_fun_things(y)
# ^-- Last thing
end
def fibonacci(n) do
cond do
n == 0
0
n == 1
1
true ->
fibonacci(n, 0, 1)
end
end
def fibonacci(n, a, b) do
if n <= 0 do
a
else
fibonacci(n - 1, b, a + b)
end
end
n | a | b |
---|---|---|
4 | - | - |
4 | 0 | 1 |
3 | 1 | 1 |
2 | 1 | 2 |
1 | 2 | 3 |
0 | 3 | 5 |
fibonacci(n)
fibonacci(n)
fibonacci(n)
fibonacci(n)
<process>
def fibonacci(n) do
cond do
n == 0
0
n == 1
1
true ->
fibonacci(n, 0, 1)
end
end
def fibonacci(n, a, b) do
if n <= 0 do
a
else
fibonacci(n - 1, b, a + b)
end
end
fibonacci(n)
fibonacci(n)
fibonacci(n)
fibonacci(n)
<process>
def fibonacci(n) do
cond do
n == 0
0
n == 1
1
true ->
fibonacci(n, 0, 1)
end
end
def fibonacci(n, a, b) do
if n <= 0 do
a
else
fibonacci(n - 1, b, a + b)
end
end
snokes_true_identity = "Plagueis"
# => "Plagueis"
snokes_true_identity = "Leia"
# => What happens?
snokes_true_identity = "Plagueis"
# => "Plagueis"
snokes_true_identity = "Leia"
# => "Leia"
before
after
foo
foo
foo = 4
foo = 5
4
5
before
after
foo
foo
foo = 4
foo = 5
4
5
4
foo
defmodule ConnectFour.IO do
def get_move(turn) do
validate_move(
String.trim(
IO.gets(:stdio, "[#{translate_player(turn)}] Enter move: "
)))
end
def validate_move(move) do
cond do
String.match?(move, ~r/[1-6]/) ->
{:ok, String.to_integer(move) - 1}
String.match?(move, ~r/q(uit)?/) ->
{:quit}
true ->
{:error}
end
end
end
defmodule ConnectFour.IO do
def get_move(turn) do
IO.gets(:stdio, "[#{translate_player(turn)}] Enter move: ")
|> String.trim
|> validate_move
end
def validate_move(move) do
cond do
String.match?(move, ~r/[1-6]/) ->
{:ok, String.to_integer(move) - 1}
String.match?(move, ~r/q(uit)?/) ->
{:quit}
true ->
{:error}
end
end
end
def insert_at_end(list, item) do
Enum.reverse(list)
|> Enum.into(list, [item])
|> Enum.reverse(list)
end
def insert_at_end(list, item) do
Enum.reverse(list)
|> Enum.into([item])
|> Enum.reverse
end
defmodule ConnectFour.IO do
# ...
def display_board(board) do
# Bad!
[h|t] = Listify.listify(board)
|> Antitranspose.antitranspose
display_board(h, t)
IO.puts " 1 2 3 4 5 6"
end
# ...
end
defmodule ConnectFour.IO do
# ...
def display_board(board) do
# Good!
[h|t] = prepare_board(board)
display_board(h, t)
IO.puts " 1 2 3 4 5 6"
end
def prepare_board(board) do
Listify.listify(board)
|> Antitranspose.antitranspose
end
# ...
end
case get_move(state[:turn]) do
{:ok, move} ->
case ConnectFour.Board.update_board(state[:board],\
move, state[:turn]) do
{:ok, new_board} ->
new_state(state, new_board)
|> do_turn
{:error} ->
do_turn(state) # redundant; can we use `with`?
{:error} ->
# do error stuff
IO.puts("Invalid move")
do_turn(state)
end
res = with \
{:ok, move} <- get_move(state[:turn]),
{:ok, new_board} <- \
ConnectFour.Board.update_board(state[:board], \
move, state[:turn]),
do:
new_state(state, new_board)
|> do_turn
case res do
{:error} ->
IO.puts "error!"
end
function isHorizontal(grid) {
for (let x = 0; x < rowsNum; x++) {
for (let y = 0; y < columnsNum; y++) {
// Current piece in this row
let piece = grid[y][x];
// Reset things if piece is 0
if (piece === 0) {
found = 0;
foundPiece = 0;
continue;
}
if (piece !== foundPiece) {
found = 1;
foundPiece = piece;
continue;
}
found++;
if (found >= 4) {
return true;
}
}
}
return false; // nothing was found in the same row
}
defmodule ConnectFour.WinChecker.Orthogonal do
def check_vertical(board) do
check(board, [])
end
def check([], row) do
check_row(row)
end
def check(remaining, []) do
[next_row | other_rows] = remaining
check(other_rows, next_row)
end
def check(remaining, row) do
if check_row(row) do
true
else
[next_row | other_rows] = remaining
check(other_rows, next_row)
end
end
end
defmodule ConnectFour.WinChecker.Orthogonal do
def check_row(row) do
[cell | other_cells] = row
check_row(cell, other_cells, 0, 0)
end
def check_row(cell, remaining, last, matching) do
new_matching =
if cell == last && cell != 0 do
matching + 1
else
1
end
if new_matching == 4 do
true
else
[next_cell | others] = remaining
check_row(next_cell, others, cell, new_matching)
end
end
end
defmodule ConnectFour.WinChecker.Orthogonal do
def check_row(cell, [], last, matching) do
new_matching =
if cell == last do
matching + 1
else
1
end
new_matching == 4
end
end
# Using accumulators in recursive fns
# http://langintro.com/elixir/article2/