游戏棋子移动优化;根据某些规则,找到最小移动次数

时间:2014-09-24 00:12:11

标签: algorithm python-2.7 chess

好的,所以这很有趣。我正在尝试用日本国际象棋(也称为shogi)编写一件作品的动作,特别是银将军。作品运动的规则是这样的:

对于位置(x,y),该片可以移动到(x-1,y + 1),(x,y + 1),(x + 1,y + 1),(x-1, y-1),或(x + 1,y-1)。换句话说,棋子可以移动到与其直接对角的任何空间或直接在其上方的空间,但不能直接向左,向右或向下移动。

所以我定义了一个函数,它将起始位置(sx,sy)和最终位置(gx,gy)作为参数,并找到两者之间最快的路径。事情似乎适用于起始坐标和结束坐标在水平或垂直线上共存的情况,但之后事情开始分崩离析。我不知道我是否错过了一个条件,或者是否有更好的方法来执行此操作,但该函数需要使用给定的参数。有没有人有任何可能指出我正确方向的建议?我的代码如下:

def minSteps(sx,sy,gx,gy):
    count = 0
    while [sx,sy] != [gx,gy]:
        if (gy != sy and gx == sx):
            if gy > sy:
                sx = sx
                sy += 1
                count += 1
            else:
                sx += 1
                sy -= 1
                count += 1
        elif (gy == sy and gx != sx):
            if gx > sx:
                sx += 1
                sy += 1
                count += 1
            else:
                sx -= 1
                sy += 1
            count += 1
        elif (gy != sy and gx != sx):
            if gy > sy:
                if gx > sx:
                    sx += 1
                    sy += 1
                    count += 1
                else:
                    sx -= 1
                    sy += 1
                    count += 1
            if gy < sy:
                if gx > sx:
                    sx += 1
                    sy -= 1
                    count += 1
                else:
                    sx -= 1
                    sy -= 1
                    count += 1
    return count


2 个答案:

答案 0 :(得分:0)

您可以尝试A* Search Algorithm,它可以搜索问题空间以获得最少的步数。鉴于移动选项有限,可能需要调整算法以专门针对Shogi限制的移动。

希望这有帮助!

答案 1 :(得分:0)

我认为空间是“无限的”。所以,我用这种方式命名不同的动作:

  • A =(x + 1,y + 1)
  • B =(x + 1,y-1)
  • C =(x-1,y-1)
  • D =(x-1,y + 1)
  • E =(x,y + 1)

由于这些动作的顺序并不重要,我不想查找路径,而是计算多少As,多少B等等。

如果我们只考虑A,B,C和D移动,那么,我们将在对角线上看到一个网格。 不属于此网格的点可以使用E move连接到网格。

所以,第1步:找到相对于起点的x和y:

x = gx-sx;
y = gy-sy;

第2步:所有计数器归零:

a = 0;
b = 0;
c = 0;
d = 0;
e = 0;

步骤3:如果该点不在“网格”中,则使用E移动将其移动到网格中:

if ((x&1) ^ (y&1)) {e=1; y--;}

步骤4:因为我更容易在正数域中操作,所以在负数情况下会反映数字:

if (x<0) {hor=1; x=-x;}
else hor=0;
if (y<0) {ver=1; y=-y;}
else ver=0;

步骤5:一旦所有数字都是正数,我找到B和A计数器,或者D和A计数器:

if (x>y) {b=(x-y)/2; a=y+b;}
else {d=(y-x)/2; a=x+d;}

步骤6:如果镜像了数字,则相应地交换计数器(右侧变为左侧,向上变为向下):

if (hor) {hor=a; a=d; d=hor; c=b; b=0;}
if (ver) {ver=a; a=b; b=ver; ver=c; c=d; d=ver;}

......就是这样。解决方案是在a,b,c,d,e计数器中。如果你真的需要一个路径,你可以从移动计数器中获得它。

最后注意:计数器中有多个解决方案,因为您可以转换:A + D = 2 E