3

我想解决骑士巡回赛的难题。当我搜索它时,我知道有很多方法可以解决它。事实上,解决它的非常有效和快速的算法包括 Warnsdoff 规则。但实际上我从来不想复制它们中的任何一个。然后我在纸上看到了一个描述解决这个问题的方法的视频。视频的链接是 www.youtube.com%2Fwatch%3Fv%3DdWM5pKYZCHw&b=28 我不知道这种方法是否已经使用,但我决定遵循. 这是算法的链接。首先,我将解释解决骑士巡回赛的方法。我们假设我们有一个 8*8 的棋盘,并且我们已经给出了马的起始位置。现在我将板子细分为 4 个系统的盒子。左菱形系统,右菱形系统,左方系统,右方系统。首先,我将检查骑士在哪个系统中启动。然后我将首先填充该系统,然后我将进入下一个系统。为了填充该系统,我将首先进入当前块。整个板子被细分为 4 个块(每个块是(4*4),正如您从视频中看到的那样。填充该块后,我将移动到下一个块,依此类推。填充所有块后,我将移动到下一个系统。现在我几乎做到了。我已经做了一些功能,用于查找当前块,当前系统,移动是否可能,骑士在块中的下一步移动,块转移,最后是系统转移。现在我正在使用3D 数组,用于存储有关每个框的一些重要信息。数组大小为 [8][8][2]。在每个框的第一个元素中,我存储系统编号 i。e 我已经为四个系统中的每一个分配了特定的编号,以便以后识别它们。左菱形系统=1,右菱形系统=2,左方系统=3,右方系统=4。在每个盒子的下一个元素中,我存储了关于盒子的信息,无论我是否已经搬进了它。一开始这些都是零,但随着我的进步,我会将它们设为 1 我移动了哪个盒子。现在我处于预测试模式,并且在 nextmove 函数中遇到了一些逻辑问题。其余功能运行良好。我在这里给出了编码,但我只给出了代码中重要的选定部分。我忘记的一件事是我将骑士的当前位置存储在一个名为当前位置的数组中,并且我将在移动时更改当前位置。在整个代码中,m代表骑士的当前行,k代表当前列。这是代码

#include<iostream>
using namespace std;
// zero element for storing current row and 1 element for current column of knight.    
int currentposition[2]={0,0};
// 3d array for storing information
int   l[8][8][2]={ {{1,0} , {3,0} , {4,0} , {2,0} , {1,0} , {3,0} , {4,0} ,{2,0}}, 
                  {{4,0} , {2,0} , {1,0} , {3,0} , {4,0} , {2,0} , {1,0} , {3,0}},
                  {{3,0} , {1,0} , {2,0} , {4,0} , {3,0} , {1,0} , {2,0} , {4,0}},
                  {{2,0} , {4,0} , {3,0} , {1,0} , {2,0} , {4,0} , {3,0} , {1,0}},
                  {{1,0} , {3,0} , {4,0} , {2,0} , {1,0} , {3,0} , {4,0} , {2,0}},
                  {{4,0} , {2,0} , {1,0} , {3,0} , {4,0} , {2,0} , {1,0} , {3,0}},
                  {{3,0} , {1,0} , {2,0} , {4,0} , {3,0} , {1,0} , {2,0} , {4,0}},
                  {{2,0} , {4,0} , {3,0} , {1,0} , {2,0} , {4,0} , {3,0} ,{1,0}}};

//function for finding current block
int currentblock(int m , int k)    // m and k are current box       co-ordinates                         
{
int block;
if ((m>=0 && m<=3) && (k>=0 && k<=3))
     block= 1;
 if ((m>=0 && m<=3) && (k>3 && k<=7))
     block= 2;
 if ((m>3 && m<=7) && (k>=0 && k<=3))
     block= 3;
 if ((m>3 && m<=7) && (k>3 && k<=7))
     block= 4;
 return block;
}

//function telling that move is possible or not.
int movepossible(int m,int k,int i, int j)
// m and k represents current position and I and j represents the wanted position.
{             
          int ans=0;
          if ( ( (m-i)==1 && (k-j)==2 ) || ( (m-i)==2 && (k-j)==1 ) )
                          ans=1;
          if ( ( (m-i)==-1 && (k-j)==-2 ) || ( (m-i)==-2 && (k-j)==-1 ) )
                          ans=1;
          if ( ( (m-i)==-1 && (k-j)==2 ) || ( (m-i)==2 && (k-j)==-1 ) )
                          ans=1;
          if ( ( (m-i)==1 && (k-j)==-2 ) || ( (m-i)==-2 && (k-j)==1 ) )
                          ans=1;
          return ans;
}

//function to find the current system.
int currentsystem(int l[8][8][2],int m,int )

{
  int ans=l[m][k][0];
  return ans;
}
// function which move the knight in the specified box. 1 time  calling of function moves knight one time.
void nextmove(int l[8][8][2],int m,int k)
{     int block=currentblock(m,k);
      int system=currentsystem(l,m,k);
      int a,b,c,d;     
a,b,c,d, represents the range of the rows and columns for a specified block. There is no problem in this section I think.
  if (block==1)
   {   a=0;b=3;c=0;d=3;}
  else 
  {      if (block==2)
            {  a=0;b=3;c=4;d=3;}
         else 
            {     if (block==3)
                     { a=4;b=7;c=0;d=3;}
                  else
                      {   a=4;b=7;c=4;d=7;}
             }         
   }          

// now this will search the whole block for next move and it will check 3 conditions to move to a box.
for ( int rowmin=a; rowmin<=b ; rowmin+=1)
{         for (int colmin=c ;colmin<=d;colmin+=1)
         {     
               if (l[rowmin][colmin][1]!=1)   //this checks if we have already moved into that box or not
                {  if (l[rowmin][colmin][0]==system)
// this checks if box belongs to current system.
                   {    if  (movepossible(m,k,rowmin,colmin))
//this checks if move is possible or not
                        {
                                   currentposition[0]=rowmin;
// if all 3 conditions are satisfied knight will move to the box.
                                    currentposition[1]=colmin;
                                    l[rowmin][colmin][1]=1;
//this will change the value of the box to 1 in which we have moved.
                              }                            
                        }
                     }               
              }         
    }            
}                  


int main()
{  //int backtrackarray[8][8][2];
int m,k,i,j;
cout<<"Enter m:";   //Enters starting position(row) 
cin>>m;
cout<<"Enter k:";
// Enters starting position(column)
cin>>k;
currentposition[0]=m;   
// this updates the current position of knight in the currentposition array
currentposition[1]=k;
l[m][k][1]=1;

for (int u=0 ; u<3; u++)   // this loop is for testing of the nextmove function.
{     
  nextmove(l,currentposition[0],currentposition[1]);
  //calling of nextmove function.
     cout<<currentposition[0]<<" ,"<<currentposition[1];
  //displaying current position.
     cout<<endl;

}  
 cout<<"current block is"<<currentblock(m,k)<<endl;    //testing the current block function. Working perfect.

 cout<<"current system"<<currentsystem(l,m,k)<<endl;  //testing of current system function. Working perfect.

return 0;
}

此外,movepossible 功能也运行良好。现在的问题是,当我调用下一个移动函数时,它会正确移动第一和第二移动,但不会在块中移动第三移动。事实上,一个特定系统的一个块中总共有三个移动,换句话说,它不会移动到块中的最后一个框。它不依赖于起始位置,对于每个起始位置,它的行为都是这样的。现在我花了很多时间来寻找问题所在,但没有找到。所以请告诉我问题出在哪里。另外,如果您有任何改进逻辑和代码的建议。当我进入起始位置(4,3)时,代码的输出是这样的

6,2     //first move      

7,0     //second move

7,0     //not moved to the third one which is (5,1)


current block is3   //these are working perfect.
movepossible is1
current system2

但输出应该是这样的(仅适用于(4,3))

6,2     //first move      

7,0     //second move

5,1     //third move

current block is3   //these are working perfect.
movepossible is1
current system2
4

2 回答 2

2

快速调试导致我在您的案例中失败了以下行:

     if (l[rowmin][colmin][1]!=1)   //this checks if we have already moved into that box or not
  1. 您应该调试(即使只是添加日志)。
  2. 这不是 C++,这是纯 C,只有一点 iostream 和 for 循环中的声明。无意冒犯,但我认为如果您重新认为它是一种更 C++ish 的方式,您的代码将更具可读性/可维护性。
于 2013-11-12T21:41:28.627 回答
1

经过长时间的调试,我才知道

if (l[rowmin][colmin][1]!=1)   //this checks if we have already moved into that box or not

只对整个问题负责。问题是我在循环中编写它,当函数搜索下一步移动时,它在最终决定之前将值更改为 1。当我把它从花括号里拿出来时,问题就解决了。

于 2013-11-13T13:39:49.873 回答