馬踏棋盤代碼分析
(因為最近數據結構講到圖和網,聽是能聽懂,可是一到代碼上,就發現問題很多,因此將馬踏棋盤的代碼拿出來分析下,貌似有些不對頭,其實呢是因為不想寫其余的作業,所以找個借口)
說到馬踏棋盤,這樣說,就是一個8*8的棋盤,指定一個位置,讓馬走日字,將棋盤上的點全部走完。
先說說思路:首先指定位置,在這個位置的基礎上走一個位置,然后再在這個基礎上走日字,現在面臨一個問題,要是走着走着,突然有一次,就那么的卡住在那里了,怎么走都不行,可是全局看下,會發現,還有空點沒有踏到,那么怎么辦?看來這條路不通了,那就得重新的找一條路,怎么從一條路到另一條路呢?那就是退回,要退回,必須有退回的路,因此呢,要有標記,不然,就找不到退回的路了,退回到另一條路,然后繼續探索,走日字,卡住了就退,哦,這里要記得將原來路也記一下,不然,你有可能重走這條不歸路。就這樣不停的走,不停地退,最終就會找到一條你想找的路。大體思路就是這樣的,思路簡單,用代碼寫起來,一定要邏輯清楚,我就是經常混在這種情況下,出不來進不去。
恩,來看代碼:
聲明:是MAXSIZE是100
先定義一個8*8的棋盤:
int board[8][8];
棋盤要進行初始化:N是8
for(i=0;i<N;i++)
for(j=0;j<N;j++)
board[i][j]=0;
那么現在要輸入馬踏的位置,這就需要用戶自己輸入:記得要進行完善,要是用戶輸入的坐標不正確,要提示重新輸入:
while(1)
{
printf("Please enter the location of the first step of the horse(1<=x<=8 and 1<=y<=8)\n");
printf("Input x = ");
scanf("%d",&x); //輸入起始位置的橫坐標
printf("Input y = ");
scanf("%d",&y); //輸入起始位置的縱坐標
if(x>=1&&x<=8&&y>=1&&y<=8)
break; //若輸入的坐標超出所給棋盤的允許范圍則跳出循環
printf("Your input is worng!!!\n");
}
當輸入正確后,就應該將值傳進去:調用起始坐標函數
InitLocation(x-1,y-1)
這里就要用到棧:利用棧的特點,來記錄走過的路
棧的定義:
struct Stack
{
int i; //行坐標
int j; //列坐標
int director; //存儲方向
}stack[MAXSIZE];
同時定義了一個棧指針:用來記錄棧的元素進入和刪除,相當於計數器
int top=-1;
然后是InitLocation函數
void InitLocation(int xi,int yi)
{
top++; //棧指針指向第一個棧的底層
stack[top].i=xi; //將起始位置的橫坐標進棧
stack[top].j=yi; //將起始位置的縱坐標進棧
stack[top].director=-1; //將起始位置的嘗試方向賦初值
board[xi][yi]=top+1; //標記棋盤
if(TryPath(xi,yi)) //調用馬兒探尋函數,如果馬兒探尋整個棋盤返回1否則返回0
Display(); //輸出馬兒的行走路徑
else
printf("sorry ,There is no solution");
}
上面有兩個函數:TryPath(x,y)和Display();
嘗試路徑:
int Htry1[8]={1,-1,-2,2,2,1,-1,-2};
//存儲馬各個出口位置相對當前位置行下標的增量數組
int Htry2[8]={2,-2,1,1,-1,-2,2,-1};
//存儲馬各個出口位置相對當前位置列下標的增量數組
int TryPath(int i,int j)
{
int find,director,number,min;
int i1,j1,h,k,s; //定義幾個臨時變量
int a[8],b1[8],b2[8],d[8]; //定義幾個臨時數組
while(top>-1) //棧不空時循環
{
for(h=0;h<8;h++) //用數組a[8]記錄當前位置的下一個位置的可行路徑的條數
{
number=0;
i=stack[top].i+Htry1[h];
j=stack[top].j+Htry2[h];
b1[h]=i;
b2[h]=j;
if(board[i][j]==0&&i>=0&&i<8&&j>=0&&j<8) //如果找到下一位置
{
for(k=0;k<8;k++)
{
i1=b1[h]+Htry1[k];
j1=b2[h]+Htry2[k];
if(board[i1][j1]==0&&i1>=0&&i1<8&&j1>=0&&j1<8) //如果找到下一位置
number++; //記錄條數
}
a[h]=number; //將條數存入數組a[8]中
}
}
for(h=0;h<8;h++) //根據可行路徑條數小到大按下表排序放入數組d[8]中
{
min=9;
for(k=0;k<8;k++)
if(min>a[k])
{
min=a[k];
d[h]=k; //將下表存入數組d[8]中
s=k;
}
a[s]=9;
}
director=stack[top].director;
if(top>=63) //如果走完整個棋盤返回
return (1);
find=0; //表示沒有找到下一個位置
for(h=director+1;h<8;h++) //向八個方向進行探尋
{
i=stack[top].i+Htry1[d[h]];
j=stack[top].j+Htry2[d[h]];
if(board[i][j]==0&&i>=0&&i<8&&j>=0&&j<8) //如果找到下一位置
{
find=1; //表示找到下一個位置
break;
}
}
if(find==1) //如果找到下一個位置進棧
{
stack[top].director=director; //存儲棧結點的方向
top++; //棧指針前移進棧
stack[top].i=i;
stack[top].j=j;
stack[top].director=-1; //重新初始化下一棧結點的嘗試方向
board[i][j]=top+1; //標記棋盤
}
else //否則退棧
{
board[stack[top].i][stack[top].j]=0; //清除棋盤的標記
top--; //棧指針前移退棧
}
}
return (0);
}
打印棋盤:board[i][j]里已經記錄了走的次序,只需輸出即可
void Display()
{
int i,j;
for(i=0;i<N;i++)
{
for(j=0;j<N;j++)
printf("\t%d ",board[i][j]); //輸出馬兒在棋盤上走過的路徑
printf("\n\n");
}
printf("\n");
}
恩恩 結束了,哦在來個運行結果截圖:
by:暖暖
20141124