困扰了我4天时间,差点被它打到! 终于找到了一种算法:探索访问
每个格子有8种移动结果,即移动后有8种位置,当然,有些靠棋盘边界的格子移动后的位置会在棋盘外面
用二维数组visit level的值表示棋盘每格的访问级别,这是个逆向思维的过程,一个格子能有几种合法方式(不超越棋盘界限,移动一步的值在0--7之间)移动到其它格子,这个格子的访问级别就越高,访问级别越高,访问它的难度越低,因此访问级别低的格子要优先访问。用一个for循环7*7*8次去移动格子,其中7*7对应每个格子,8对应每个格子的移动方法,如果移动后没有越界,格子的访问级别加1
用二位数组moveways记录每个格子的具体8种移动方式的合法情况,没一排为一个格子,共0--63个格子,每列8个元素为8种移动方法,用上面for7*7*8的同一个循环,可以创建每一格格子每种移动的合法情况,1为合法,0为非法
用函数boardtotal来检测board二维数组的总值,如果为64,则while循环结束
在while循环中比较当前位置几种合法走法的最优路径,并依据此路径确定下一步及位置。原则是每次访问最低访问等级的格子且格子的值为1(初始化为0,表示没有被访问过)。在确定下一步是把当前格子对应board二维数组的值设为1.
#include<stdio.h>
#define row 8
#define column 8
int boardtotal(int[][column]);
int main(){
int board[row][column] = { 1 };
int visitLevel[row][column] = { 0 };
int horizontal[8] = { 2, 1, -1, -2, -2, -1, 1, 2 };
int vertical[8] = { -1, -2, -2, -1, 1, 2, 2, 1 };
int moveways[64][8] = { 0 };
int startrow, startcolumn , movestyle = 0,grid=0,best=9;
int currentrow, currentcolumn,x=0,y=0;
//Creat visit level&ways of each grid
for (startrow = 0; startrow<=7; startrow++){
for (startcolumn = 0; startcolumn<=7; startcolumn++){
for (movestyle = 0; movestyle <= 7; movestyle++){
if (startrow + vertical[movestyle] >= 0 &&
startrow + vertical[movestyle] <= 7 &&
startcolumn + horizontal[movestyle] >= 0 &&
startcolumn + horizontal[movestyle] <= 7){
visitLevel[startrow][startcolumn]++;
moveways[grid][movestyle] = 1;
}
}
grid++;
}
}//creat visit level&ways of each grid finish
//print level form
printf("********** visit level of each grid **********\n");
printf("(the bigger the visitvalue, the easier to visit, \n");
printf("so must visit the small value grid first)\n\n");
for (x = 0; x <= 7; x++){
for (y = 0; y <= 7; y++){
printf("%d ", visitLevel[x][y]);
}
printf("\n");
}
printf("-------------------------------------------------------------------------");
//print ways of each grid
printf("\n\n\n**********the move right of each grid**********\n");
printf("(each grid has 8 move right,but not every right is legal\n");
printf("the legal move can't overstep the boundary of the cheeseboard\n");
printf("each grid(row) try each move righ(column),and assign 1 to the legal move)\n\n");
for (x = 0; x <= 63; x++){
for (y = 0; y <= 7; y++)
printf("%d ", moveways[x][y]);
printf("\n");
}
printf("-------------------------------------------------------------------------");
printf("\n\n ***************Let's begin the knight's travel***************\n");
printf("enter the start row location:");
scanf("%d", &startrow);
printf("enter the start column location:");
scanf("%d", &startcolumn);
grid = 8 * startrow + startcolumn;//translate to array "moveways"
printf("Knight'travel begin from row[%d],column[%d]\n", startrow, startcolumn);
while (boardtotal(board) != 64){//once one grid visited,the grid's
//boardvalue will assign to 1,aft one step(one loop of while),
//boardtotal()will check and return total boardvalue,when it became 64
//loop stop,means the knight visited all grid of the fucking cheeseboard!
for (movestyle = 0; movestyle <= 7; movestyle++){//try 8 move rights
if (moveways[grid][movestyle] == 1){//see if the way of move rights leagle
if (visitLevel[startrow + vertical[movestyle]]//must visit the smallest visit value
[startcolumn + horizontal[movestyle]] <= best&&//compare value
board[startrow + vertical[movestyle]]//avoid visiting the visited grid again
[startcolumn + horizontal[movestyle]] == 0){
currentrow = startrow + vertical[movestyle];
currentcolumn = startcolumn + horizontal[movestyle];
best = visitLevel[currentrow][currentcolumn];
}
}
}
startrow = currentrow;//aft compare 8 ways,confirm the best way
startcolumn = currentcolumn;//also confirm new start location
best = 9;//initialize for next round
grid = 8 * currentrow + currentcolumn;//translate
board[currentrow][currentcolumn] = 1;//mark the visited grid with 1,others is 0
printf("\n→row[%d],column[%d],boardtotal[%d]\n",//print the step,total board value
currentrow, currentcolumn, boardtotal(board));
//down the level related to current grid(will be locked!)
//the visit value of grid A means how many other grids can visit it
//so once the grid which can visit grid A became the visited one
//the visit value of grid A must minus 1
for (movestyle = 0; movestyle <= 7; movestyle++){
if (moveways[grid][movestyle] == 1)//the grid which the visited grid can visit
visitLevel[currentrow + vertical[movestyle]]
[currentcolumn + horizontal[movestyle]]--;
}
}
}
int boardtotal(int board[][column]){
int x = 0, y = 0, d = 0;
for (x = 0; x <= row - 1; x++){
for (y = 0; y <= column - 1; y++)
d = d + board[x][y];
}
return d;
}