Tic-tac-toe in Erlang — board display
This is part of an Erlang tutorial built around a tic-tac-toe program. The program is stuffed into one file, called tic.erl and available for download. The source code and this tutorial are organized into these sections:
- Introduction
- Top-level loop
- User input
- Board display (this page)
- Board abstraction
- Game abstraction
- Next move calculations and predictions
- Predicted outcome abstraction
- Utilities to introduce randomness
- Macros for testing and debugging
Board display
This section provides a function to display the tic-tac-toe board as the game progresses. Although only one function is used outside this section, about 30 functions are defined and used internally.
This draws the board using fixed-width text on standard-IO. It is very primitive. It would not be too hard to replace it with code to draw the board to a window (using GS, the Erlang graphics module), or code to create an XML or HTML description of the board and send it to a waiting Erlang process.
Interface
The board display section of the code provides a single function that is used elsewhere.
Source code
Here’s the Erlang source code for the board display section of the tic.erl file.
% --------------------------------------------------------------
% Board Display - print_board(..)
% --------------------------------------------------------------
%
% This section "exports" the function print_board( Game ).
%
% Prints the tic-tac-toe board to standard IO.
% The printed board looks like this (with predictions):
%
% [] OOOOO [] XXX XXX
% 1 WINNING [] OOO OOO [] XX XX
% MOVE! [] OOO OOO [] XXX
% [] OOO OOO [] XX XX
% [] OOOOO [] XXX XXX
% ===============##===============##===============
% [] XXX XXX [] XXX XXX
% 2 Loses in [] XX XX [] XX XX
% three moves [] XXX [] XXX
% after this [] XX XX [] XX XX
% [] XXX XXX [] XXX XXX
% ===============##===============##===============
% OOOOO [] OOOOO []
% OOO OOO [] OOO OOO [] 9 Leads to
% OOO OOO [] OOO OOO [] CAT game
% OOO OOO [] OOO OOO []
% OOOOO [] OOOOO []
% --------------------------------------------------------------
% print_board( Game )
% print_board( Board, Option )
%
% Writes a big-display board to standard IO.
%
% Option controls what we show in empty cells.
% It is one of the following:
% simple - leave empty cells blank
% number - show position number in empty cell
% predict - show position and predicted outcome
print_board( Game ) ->
print_board(
get_game_board( Game), get_game_print_option( Game)).
print_board( Board, Option ) ->
?m_assert(
(Option == simple) or
(Option == number) or
(Option == predict)),
Option_adjusted =
case (Option == predict) andalso is_board_empty( Board) of
true -> number;
false -> Option
end,
write_line( ),
print_row( Board, Option_adjusted, 1),
print_hori_divider( ),
print_row( Board, Option_adjusted, 4),
print_hori_divider( ),
print_row( Board, Option_adjusted, 7),
write_line( ).
% --------------------------------------------------------------
% print_hori_divider( )
% print_vert_divider( )
print_hori_divider( ) ->
write_string( "===============##"),
write_string( "===============##"),
write_line( "===============").
print_vert_divider( ) ->
write_string( "[]").
% --------------------------------------------------------------
% print_row( Board, Option, Position )
% print_row( Option, Pos, Mark1, Mark2, Mark3, Index )
% print_row( Option, Pos, Mark, Index )
print_row( Board, Option, Pos ) ->
M1 = get_board_mark( Board, Pos + 0),
M2 = get_board_mark( Board, Pos + 1),
M3 = get_board_mark( Board, Pos + 2),
lists:foreach(
fun ( Index ) ->
print_row( Option, Pos, M1, M2, M3, Index)
end,
lists:seq( 1, 5)).
print_row( Option, Pos, M1, M2, M3, Index ) ->
print_row( Option, Pos + 0, M1, Index),
print_vert_divider( ),
print_row( Option, Pos + 1, M2, Index),
print_vert_divider( ),
print_row( Option, Pos + 2, M3, Index),
write_line( ).
print_row( Option, Pos, M, Index ) ->
case M of
x_mark -> print_cell_x( Index);
o_mark -> print_cell_o( Index);
_ ->
case Option of
simple ->
print_cell_empty( );
number ->
print_cell_number( Pos, Index);
predict ->
case M of
empty ->
print_cell_number( Pos, Index);
_ ->
% M must be an Outcome.
?m_assert( is_outcome_valid( M)),
print_cell_predict_outcome( M, Pos, Index)
end
end
end.
% --------------------------------------------------------------
% print_cell_x( Index )
% print_cell_o( Index )
% print_cell_empty( )
% print_cell_number( Position, Index )
%
% Index goes from 1 thru 5.
print_cell_x( Index ) ->
write_string(
if
Index == 1; Index == 5 -> " XXX XXX ";
Index == 2; Index == 4 -> " XX XX ";
Index == 3 -> " XXX "
end).
print_cell_o( Index ) ->
write_string(
if
Index == 1; Index == 5 -> " OOOOO ";
Index == 2; Index == 4 -> " OOO OOO ";
Index == 3 -> " OOO OOO "
end).
print_cell_empty( ) ->
write_space( 15).
print_cell_number( Pos, Index ) ->
if
Index == 3 ->
write_space( 7),
write_arg( Pos),
write_space( 7);
true ->
write_space( 15)
end.
% --------------------------------------------------------------
% print_cell_predict_outcome( Outcome, Position, Index )
print_cell_predict_outcome( Outcome, Pos, Index ) ->
if
Index == 1;
Index == 5 ->
write_space( 15);
true ->
write_space( 2),
case Index of
2 -> print_cell_predict_outcome_1( Outcome, Pos);
3 -> print_cell_predict_outcome_2( Outcome);
4 -> print_cell_predict_outcome_3( Outcome)
end,
write_space( 2)
end.
% --------------------------------------------------------------
% print_cell_predict_outcome_1( Outcome, Position )
% print_cell_predict_outcome_2( Outcome )
% print_cell_predict_outcome_3( Outcome )
print_cell_predict_outcome_1( Outcome, Pos ) ->
write_arg( Pos),
write_space( ),
write_string(
case is_outcome_undecided( Outcome) of
true -> get_print_string_leads_to( );
false ->
case is_outcome_a_win( Outcome) of
true ->
case outcome_turn_count( Outcome) of
1 -> get_print_string_winning( );
_ -> get_print_string_wins_in( )
end;
false ->
case is_outcome_a_loss( Outcome) of
true ->
case outcome_turn_count( Outcome) of
1 -> get_print_string_loses( );
_ -> get_print_string_loses_in( )
end
end end end).
print_cell_predict_outcome_2( Outcome ) ->
write_string(
case is_outcome_undecided( Outcome) of
true -> get_print_string_cat_game( );
false ->
case is_outcome_a_win( Outcome) of
true ->
case outcome_turn_count( Outcome) of
1 -> get_print_string_move( );
2 -> get_print_string_next_turn( );
3 -> get_print_string_three_turns( );
4 -> get_print_string_four_turns( );
5 -> get_print_string_five_turns( )
end;
false ->
case is_outcome_a_loss( Outcome) of
true ->
case outcome_turn_count( Outcome) of
1 -> get_print_string_after_this( );
2 -> get_print_string_two_turns( );
3 -> get_print_string_three_turns( );
4 -> get_print_string_four_turns( )
end
end end end).
print_cell_predict_outcome_3( Outcome ) ->
write_string(
case
is_outcome_undecided( Outcome) orelse
(outcome_turn_count( Outcome) == 1)
of
true -> get_print_string_blank( );
false -> get_print_string_after_this( )
end).
% --------------------------------------------------------------
% Strings used to construct messages
get_print_string_leads_to( ) -> " Leads to".
get_print_string_winning( ) -> " WINNING".
get_print_string_loses( ) -> " Loses".
get_print_string_wins_in( ) -> " Wins in".
get_print_string_loses_in( ) -> " Loses in".
get_print_string_cat_game( ) -> " CAT game".
get_print_string_move( ) -> " MOVE!".
get_print_string_next_turn( ) -> " next turn".
get_print_string_two_turns( ) -> " two turns".
get_print_string_three_turns( ) -> "three turns".
get_print_string_four_turns( ) -> " four turns".
get_print_string_five_turns( ) -> " five turns".
get_print_string_after_this( ) -> " after this".
get_print_string_blank( ) -> " ".
Comments
4 Responses to “Tic-tac-toe in Erlang — board display”
Leave a Reply
plz send me this TIC TAC TOE OpenGL program
plz send me tic tac toe opengl program soon reply
This program doesn’t use OpenGL.
Very informative blog. Thanks for taking the time to share your view with us.