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:

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.

print_board( Game )
Displays the tic-tac-toe board. Prints to standard IO.

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

3 Responses to “Tic-tac-toe in Erlang — board display”

  1. mahesh babu on April 30th, 2010 9:26 pm

    plz send me this TIC TAC TOE OpenGL program

  2. mahesh babu on April 30th, 2010 9:29 pm

    plz send me tic tac toe opengl program soon reply

  3. Neal on May 1st, 2010 12:01 am

    This program doesn’t use OpenGL.

Leave a Reply