unit BoardADT;
{programmed by Samuel Marateck}
interface
const
number_of_columns = 7;
number_of_rows = 6;
type
column_type = 1..number_of_columns; {index for columns}
row_type = 1..number_of_rows; {index for rows}
square_type = {index for squares}
record
column : column_type;
row : row_type
end;
color_type = (red, blue);
value_type = {what a square contains}
record
empty : boolean; {is square empty?}
color : color_type {if not empty, what color it is}
end;
array_type = array[column_type, row_type] of value_type;
board_type =
object
procedure Initialize;
procedure Make_Move(column : column_type);
procedure Get_Value(square : square_type; var val : value_type);
function Get_Current_Color : color_type;
function Almost_Full(column : column_type) : boolean;
function is_Win : boolean;
function Almost_Draw : boolean;
private
Value : array_type; {the board configuration}
current_color : color_type; {whose turn it is}
end; {object board_type}
implementation
procedure board_type.Initialize;
{2/26/95}
{Initializes the board -- sets every square in the board empty.
Pre : None
Post : Board is empty and color is set to RED}
var column : column_type;
row : row_type;
begin
for column := 1 to number_of_columns do
for row := 1 to number_of_rows do
value[column, row].empty := true;
current_color := red;
end; {Initialize}
(****************************************************************************)
procedure board_type.Make_Move;
{Takes a column number and moves player's checker to the lowest available
position within that column.
Pre : Column is not full and 7 >= column number > 0.
Post : Current player's checker will go to the lowest available position.
Color is switched
Calls: Get_Current_Color -- needed to switch player colors.}
var row : row_type;
begin
row := 1; {start at the first row}
while not (value[column, row ].empty) and (row <= number_of_rows) do
row := row + 1;
value[column, row].empty := false;
value[column, row].color := current_color;
current_color := Get_Current_Color
end; {Make_Move}
(****************************************************************************)
procedure board_type.Get_Value;
{2/26/95}
{Outputs board value that is in location square}
begin
val := value[ square.column, square.row];
end; {Get_Value}
(****************************************************************************)
function board_type.Get_Current_Color;
{Changes the player's color
Pre : Board is Initialized and a move is made
Post : Switches the color to that of the next player.}
begin
if current_color = red then
Get_Current_Color := blue
else
Get_Current_Color := red
end; {Get_Current_Color}
(****************************************************************************)
function board_type.Almost_Full;
{Determines whether or not a column is full.
Pre : 7 >= Column > 0
Post : Outputs TRUE if Column is full, and FALSE if Column is not almost
full}
begin
Almost_Full:= NOT value[ column, number_of_rows - 1].empty
and value[ column, number_of_rows ].empty
end; {Is_Full}
(****************************************************************************)
function board_type.Is_Win;
{Checks to see if there is a winner.
Pre : Board has been initialized and moves have been made by both the
human and computer.
Post: Outputs TRUE if there is a winner (four of the same colored checkers
in a row, either horizontally, vertically, or diagonally), FALSE if
there isn't a winner.
Calls: Functions within itself to check diagonals, rows and columns}
var temp: boolean;
function valid( col: column_type; row:row_type) : boolean;
begin
valid:= not value[ col, row].empty and
(value[ col, row].color = current_color)
end;
procedure change;
{needed to compensate for changing color at end of make_move. Otherwise
a win is not detected until the other player moves. This is placed at
beginning and end of is_win}
begin
current_color := get_current_color
end;
function row_win(row : row_type) : boolean;
{checks if there is a winner in a row.
Pre : Moves have been made.
Post : Outputs true if a row has four contiguous checkers}
var col : column_type;
found : boolean;
begin
col:= 1;
found:= false;
while (col <= (number_of_columns - 3) ) and not found do begin
if valid( col, row) and
valid( col + 1, row) and
valid( col + 2, row) and
valid( col + 3, row) then
found:= true else
col:= col + 1
end {while};
row_win:= found
end ; {row_win}
function all_row_win : boolean;
{checks if there is a winner in any of the rows.
Pre : Moves have been made.
Post : Outputs true as soon as a row has four contiguous checkers}
var row : row_type;
found : boolean;
begin
row:= 1;
found:= false;
while not found and (row <= number_of_rows) do begin
found:= row_win(row);
row:= row + 1
end {while};
all_row_win:= found
end {all_row_win};
function col_win(col : column_type) : boolean;
{checks if there is a winner in a column.
Pre : Moves have been made.
Post : Outputs true if a column has four contiguous checkers}
var row : row_type;
found : boolean;
begin
row:= 1;
found:= false;
while (row <= (number_of_rows- 3) ) and not found do begin
if valid( col, row) and
valid( col, row + 1) and
valid(col, row + 2 ) and
valid(col, row + 3 ) then
found:= true;
row:= row + 1
end {while};
col_win:= found
end ; {col_win}
function all_column_win : boolean;
{checks if there is a winner in any of the columns.
Pre : Moves have been made.
Post : Outputs true as soon as a column has four contiguous checkers}
var col : column_type;
found : boolean;
begin
col:= 1;
found:= false;
while not found and (col <= number_of_columns) do begin
found:= col_win(col);
col:= col + 1
end {while};
all_column_win:= found
end {all_column_win};
function right_diagnol_win : boolean;
{checks if there is a winner in any of the 45 degree diagnols.
Pre : Moves have been made.
Post : Outputs true as soon as a diagnol has four contiguous checkers}
var col : column_type;
row : row_type;
found : boolean;
begin
found := false;
row := 1;
while not found and (row <= (number_of_rows -3) ) do begin
col := 1;
while not found and (col <= (number_of_columns -3) ) do begin
if valid(col, row ) and
valid(col + 1, row + 1 ) and
valid(col + 2, row + 2 ) and
valid(col + 3, row + 3) then
found := true;
col:= col + 1
end {while};
row:= row + 1
end {while};
right_diagnol_win:= found
end {right_diagnol_win};
function left_diagnol_win : boolean;
{checks if there is a winner in any of the 135 degrees diagnols.
Pre : Moves have been made.
Post : Outputs true as soon as a diagnol has four contiguous checkers}
var col : column_type;
row : row_type;
found : boolean;
begin
found := false;
row := 1;
while not found and (row <= (number_of_rows -3) ) do begin
col := 4;
while not found and (col <= number_of_columns) do begin
if valid(col, row) and
valid(col - 1, row + 1 ) and
valid(col - 2, row + 2 ) and
valid(col - 3, row + 3) then
found := true;
col:= col + 1
end {while};
row:= row + 1
end {while};
left_diagnol_win:= found
end {right_diagnol_win};
begin
change; {compensate for changing color at end of make_move}
is_win:= all_column_win or all_row_win or
right_diagnol_win or left_diagnol_win;
change
end;
(****************************************************************************)
function board_type.Almost_Draw;
{Checks to see if there is a draw -- there are no more spaces available.
Pre : Game board has been Initialized and moves have been made.
Post : Outputs TRUE if all spaces in the top row of the board have
been filled -- game outcome is DRAW.}
var col : column_type;
found:boolean;
begin
found:= true;
for col := 1 to number_of_columns do
found := found and almost_full( col );
Almost_draw := found
end; {Is_Draw}
end.{BoardADT}