You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Prolog类俄罗斯方块程序中根据nrot和ndir修改方块坐标?

实现俄罗斯方块Prolog程序的旋转与右移坐标变换

你已经完成了初始方块的定义,接下来可以通过坐标变换规则分别实现旋转和右移操作,以下是具体步骤和代码实现:

一、明确坐标变换规则

1. 顺时针90度旋转的坐标变换

俄罗斯方块的旋转通常围绕方块的「边界基准点」(取方块所有点的最小行Rmin和最小列Cmin作为基准)进行:

  • 先将绝对坐标(R, C)转换为相对基准的偏移量(r = R - Rmin, c = C - Cmin)
  • 一次顺时针90度旋转后,偏移量变为(c, S - 1 - r),其中S是方块的边长(I型为4,S/O/T型为3)
  • 旋转NROT次就重复该变换NROT次,最后转换回绝对坐标

2. 右移操作的坐标变换

右移NDIR块数的逻辑很直接:每个点的列坐标直接加上NDIR,同时要保证右移后所有点的列坐标不超过棋盘宽度n(避免超出边界)。

二、代码实现

1. 辅助谓词:计算方块的基准点和边长

% 获取方块的最小行Rmin
min_row(Peca, Rmin) :-
    findall(R, member([R,_], Peca), Rs),
    min_list(Rs, Rmin).

% 获取方块的最小列Cmin
min_col(Peca, Cmin) :-
    findall(C, member([_,C], Peca), Cs),
    min_list(Cs, Cmin).

% 获取方块的边长S(最大行差+1)
peca_size(Peca, S) :-
    findall(R, member([R,_], Peca), Rs),
    max_list(Rs, Rmax),
    min_list(Rs, Rmin),
    S is Rmax - Rmin + 1.

2. 单坐标点的旋转实现

% 旋转0次,坐标不变
rotate_point(_, 0, [R,C], [R,C]).
% 递归实现多次旋转
rotate_point(S, NROT, [R,C], NewPoint) :-
    NROT > 0,
    N1 is NROT - 1,
    % 一次顺时针90度旋转:(r,c) → (c, S-1 - r)
    NewR is C,
    NewC is S - 1 - R,
    rotate_point(S, N1, [NewR, NewC], NewPoint).

3. 整个方块的旋转实现

% 旋转整个方块
rotate_peca(Peca, NROT, RotatedPeca) :-
    min_row(Peca, Rmin),
    min_col(Peca, Cmin),
    peca_size(Peca, S),
    % 转换为相对基准的坐标,旋转后再转回绝对坐标
    maplist(
        [Point, NewPoint] >> (
            Point = [R,C],
            RelR is R - Rmin,
            RelC is C - Cmin,
            rotate_point(S, NROT, [RelR, RelC], [NewRelR, NewRelC]),
            NewR is NewRelR + Rmin,
            NewC is NewRelC + Cmin,
            NewPoint = [NewR, NewC]
        ),
        Peca,
        RotatedPeca
    ).

4. 右移操作实现

% 右移整个方块,确保不超出棋盘宽度
shift_right(Peca, NDIR, ShiftedPeca) :-
    n(BoardWidth),
    % 检查所有点右移后列不超过棋盘宽度
    forall(member([_,C], Peca), (C + NDIR =< BoardWidth)),
    % 每个点的列加上NDIR
    maplist(
        [Point, NewPoint] >> (
            Point = [R,C],
            NewC is C + NDIR,
            NewPoint = [R, NewC]
        ),
        Peca,
        ShiftedPeca
    ).

5. 组合旋转与右移的主谓词

% 获取经过旋转和右移后的方块
peca_transformada(Tipo, NROT, NDIR, FinalPeca) :-
    peca(Tipo, InitialPeca),
    rotate_peca(InitialPeca, NROT, RotatedPeca),
    shift_right(RotatedPeca, NDIR, FinalPeca).

三、测试示例

测试I型方块旋转1次、右移1次:

?- peca_transformada(i, 1, 1, P).
P = [[1,1],[2,1],[3,1],[4,1]]. % 旋转后I型变为竖排,右移1列后列坐标均为1

测试T型方块旋转2次、右移1次(棋盘宽度为4):

?- peca_transformada(t, 2, 1, P).
P = [[1,3],[2,2],[2,3],[2,4]].

内容的提问来源于stack exchange,提问作者DFerreira

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 15:33:15