2010-12-04 4 views
4

Ich habe eindimensionale Array, die Schachtisch bedeutet. Ich würde gerne alle Positionen finden, die Ritter angreifen könnte. Zum Beispiel 3x3 Schachtisch haben (K ist Ritter, X Position Angriff):Prolog, Ritter Angriff

--------------- 
| X | | | 
--------------- 
| | | K | 
--------------- 
| X | | | 
--------------- 

und für diese Tabelle, die ich in Prolog-Programm möchte Array haben:

------------------------------------- 
| X | | | | | K | X | | | 
------------------------------------- 

Ich möchte universelles Programm für alle Fälle zu schreiben - 3x3 Tisch, 4x4, 5x5, usw.

ich habe versucht:

control(Table, N, Pos, NewTable) :- insert(Table, Pos, 'k' , TempTable1, 1), 
        insert(TempTable1, Pos-N*2+1, 'x' , TempTable2, 1), 
        insert(TempTable2, Pos-N*2-1, 'x' , TempTable3, 1), 
        insert(TempTable3, Pos-N +2, 'x' , TempTable4, 1), 
        insert(TempTable4, Pos-N -2, 'x' , TempTable5, 1), 
        insert(TempTable5, Pos+N*2+1, 'x' , TempTable6, 1), 
        insert(TempTable6, Pos+N*2-1, 'x' , TempTable7, 1), 
        insert(TempTable7, Pos+N +2, 'x' , TempTable8, 1), 
        insert(TempTable8, Pos+N -2, 'x' , NewTable, 1). 

Dort N - ist Tischgröße (3), Pos - Ritterposition. Die „Einfügen“ ist in Ordnung, aber „Kontrolle“ nicht ordnungsgemäß funktioniert:

?- control([0,0,0,0,0,0,0,0,0], 3, 6, R). 
R = [x, 0, 0, 0, x, k, x, 0, 0]. 

R = [x, 0, 0, 0, 0, k, x, 0, 0] sein sollte.

Irgendwelche Ideen, wie "Kontrolle" Prädikat zu ändern?

+1

Ich denke, das wird viel einfacher, wenn Sie die Tabelle als 2d-Array modellieren und X- und Y-Koordinaten an "control" übergeben. – Cephalopod

Antwort

1

Entfernen Sie die Inserts, bis das Rogue x verschwindet. Das sollte dir sagen, wo das Problem liegt.

EDIT: Ah-ha! Es hätte mir früher einfallen sollen. Sie sind nicht Clipping Springer bewegt, wenn sie gehen die linke oder rechte Kante des Brettes, so dass der Springer auf die oberste Reihe, dann zwei nach rechts, die um den mittleren Rang umschließt und plündert den Ritter direkt neben seinem Startposition. insert kann nur oben und unten abschneiden, weil es nur ein Array sieht; Es weiß nicht, wie breit das Board ist.

+0

Ja, ich könnte Zeile "einfügen (TempTable3, Pos-N +2, 'x', TempTable4, 1)" entfernen, aber diese Zeile ist korrekt für andere Springer-Position. – Martynas

+0

Ich habe meine Antwort geändert. BTW, die Zeile ist z. B. für "control ([0,0,0,0,0,0,0,0,0,0], 3, 5, R)" immer noch falsch. In der Tat wird dies * zwei * Rogue 'x'-Zellen erzeugen. –

0

Ich stimme Arian zu. Es scheint wirklich viel einfacher zu sein, zwei Koordinaten zu verwenden. Aber wenn Sie wirklich alles so behalten wollen, wie es ist, habe ich etwas gefunden, das wie eine Lösung aussieht.

Sie schreiben nichts über Ihre insert/5 Prädikat, also werde ich nehme an, Sie haben dies:

insert(A, Pos, H, A, X) :- 
    Pos < 1, 
    !. 
insert([], Pos, H, [], N) :- 
    !. 
insert([H1|T1], Pos, H, [H|T1], N) :- 
    N =:= Pos, 
    !. 
insert([H1|T1], Pos, H, [H1|T2], N) :- 
    N < Pos, 
    N2 is N + 1, 
    insert(T1, Pos, H, T2, N2). 

mit Koordinaten zu helfen, ich ein Prädikat schrieb, dass Sie die Zeile und eine Spalte einer Position sagt:

