数据结构栈的使用——马踏棋盘

题目

设计一个国际象棋的马踏遍棋盘的演示程序。

将马随机放在国际象棋棋盘8×8棋盘 map[8][8]的某个方格中,马按照走棋规则进行移动。要求每个方格只进入一次,走遍棋盘上全部64个方格。编制程序,求出马的行走路线,并按求出的行走路线,将数字1,2,.......,64依次填入一个8×8的方阵,输出之。可自行指定一个马的初始位置(x,y)。下面图中显示了马位于方格位置中8个可移动的位置。

每次在多个可走位置中选择其中一个进行试探,其余未曾试探过的可走位置必须用适当的结构妥善管理,以备试探失败时“回溯”(悔棋)使用。

 结构体的定义:

#define MAX 64
typedef struct 	//存储马可以踏成功的位置 
{
	int x,y;	 
}postion;

typedef struct Zhan		//栈就是存储已经成功踏入的点 
{
	postion a[MAX];		//存位置 
	int top;	//栈顶位置 
}Zhan;		//结构体别名 

栈需要进行初始化,初始化函数的代码如下:

void InitZhan(Zhan *s)	//栈的初始化 
{
	s->top=-1;
}

压栈和退栈的操作与简单栈的操作相同代码如下所示:

int Push(Zhan *s,postion x)	//存数据的函数 
{	
	if(s->top==MAX-1)	//判断栈有没有存满也就是马有没有把棋盘踏完 
		return 0;	
	else		//没有踏完 
	{
		s->top++;	//栈顶先加 
		s->a[s->top]=x;	// 存入栈里 
		return 1;	
	 } 
}

int Pop(Zhan *s)	//如果马已经无路可走就退回上一步,然后继续判断其他的路 
{
	if(s->top==-1)	//栈有没有空 
	return 0;
	else	//没空的时候就让栈顶减1 
	{
		s->top--;
		return 1;
	}
}

在马进行踏迷宫的时候需要有一个函数判断我们存储数据的栈中的元素是否已经全部退出完成,其中的代码如下所示:

int IsEmpty(Zhan *s)	//栈有没有空的一个函数 
{
	if(s->top==-1)
		return 1;
	return 0;
}

在找马可以走的位置还需要有一个得到栈顶位置的函数,其中代码如下:

postion Gettop(Zhan *s)	//找到栈顶的位置在哪 
{
	postion x;
	x=s->a[s->top];
	return x;
}

在该程序中需要定义两个[8][8]的数组初始值为0,一个用来存储马在其中踏的第几次,另一个则用来判断马有没有将其走过。和马可以走的八个位置的数组,还需定义一个标记变量,用来判断马有没有踏完棋盘。(其中全为全局变量,还需定义一个栈)

定义如下所示:

int map[8][8]={0};	//初始化棋盘 
int book[8][8]={0};	//存储有没有走 
int next[8][2]={-2,1,-1,2,1,2,2,1,2,-1,1,-2,-1,-2,-2,-1};	//
int flag=0;	//一个变量判断有没有走完 
Zhan s;	//先定义一个栈 

然后下来就是该程序的核心代码,也就是马该怎么走,该函数包含三个参数,两个用来存储马的坐标位置,第三个参数用来存储马走了第几步。在函数中首先判断马有没有将棋盘走完,如果走完了则在其中将判断变量值设置为1,且定义一个次数变量,加一个循环其停止条件则是该栈为空,当栈一直不为空时则让一个结构体存储栈顶的数据,然后进行退栈操作随后将map中的栈顶位置存储为最后一个位置,依次类推存储马走的位置。然后当栈为空时退出循环打印马走的棋盘。如果马没有将棋盘走完则让马的当前位置判断周围的八个点是否可以走,如果可以走则标记该点已走过然后将数据存入栈中,如果走不了则继续进行循环直到八个点都不可以走之后则将栈元素退出然后标记值设置为0,再次调用该函数让马继续走。

核心代码如下所示:

void Run(int x,int y,int step)	//马走的函数 
{
	if(step==64)	//判断棋盘走没走完,走完就输出地图 
	{
		flag=1;	//走完变量为1 
		int Count=0;	//走的次数 
		while(!IsEmpty(&s))	//判断栈有没有空 
		{
			postion n =Gettop(&s);	// 让n获得栈顶的位置 
			Pop(&s);	//退出一个位置,为了得到下一个位置所以得到栈顶后需要退出栈顶的元素 
			map[n.x][n.y]=64-(Count++);	//将栈退出的次数存入地图中 
		}
		for(int i=0;i<8;i++)	//打印棋盘 
		{
			for(int j=0;j<8;j++)
			{
					cout<<map[i][j]<<" "; 	//相当于C语言的printf 
			}
			cout<<endl;	//相当于\n 
		}
		return ;
	}
	for(int i=0;i<8;i++)	//马当前可以走的8个位置 
	{	
		int x1=x+next[i][0];	//找到马走的下一步的x位置	
		int y1=y+next[i][1];	//找到马走的下一步的y位置	
		if(x1<0||x1>7||y1<0||y1>7||book[x1][y1]==1)	//判断马的下一步有没有超过棋盘的位置,如果超过了则继续返回循环 
		{
			continue;
		}
		if(book[x1][y1]==0)	//判断马的下一步走了没走 
		{
			book[x1][y1]=1;	//马已经走了这一步 
			postion p;	//存x,y的结构体 ,把马当前的位置存在p中 
			p.x=x1;	
			p.y=y1;
			Push(&s,p);	//把结构体p放在栈中 
			Run(x1,y1,step+1);	//递归下一步, 
			if(flag)	return ;	// 如果已经走完直接出函数 
			book[x1][y1]=0;	//把当前马的位置设置为0,也就是没有走 
			Pop(&s);	//把存储进去的位置退出来 
		}
	}
	return ;
}

