用c ++解决骑士之旅

时间:2013-11-12 17:31:42

标签: c++ arrays algorithm c++11

我想解决骑士之旅的难题。当我搜索它时,我发现有很多方法可以解决它。事实上,非常有效和快速的算法可以解决它,包括Warnsdoff的规则。但实际上我从来不想复制其中任何一个。然后我看了一个视频,描述了在纸上解决这个问题的方法。视频的链接是www.youtube.com%2Fwatch%3Fv%3DdWM5pKYZCHw& b = 28 我不知道这种方式是否已经使用过,但我决定这样做。这是算法的链接。 首先,我将解释解决骑士之旅的方法。我们假设我们有一个8 * 8的棋盘,我们已经给出了骑士的起始位置。现在我将电路板细分为4个盒子系统。左钻石系统,右钻石系统,左方系统,右方系统。首先,我将检查骑士在哪个系统中开始。然后我将首先填写该系统,然后我将移动到下一个系统。为了填充该系统,我将首先进入当前块。整个电路板被细分为4个块(每个块是(4 * 4),你可以从视频中看到。填充该块后,我将移动到下一个块,依此类推。在填充所有块之后,我将移动到下一个系统。现在我已经差不多了。我已经做了一些功能来寻找当前的块,当前系统,是否可以移动,下一步的骑士移动,块移位和最后的系统移动。现在我使用的是3D数组存储关于每个盒子的一些重要信息。数组大小是[8] [8] [2]。在每个盒子的第一个元素中我存储系统编号,即我已经为四个系统中的每一个分配了特定的数字以后认出它们。左钻石系统= 1,右钻石系统= 2,左方形系统= 3,右方系统= 4.在每个方框的下一个元素中,我存储有关方框的信息,我是否已经进入它在开始时这些都是零,但随着我的进步,我会把它们变成一个我移动的盒子w我处于预测试模式,我在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

2 个答案:

答案 0 :(得分: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 ++方式,那么您的代码将更具可读性/可维护性。

答案 1 :(得分:1)

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

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

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