пролог, рыцарская атака - PullRequest
       24

пролог, рыцарская атака

4 голосов
/ 05 декабря 2010

У меня есть одномерный массив, что означает шахматный стол. Я хотел бы найти все позиции, на которые мог бы атаковать рыцарь. Например, иметь шахматный стол 3x3 (K - рыцарь, X - позиция атаки):

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

и для этой таблицы в прологе я хотел бы иметь массив:

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

Я хочу написать универсальную программу для всех случаев - 3х3 таблицы, 4х4, 5х5 и т. Д.

Я пытался:

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).

Там N - размер стола (3), Pos - положение коня. «Вставка» в порядке, но «управление» не работает правильно:

?- 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].

Есть идеи, как изменить предикат "control"?

Ответы [ 3 ]

1 голос
/ 05 декабря 2010

Удалите вставки, пока не исчезнет разбойник х. Это должно сказать вам, где проблема.

РЕДАКТИРОВАТЬ: Ах-ха! Это должно было случиться со мной раньше. Вы не ограничиваете ходы рыцаря, когда они проходят через левый или правый край доски, поэтому рыцарь поднимается до верхнего ранга, затем на два вправо, который приближается к среднему рангу и наклоняет рыцаря рядом с его Начальная позиция. insert может обрезать только верх и низ, потому что видит только массив; она не знает, насколько широка доска.

0 голосов
/ 29 апреля 2011

другой подход будет делать что-то вроде этого:

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.

, чтобы получить список, который вы просто спрашиваете, атакован ли каждый квадрат или нет.приложение, я думаю, что это немного менее грязный xd, также, если у вас есть решение nxn, вы можете легко / быстро получить (n + 1) x (n + 1)

0 голосов
/ 09 декабря 2010

Я согласен с Арианом.На самом деле, кажется, гораздо проще использовать две координаты.Но если вы действительно хотите оставить все как есть, я придумаю что-то вроде решения.

Вы ничего не написали о своем предикате insert/5, поэтому я предполагаю, что у вас есть это:

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).

Чтобы помочь с координатами, я написал предикат, который сообщает вам строку и столбец позиции:

getposition(Size, Pos, Row, Column) :-
    First is truncate(Pos / Size),
    (Pos mod Size > 0,!,Row is First + 1;Row is First),
    Second is Pos - First * Size,
    (Second =:= 0,!,Column is Size;Column is Second).

Таким образом, вы можете получить строку + столбец рыцаря, рассчитать строку + столбец новой позиции атаки и сравнить их.Если это правильно - вы вставляете, если не правильно - вы игнорируете вставку.

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).

Это, вероятно, не лучшее решение, так как оно громоздко и мои навыки пролога ограничены, но по крайней мере это работает!

?- 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].
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...