整体的完整代码如下所示:

#include<iostream>	//include<stdio.h> 
#include<stdlib.h>	//开辟空间的头文件malloc 
#include<iomanip>	//不写 
using namespace std;	//可以不写 

#define MAX 64
typedef struct 	//存储马可以踏成功的位置 
{
	int x,y;	 
}postion;

typedef struct Zhan		//栈就是存储已经成功踏入的点 
{
	postion a[MAX];		//存位置 
	int top;	//栈顶位置 
}Zhan;		//结构体别名 

void InitZhan(Zhan *s)	//栈的初始化 
{
	s->top=-1;
}

int Push(Zhan *s,postion x)	//存数据的函数 
{	
	if(s->top==MAX-1)	//判断栈有没有存满也就是马有没有把棋盘踏完 
		return 0;	
	else		//没有踏完 
	{
		s->top++;	//栈顶先加 
		s->a[s->top]=x;	// 存入栈里 
		return 1;	
	 } 
}

int Pop(Zhan *s)	//如果马已经无路可走就退回上一步,然后继续判断其他的路 
{
	if(s->top==-1)	//栈有没有空 
	return 0;
	else	//没空的时候就让栈顶减1 
	{
		s->top--;
		return 1;
	}
}

int IsEmpty(Zhan *s)	//栈有没有空的一个函数 
{
	if(s->top==-1)
		return 1;
	return 0;
}

postion Gettop(Zhan *s)	//找到栈顶的位置在哪 
{
	postion x;
	x=s->a[s->top];
	return x;
}

int map[8][8]={0};	//初始化棋盘 
int book[8][8]={0};	//存储有没有走 
int next[8][2]={-2,1,-1,2,1,2,2,1,2,-1,1,-2,-1,-2,-2,-1};	//
int flag=0;	//一个变量判断有没有走完 
Zhan s;	//先定义一个栈 

void Run(int x,int y,int step)	//马走的函数 
{
	if(step==64)	//判断棋盘走没走完,走完就输出地图 
	{
		flag=1;	//走完变量为1 
		int Count=0;	//走的次数 
		while(!IsEmpty(&s))	//判断栈有没有空 
		{
			postion n =Gettop(&s);	// 让n获得栈顶的位置 
			Pop(&s);	//退出一个位置,为了得到下一个位置所以得到栈顶后需要退出栈顶的元素 
			map[n.x][n.y]=64-(Count++);	//将栈退出的次数存入地图中 
		}
		for(int i=0;i<8;i++)	//打印棋盘 
		{
			for(int j=0;j<8;j++)
			{
					cout<<map[i][j]<<" "; 	//相当于C语言的printf 
			}
			cout<<endl;	//相当于\n 
		}
		return ;
	}
	for(int i=0;i<8;i++)	//马当前可以走的8个位置 
	{	
		int x1=x+next[i][0];	//找到马走的下一步的x位置	
		int y1=y+next[i][1];	//找到马走的下一步的y位置	
		if(x1<0||x1>7||y1<0||y1>7||book[x1][y1]==1)	//判断马的下一步有没有超过棋盘的位置,如果超过了则继续返回循环 
		{
			continue;
		}
		if(book[x1][y1]==0)	//判断马的下一步走了没走 
		{
			book[x1][y1]=1;	//马已经走了这一步 
			postion p;	//存x,y的结构体 ,把马当前的位置存在p中 
			p.x=x1;	
			p.y=y1;
			Push(&s,p);	//把结构体p放在栈中 
			Run(x1,y1,step+1);	//递归下一步, 
			if(flag)	return ;	// 如果已经走完直接出函数 
			book[x1][y1]=0;	//把当前马的位置设置为0,也就是没有走 
			Pop(&s);	//把存储进去的位置退出来 
		}
	}
	return ;
}

int main()
{
	InitZhan(&s);	//初始化 
	int x,y;	
	cout<<"请输入马的初始位置->";	//printf 
	cin>>x>>y;		//相当于c语言的scanf 
	map[x][y]=1;	//先存储初始位置 
	book[x][y]=1;	//马已经走过存1 
	Run(x,y,1); 	//运行初始位置时马走的步 
	return 0;
}

最终运行的结果如下图所示:

 输入其他值可能会导致运行变慢因为马踏的时候可能会存在很多次回溯所以运行的时间会变的很长,甚至有些位置可能不会踏完棋盘。

  • 7
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小侯不躺平.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值