recursion(backtracking) pascal

Discussion in 'Programming' started by serxasz, Mar 26, 2013.

  1. #1
    hello everyone,
    i have problems with this program and i am praying for your help.
    The task is to put given number of knights, on given size chess board, that every square of the board is covered. That is, every square on the board is either occupied by a knight or attacked by a knight. knights can attack each other. the solutions are givven here.
    http://www.contestcen.com/knight.htm
    i am using recursion. algorithm:
    1. choose not occupied square
    2. try every knight, which can occupy that square
    3. choose another square and so on, till knight max number is reached.
    basicly, i try every posibble knight positions.
    i wrote program, which is below, but it crashes when i put more than 6 knights, and show nonsense in boards below 6. i know that the problem is in backtracking, when i need to delete a knight. but i dont know how to correct it.
    again, praying for your help. Thanks in advance.

    program zirgai;
    uses crt;
    type lenta = array[1..8,1..8] of char;
        ejimai = array[1..8] of integer;
    var L:lenta;
        N,M,Grizti:ejimai;
        zirgu_sk,dydis,r:integer;
    //******************************//
    procedure nulinimas(var L:lenta; d:integer);
    var x,y:integer;
    begin
    for x:=1 to d do
        begin
        for y:=1 to d do
            begin
            L[x,y]:='0';
            end;
        end;
    end;
    //******************************//
    procedure tikrinimas(L:lenta; d:integer; var r:integer);
    var x,y:integer;
    begin
    r:=1;
    for x:=1 to d do
        begin
        for y:=1 to d do
            begin
            if L[x,y]='0' then begin r:=0; break; end;
            end;
        if L[x,y]='0' then begin r:=0; break; end;
        end;
    end;
    //******************************//
    procedure braizyti(L:lenta; d:integer);
    var x1,x2,y1,y2,counter,x,y:integer;
    begin
    counter:=1;
    y1:=1;
    y2:=3;
        for x:=1 to d do                                          // draws a chess board
        begin
        x1:=1;
        x2:=5;
            for y:=1 to d do
            begin
            window(x1,y1,x2,y2);
            if (counter mod 2) = 0 then textbackground(red)
            else textbackground(green);
            clrscr;
            writeln;
            writeln('  ',L[x,y]);
            counter:=counter+1;
            x1:=x1+5;
            x2:=x2+5;
            end;
        y1:=y1+3;
        y2:=y2+3;
        if (d mod 2) = 0 then counter:=counter+1;
        end;
    end;
    //******************************//
    procedure Delioti(zirgas,x,y:integer);
    var i,z:integer;
    begin
    tikrinimas(L,dydis,r);
    if r=1 then
    begin
    writeln('done');                    // checks if all sqaures are covered
    braizyti(L,dydis);
    readln;
    exit;
    end;
    ///////////////////////////////////////////////////////////
        if (x<>1) and (y<>1) and (zirgas<>0) then
        begin
            if (x>=1) and (y>=1) and (x<=dydis) and (y<=dydis) then
            begin
            L[x,y]:='Z';                                                                            // puts knight, and marks covered squares
                for i:=1 to 8 do
                begin
                    if (x+N[i]>=1) and (y+M[i]>=1) and (x+N[i]<=dydis) and (y+M[i]<=dydis)
                    and (L[x+N[i],y+M[i]]<>'Z') and (L[x+N[i],y+M[i]]<>'.') then
                    begin
                    L[x+N[i],y+M[i]]:='.';  Grizti[i]:=1;
                    end;
                end;
            end;
        end;
     
    ///////////////////////////////////////////////////////////
        for x:=1 to dydis do
        begin
            for y:=1 to dydis do
            begin
            if (L[x,y]<>'Z') and (L[x,y]<>'.') then break;                          // finds not occupied square
            end;
        if (L[x,y]<>'Z') and (L[x,y]<>'.') then break;
        end;
     
        if zirgas<=zirgu_sk then
        begin
            for i:=1 to 8 do                                                        // recursion. calls procedure again and again
            begin
            Delioti(zirgas+1,x+N[i],y+M[i]);
            end;
        end;
    ///////////////////////////////////////////////////////////
        if (x<>1) and (y<>1) and (zirgas<>0) then
        begin
            if (x>=1) and (y>=1) and (x<=dydis) and (y<=dydis) then
            begin
            L[x,y]:='0';
                for i:=1 to 8 do
                begin
                    if Grizti[i]=1 then
                    begin                                                              // deletes knight, and his covered squares
                    L[x+N[i],y+M[i]]:='0';
                    end;
                end;
            end;
        end;
        for z:=1 to 8 do
        begin
        Grizti[z]:=0;
        end;
    ///////////////////////////////////////////////////////////
    end;
    //******************************//
    begin
      N[1]:=1;  M[1]:=2;
      N[2]:=1;  M[2]:=-2;
      N[3]:=2;  M[3]:=-1;
      N[4]:=2;  M[4]:=1;
      N[5]:=-2; M[5]:=-1;
      N[6]:=-2; M[6]:=1;
      N[7]:=-1; M[7]:=-2;
      N[8]:=-1; M[8]:=2;
        for dydis:=1 to 8 do
        begin
        Grizti[dydis]:=0;
        end;
    writeln('zirgu skaicius:');
    readln(zirgu_sk);
    writeln('lentos dydis:');
    readln(dydis);
    nulinimas(L,dydis);    // changes all squares value to '0'
    Delioti(0,1,1);
    readln;
    end.
    Code (markup):
     
    serxasz, Mar 26, 2013 IP
  2. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,999
    Best Answers:
    253
    Trophy Points:
    515
    #2
    Now, I'm a Pascal guy... and to be honest... I can't even make sense out of your code OR the problem in question... much less what "recursion" has to do with anything because there is none I can see in your code; though your code is VERY hard to follow with the oddball nonsensical inconsistent willy-nilly formatting, use of non-pascal commenting style, etc, etc...

    Can't say I've ever seen this problem before -- looks like one of those 'deep thought' examples teachers love to use that has little if anything to do with real world problems... I would probably have each square be an object -- are you up to using object pascal in this? (I would think so since you're using the CRT unit, so TP4 through 7?)

    Hardest part would likely be figuring which knight to add first -- I'd probably run each test based on the 2x3 area of a normal attack -- then plug in other knights in unattacked spaces as need be. It's a interesting one alright... though again, I can't figure out your code at all. (admittedly, the non-english names on things is an issue too).

    You do seem to be using WAY too many break and for loops, instead of while and increments. Shouldn't effect the result though.

    I tried reformatting it, but I keep coming up with too many 'end' -- likewise neither TP7 or FPC will compile it.. so I'm wondering how you're getting as far as testing values on it.
     
    deathshadow, Mar 28, 2013 IP