用链式栈实现的马踏棋盘回溯算法问题

主体思路

马儿由用户输入,出现在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);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章