How to resolve the algorithm Tic-tac-toe step by step in the Pascal programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm Tic-tac-toe step by step in the Pascal programming language

Table of Contents

Problem Statement

Play a game of tic-tac-toe. Ensure that legal moves are played and that a winning position is notified.

Tic-tac-toe   is also known as:

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Tic-tac-toe step by step in the Pascal programming language

Source code in the pascal programming language

program Tic(Input, Output);

type
  Contents = (Unassigned, Human, Computer);
var
  BestI, BestJ: integer; { best solution a depth of zero in the search }
  B: array[0..2, 0..2] of Contents;  {zero based so modulus works later}
  Player: Contents;

  procedure DisplayBoard;
  var
    I, J: integer;
    T: array [Contents] of char;
  begin
    T[Unassigned] := ' ';
    T[Human] := 'O';
    T[Computer] := 'X';
    for I := 0 to 2 do
    begin
      for J := 0 to 2 do
      begin
        Write(T[B[I, J]]);
        if J <> 2 then
          Write(' | ');
      end;
      WriteLn;
      if I < 2 then
        WriteLn('---------');
    end;
    WriteLn;
    WriteLn;
  end;

  function SwapPlayer(Player: Contents): Contents;
  begin
    if Player = Computer then
      SwapPlayer := Human
    else
      SwapPlayer := Computer;
  end;

  function CheckWinner: Contents;
  var
    I: integer;
  begin
    CheckWinner := Unassigned; { no winner yet }
    for I := 0 to 2 do
    begin
      { first horizontal solution }
      if (CheckWinner = Unassigned) and (B[I, 0] <> Unassigned) and
        (B[I, 1] = B[I, 0]) and (B[I, 2] = B[I, 0]) then
        CheckWinner := B[I, 0]
      else
      { now vertical solution }
      if (CheckWinner = Unassigned) and (B[0, I] <> Unassigned) and
        (B[1, I] = B[0, I]) and (B[2, I] = B[0, I]) then
        CheckWinner := B[0, I];
    end;
    { now check the paths of the two cross line slants that share the middle position }
    if (CheckWinner = Unassigned) and (B[1, 1] <> Unassigned) then
    begin
      if (B[1, 1] = B[0, 0]) and (B[2, 2] = B[0, 0]) then
        CheckWinner := B[0, 0]
      else if (B[1, 1] = B[2, 0]) and (B[0, 2] = B[1, 1]) then
        CheckWinner := B[1, 1];
    end;
  end;

  { Basic strategy test - is this te best solution we have seen }
  function SaveBest(CurScore, CurBest: Contents): boolean;
  begin
    if CurScore = CurBest then
      SaveBest := False
    else if (CurScore = Unassigned) and (CurBest = Human) then
      SaveBest := False
    else if (CurScore = Computer) and ((CurBest = Unassigned) or
      (CurBest = Human)) then
      SaveBest := False
    else
      SaveBest := True;
  end;


  { Basic strategy - recursive depth first search of possible moves
  if computer can win save it, otherwise block if need be, else do deeper.
  At each level modify the board for the next call, but clean up as go back up,
  by remembering the modified position on the call stack. }
  function TestMove(Val: Contents; Depth: integer): Contents;
  var
    I, J: integer;
    Score, Best, Changed: Contents;
  begin
    Best := Computer;
    Changed := Unassigned;
    Score := CheckWinner;
    if Score <> Unassigned then
    begin
      if Score = Val then
        TestMove := Human
      else
        TestMove := Computer;
    end
    else
    begin
      for I := 0 to 2 do
        for J := 0 to 2 do
        begin
          if B[I, J] = Unassigned then
          begin
            Changed := Val;
            B[I, J] := Val;
            { the value for now and try wioth the other player }
            Score := TestMove(SwapPlayer(Val), Depth + 1);
            if Score <> Unassigned then
              Score := SwapPlayer(Score);
            B[I, J] := Unassigned;
            if SaveBest(Score, Best) then
            begin
              if Depth = 0 then
              begin { top level, so remember actual position }
                BestI := I;
                BestJ := J;
              end;
              Best := Score;
            end;
          end;
        end;
      if Changed <> Unassigned then
        TestMove := Best
      else
        TestMove := Unassigned;
    end;
  end;

  function PlayGame(Whom: Contents): string;
  var
    I, J, K, Move: integer;
    Win: Contents;
  begin
    Win := Unassigned;
    for I := 0 to 2 do
      for J := 0 to 2 do
        B[I, J] := Unassigned;
    WriteLn('The board positions are numbered as follows:');
    WriteLn('1 | 2 | 3');
    WriteLn('---------');
    WriteLn('4 | 5 | 6');
    WriteLn('---------');
    WriteLn('7 | 8 | 9');
    WriteLn('You have O, I have X.');
    WriteLn;
    K := 1;
    repeat {rather a for loop but can not have two actions or early termination in Pascal}
      if Whom = Human then
      begin
        repeat
          Write('Your move: ');
          ReadLn(Move);
          if (Move < 1) or (Move > 9) then
            WriteLn('Opps: enter a number between 1 - 9.');
          Dec(Move);
          {humans do 1 -9, but the computer wants 0-8 for modulus to work}
          I := Move div 3; { convert from range to corridinated of the array }
          J := Move mod 3;
          if B[I, J] <> Unassigned then
            WriteLn('Opps: move ', Move + 1, ' was already done.')
        until (Move >= 0) and (Move <= 8) and (B[I, J] = Unassigned);
        B[I, J] := Human;
      end;
      if Whom = Computer then
      begin
        { randomize if computer opens, so its not always the same game }
        if K = 1 then
        begin
          BestI := Random(3);
          BestJ := Random(3);
        end
        else
          Win := TestMove(Computer, 0);
        B[BestI, BestJ] := Computer;
        WriteLn('My move: ', BestI * 3 + BestJ + 1);
      end;
      DisplayBoard;
      Win := CheckWinner;
      if Win <> Unassigned then
      begin
        if Win = Human then
          PlayGame := 'You win.'
        else
          PlayGame := 'I win.';
      end
      else
      begin
        Inc(K); { "for" loop counter actions }
        Whom := SwapPlayer(Whom);
      end;
    until (Win <> Unassigned) or (K > 9);
    if Win = Unassigned then
      PlayGame := 'A draw.';
  end;

begin
  Randomize;
  Player := Human;
  while True do
  begin
    WriteLn(PlayGame(Player));
    WriteLn;
    Player := SwapPlayer(Player);
  end
end.


  

You may also check:How to resolve the algorithm Sailors, coconuts and a monkey problem step by step in the Objeck programming language
You may also check:How to resolve the algorithm SEDOLs step by step in the Go programming language
You may also check:How to resolve the algorithm Boolean values step by step in the Futhark programming language
You may also check:How to resolve the algorithm Sum and product of an array step by step in the Fermat programming language
You may also check:How to resolve the algorithm Logical operations step by step in the Racket programming language