prolog,骑士攻击

时间:2010-12-04 22:11:56

标签: arrays prolog combinatorics

我有一维数组,意思是象棋表。我想找到骑士可以攻击的所有位置。 例如,有3x3象棋桌(K是骑士,X是攻击位置):

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

对于这个表,在prolog程序中我想有数组:

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

我想为所有案例编写通用程序 - 3x3表,4x4,5x5等。

我试过了:

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]

任何想法,如何改变“控制”谓词?

3 个答案:

答案 0 :(得分:1)

删除插入,直到恶意x消失。这应该告诉你问题出在哪里。

编辑:啊哈!它本来应该发生在我之前。当他们通过棋盘的左边缘或右边缘时,你不会削减骑士的动作,所以骑士向上移动到最高等级,然后向右移动两个,它绕到中间等级,并且骑士紧挨着它的旁边起始位置。 insert只能剪辑顶部和底部,因为它只能看到一个数组;它不知道电路板有多宽。

答案 1 :(得分:0)

我同意阿里安。使用两个坐标似乎更容易。但是如果你真的想要保持原样,我想出了一些似乎是解决方案的东西。

你没有写任何关于你的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).

这可能不是最好的解决方案,因为它很麻烦且我的prolog技能有限,但至少它有效!

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

答案 2 :(得分:0)

一种不同的方法是做这样的事情:

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)

相关问题