Auf diese Weise können Sie Zeile + Spalte des Ritters erhalten, Zeile + Spalte der neuen Angriffsposition berechnen und vergleichen. Wenn es korrekt ist - Sie einfügen, wenn nicht korrekt - Sie ignorieren einfügen. Diese

control(Table, N, Pos, NewTable) :- 
    insert(Table, Pos, 'k' , TempTable1, 1), 
    getposition(N, Pos, Row1, Column1), 

    getposition(N, Pos-N*2+1,RowA, ColumnA), 
    (RowA =:= Row1 - 2, ColumnA =:= Column1 + 1,!, 
    insert(TempTable1, Pos-N*2+1, 'x' , TempTable2, 1);TempTable2 = TempTable1),  

    getposition(N, Pos-N*2-1,RowB, ColumnB), 
    (RowB =:= Row1 - 2, ColumnB =:= Column1 - 1,!, 
    insert(TempTable2, Pos-N*2-1, 'x' , TempTable3, 1);TempTable3 = TempTable2), 

    getposition(N, Pos-N + 2,RowC, ColumnC), 
    (RowC =:= Row1 - 1, ColumnC =:= Column1 + 2,!, 
    insert(TempTable3, Pos-N +2, 'x' , TempTable4, 1);TempTable4 = TempTable3), 

    getposition(N, Pos-N - 2,RowD, ColumnD),  
    (RowD =:= Row1 - 1, ColumnD =:= Column1 - 2,!, 
    insert(TempTable4, Pos-N -2, 'x' , TempTable5, 1); TempTable5 = TempTable4), 

    getposition(N, Pos+N*2+1,RowE, ColumnE), 
    (RowE =:= Row1 + 2, ColumnE =:= Column1 + 1,!, 
    insert(TempTable5, Pos+N*2+1, 'x' , TempTable6, 1); TempTable6 = TempTable5), 

    getposition(N, Pos+N*2-1,RowF, ColumnF),  
    (RowF =:= Row1 + 2, ColumnF =:= Column1 - 1,!, 
    insert(TempTable6, Pos+N*2-1, 'x' , TempTable7, 1); TempTable7 = TempTable6), 

    getposition(N, Pos+N + 2,RowG, ColumnG), 
    (RowG =:= Row1 + 1, ColumnG =:= Column1 + 2,!, 
    insert(TempTable7, Pos+N +2, 'x' , TempTable8, 1); TempTable8 = TempTable7), 

    getposition(N, Pos+N - 2,RowH, ColumnH), 
    (RowH =:= Row1 + 1, ColumnH =:= Column1 - 2,!, 
    insert(TempTable8, Pos+N -2, 'x' , NewTable, 1); NewTable = TempTable8). 

ist wahrscheinlich nicht die beste Lösung, da es mühsam ist und mein Prolog Fähigkeiten sind begrenzt, aber zumindest funktioniert es!

?- control([0,0,0,0,0,0,0,0,0], 3, 6, R). 
R = [x, 0, 0, 0, 0, k, x, 0, 0]. 

?- control([0,0,0,0,0,0,0,0,0], 3, 5, R). 
R = [0, 0, 0, 0, k, 0, 0, 0, 0]. 
0

ein anderer Ansatz wäre so etwas wie dies tun:

knight_in_range(X,Y):- 
    knight_move(X,Y,Xn,Yn), 
    knight(Xn,Yn). 

%writing manually all the pairs is kinda boring 
knight_move(X,Y,Xn,Yn):- 
    alter(Ax), 
    alter(Ay,Ax), 
    Yn is Y+Ay, 
    Xn is X+Ax. 

alter(Ax):- 
    member(Ax,[1,2,-1,-2]). 
alter(Ay,Ax):- 
    Ay is 2/Ax. 
alter(Ay,Ax):- 
    Ay is -2/Ax. 

um die Liste zu bekommen Sie einfach fragen, ob jeder Platz unter Beschuss ist oder nicht.
während es mehr Zeit für diese spezifische Anwendung nehmen sollte ich denke, es ist ein bisschen weniger chaotisch xd auch, wenn Sie die nxn Lösung haben, können Sie leicht/schnell bekommen die (n + 1) x (n + 1)