用鏈式棧實現的馬踏棋盤迴溯算法問題

主體思路

馬兒由用戶輸入,出現在8*8棋盤(棋盤可以改大小)的任意位置,接下來它會根據選擇最難走的路,這一想法不斷前進,每次前進都會判斷該位置的下一步走哪裏最困難能走的路最少,先走最少的路,之後才能走的順利,否則容易卡很久。這算是數據結構的作業,能力有限,代碼比較長,高手勿噴。。。

代碼

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//X,Y值可以修改,但是棋盤必須在6*6-9*9之間
#define X 8
#define Y 8

//全局變量
int list[X][Y];//X*Y棋盤
int HTry1[8]={-2,-1,1,2,2,1,-1,-2};
int HTry2[8]={1,2,2,1,-1,-2,-2,-1};

//**鏈表準備**
//創建鏈表
struct Node
{
	int x;//列項
	int y;//橫項
	int index;//當前步數
	int lt[8];//當前可行路線
	struct Node* next;//指針指向下一步的結點
};
//初始化鏈表
struct Node* createList()
{
	struct Node* headNode = (struct Node*)malloc(sizeof(struct Node));
	headNode->next = NULL;
	return headNode;//返回頭結點
}

//創建結點
struct Node* createNode(int x,int y,int index)
{
	int i;
	struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
	newNode->x = x;
	newNode->y = y;
	newNode->index = index;
	for(i=0;i<8;i++){
		if(x+HTry1[i]>=0&&y+HTry2[i]>=0&&x+HTry1[i]<=X-1&&y+HTry2[i]<=Y-1&&list[x+HTry1[i]][y+HTry2[i]]==0)
			{
				newNode->lt[i]=(x+HTry1[i])*10+y+HTry2[i];
			}
		}
	newNode->next = NULL;
	return newNode;
}



//打印鏈表
void printList(struct Node* headNode)
{
	struct Node* pMove = headNode->next;
	int i;
	while(pMove)
	{
		printf("(%d,%d,%d)->",pMove->x,pMove->y,pMove->index);
		pMove = pMove->next;
	}

}

//打印棋盤
void printarg(struct Node* headNode)
{
	struct Node* pMove = headNode->next;
	int i,j;
	int arg[X][Y];
	for(i=0;i<X;i++){
		for(j=0;j<Y;j++){
			arg[i][j]=0;
		}
	}
	printf("\n");
	while(pMove)
	{
		arg[pMove->x][pMove->y]=pMove->index;
		pMove = pMove->next;
	}
	for(i=0;i<X;i++){
		for(j=0;j<Y;j++){
			printf("%-3d",arg[i][j]);
		}
		printf("\n");
	}
	

}
//獲取指向鏈表最後一個元素的指針p
struct Node* P(struct Node* L){
	struct Node* p=L;
	while(p->next!=NULL){
			p=p->next;
		}
	return p;
}


//判斷該位置有幾個可行點
int num(int x,int y){
	int a=0,i;
	for(i=0;i<8;i++){
		if(x+HTry1[i]>=0&&y+HTry2[i]>=0&&x+HTry1[i]<=X-1&&y+HTry2[i]<=Y-1&&list[x+HTry1[i]][y+HTry2[i]]==0)
			{
				a+=1;
			}
		}
	return a;
}

//尾部插入結點
//馬前進
//入棧函數
int insertNode(struct Node* headNode,int x,int y,int index)
{
	if(x>=0 && y>=0 && x<=X-1 && y<=Y-1){
		struct Node* p = headNode;
		while(p->next!=NULL){
			p=p->next;
		}
		struct Node* newNode = createNode(x,y,index);
		newNode->next = p->next;
		p->next = newNode;
		return 1;
	}
	return 0;
}

//馬回頭
//出棧函數
int back(struct Node* headNode){
	struct Node* p = headNode;
	struct Node* q;
	int a;

	while(p->next->next!=NULL){
		p=p->next;
	}
	q=p->next;
	p->next=p->next->next;
	a = (q->x)*10+(q->y);
	free(q);
	return a;
}
int main()
{
	int a=0,b=0,h,i,n=1,j,index=1,index2,min;
	int ls[8],ls1[8]={9,9,9,9,9,9,9,9};
	struct Node* L = createList();//獲得頭節點,頭節點沒有數據域
	struct Node* p = L;//指針p主要用於遍歷結點

	//獲得用戶輸入
	printf("在%d*%d的棋盤中,請輸入馬所在的初始位置(輸入範圍內的整數座標,空格相隔):",X,Y);
	while(1){
		scanf("%d",&i);
		scanf("%d",&j);
		if(i>=0&&i<X&&j>=0&&j<=Y)break;
		else printf("\n輸入不合法!!!請重新輸入:\n");
	}
	//初始化首元結點,另該位置爲1,表示已經走過
	insertNode(L,i,j,index);
	list[i][j]=1;
	//主循環,馬兒會在此走完其餘的棋盤
	while(n<X*Y){
		//初始化數據,或者重置數據
		index2=0;
		for(h=0;h<8;h++){
			ls1[h]=9;	
		}
		//測試可前進
		p=P(L);
		for(h=0;h<8;h++){ 
			if(p->lt[h]>=0)
			{
			index2++;
			}
		}
		//回溯
		if(index2==0){
			a = back(L); 
			n--;
			list[a/10][a%10]=0;
			p=P(L);
			for(i=0;i<8;i++){
				if(p->lt[i]==a){
					p->lt[i]=-1;
				}
			}i=0;
		}
		//嘗試插入結點
		else{
			//獲得最難走的路
			p=P(L);
			for(h=0;h<8;h++){
				if(p->lt[h]<0){
					continue;
				}
				if (p->lt[h]>=0&&p->lt[h]<=9){
					i=0;
					j=p->lt[h];
				}
				else if(p->lt[h]>=10){
					i=p->lt[h]/10;
					j=p->lt[h]%10;
				}
				ls1[h]=num(i,j);
			}
			min=9;
			//該位置最難走的路的可行數min
			for(h=0;h<8;h++){
				if(ls1[h]<min){
					min=ls1[h];
				}
			}
			//獲得最難走的位置的座標i,j
			for(h=0;h<8;h++){
				if(ls1[h]==min){
					i=p->lt[h]/10;
					j=p->lt[h]%10;
					break;
				}
			}
		//插入結點
			insertNode(L,i,j,++n);
			list[i][j]=1;
		}
		}
printarg(L);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章