Search code examples
pascalfreepascaltic-tac-toe

Tic Tac Toe check winner free pascal


function CheckWinner(const track:MarkArray ;const index:Integer; p1:Player; p2:Player):String;
var 

i,N:Integer; //Creating index to traverse the 2D array
row,col: Integer; //creating variables to fix rows and columns
temp : String;

begin

row:=(index-1) DIV 3;  //fix row to check
col:=(index-1) MOD 3;      //fix column to check
N:=3;
temp:='YES';
for i:=0 to N-1 do
begin
    //check for player 1
    if(NOT(track[row][i]=p1.sign)) then
    begin
        temp:='NO';
        WriteLn('P1',temp);
    end;
    if((i=(N-1)) AND NOT(temp='NO') AND (track[row][i]=p1.sign)) then
    begin
        temp:='P1';
        WriteLn('P1 won');
        continue;
    end;

    ///player 2 check for rows
    if(NOT(track[row][i]=p2.sign)) then
    begin
        temp:='NO';
        WriteLn('P2',temp);
        continue;
    end;
    if((i=N-1) AND NOT(temp='NO') AND (track[row][i]=p2.sign)) then
    begin
        temp:='P2';
        WriteLn('P2 won');
    end;
end;

Hey I am writing code for TicTacToe in pascal and stuck at check winner function.

The problem is this code always check the last index of the row for the sign and is telling only for player 1, the main problem is with checks and i can't think of any checks anymore. Please help.

The function is being passed two player records for player 1 and player 2, player sign is tick or cross and index parameter is the box number on screen converted to a 2D array index. Please someone help with this.This is a row only check i can add to it later.


Solution

  • I think you are trying to do too much in that one function. Split the single tasks up in smaller functions and it will become a lot more readable and a lot simpler.

    I would do something like this:

    type
      TSign = (empty, nought, cross);
    
      TMarkArray = array[0..2, 0..2] of TSign;
    
      TPlayer = record
        sign: TSign;
        // other fields you may need
      end;
    
     function CheckSign(const track: TMarkArray; sign: TSign; p1, p2, p3: Integer): Boolean;
     begin
        Result := (track[p1 div 3, p1 mod 3] = sign) and
                  (track[p2 div 3, p2 mod 3] = sign) and
                  (track[p3 div 3, p3 mod 3] = sign);
     end;
    
     function CheckPlayer(const track: TMarkArray; sign: TSign): Boolean;
     begin
       Result := CheckSign(track, sign, 0, 1, 2) or // top row
                 CheckSign(track, sign, 3, 4, 5) or // middle row
                 CheckSign(track, sign, 6, 7, 8) or // bottom row
                 CheckSign(track, sign, 0, 3, 6) or // left column
                 CheckSign(track, sign, 1, 4, 7) or // middle column
                 CheckSign(track, sign, 2, 5, 8) or // right column
                 CheckSign(track, sign, 0, 4, 8) or // top-left - bottom right
                 CheckSign(track, sign, 2, 4, 6);   // top right - bottom left
     end;
    
     function CheckWinner(const track: TMarkArray; p1, p2: TPlayer): string;
     begin
       if CheckPlayer(track, p1.sign) then
         Result := 'P1'
       else if CheckPlayer(track, p2.sign) then
         Result := 'P2'
       else
         Result := 'NO';
     end;
    

    I don't know how your types are defined, but I made them as simple as possible for this piece of code and added a T in front to designate them as types.

    You could check rows and columns in a loop and jump out if you found a winner, but for a small playfield like this, with only 8 possible winner series, I left out the loops. They would only complicate CheckPlayer. For larger playfields, loops might make sense.

    Try if that works.