问题:假设国际象棋棋盘有5*5共25个格子。设计一个程序,使棋子从初始位置(棋盘编号为1的位置)开始跳马,能够把棋盘的格子全部都走一遍,每个格子只允许走一次。遍历打印出5*5的格子,并在每个格子填写跳马的先后顺序,例如左上角第一个格子是1。
程序:
#include<stdio.h>
#include<stdlib.h>
#define X 5
#define Y 5
int count=0;
int chess[X][Y]={{0}};
void print()
{
int i,j;
for(i=0;i<X;i++)
{
for(j=0;j<Y;j++)
{
printf("%-2d ",chess[i][j]);
}
printf("\n");
}
printf("\n");
}
void visit(int i,int j,int tag)
{
int x=i;
int y=j;
chess[x][y]=tag;
if(tag==X*Y)
{
printf("第%d种解法\n",++count);
print();
}
//左上对角下
if(x-1>=0&&y-2>=0&&chess[x-1][y-2]==0)
{
visit(x-1,y-2,tag+1);
}
//左上对角上
if(x-2>=0&&y-1>=0&&chess[x-2][y-1]==0)
{
visit(x-2,y-1,tag+1);
}
//右上对角下
if(x-1>=0&&y+2<Y&&chess[x-1][y+2]==0)
{
visit(x-1,y+2,tag+1);
}
//右上对角上
if(x-2>=0&&y+1<Y&&chess[x-2][y+1]==0)
{
visit(x-2,y+1,tag+1);
}
//左下对角下
if(x+2<X&&y-1>=0&&chess[x+2][y-1]==0)
{
visit(x+2,y-1,tag+1);
}
//左下对角上
if(x+1<X&&y-2>=0&&chess[x+1][y-2]==0)
{
visit(x+1,y-2,tag+1);
}
//右下对角下
if(x+2<X&&y+1<Y&&chess[x+2][y+1]==0)
{
visit(x+2,y+1,tag+1);
}
//右下对角上
if(x+1<X&&y+2<Y&&chess[x+1][y+2]==0)
{
visit(x+1,y+2,tag+1);
}
chess[x][y]=0;
}
void main()
{
int x,y;
printf("输入初始坐标,横纵坐标都从0开始,例如0,0\n");
scanf("%d,%d",&x,&y);
visit(x,y,1);
}
思考:此题也是递归回溯的思想。当确定一个位置之后,要考虑8种可以跳马的方向,设置一个记步数的变量tag,当tag为25时退出递归,同时把最后确定的一个位置,即写着25的格子的变量重置为0,同时退回到第24步,去寻找其它第25步的可能位置。