数据结构课程设计 马踏棋盘求全部解及演示程序

合集下载

马的遍历VC++课程设计报告

马的遍历VC++课程设计报告

课程设计报告学院、系:专业名称:网络工程课程设计科目VC++程序课程设计学生姓名:指导教师:完成时间:2010年9月-11月解骑士巡游问题一、设计任务与目标国际象棋中马采用“日”字走法,对棋盘上马所在的结点,一步内到达的结点最多有八个,即假设马所在点的坐标为(i,j),那么其它八个结点的坐标为(i+1,j+2),(i+2,j+1),(i+2,j-1),(i+1,j-2),(i-1,j-2),(i-2,j-1),(i-2,j+1),(i-1,j+2)把这些点看作马所在点的邻接点,所以可以采用类似图的深度优先遍历,以马所在点为初始点对整个棋盘进行遍历。

然后按遍历的顺序输出结点棋盘的规格限制为8*8,输入数据为起始点的位置(0-7)。

输出数据为可以遍历成功的若干方案(本程序设置为至多八种)。

二、方案设计与论证解决马的遍历问题,可以用一个二维数组board[][]来表示棋盘,一开始用来存放步骤号,若走过了则把它赋值为1。

另对马的8种可能走法设定一个顺序,如当前位置在棋盘的(i,j)方格,下一个可能的位置依次为(i+2,j+1)、(i+1,j+2)、(i-1,j+2)、(i-2,j+1)、(i-2,j-1)、(i-1,j-2)、(i+1,j-2)、(i+2,j-1),实际可以走的位置尽限于还未走过的和不越出边界的那些位置。

为便于程序的同意处理,可以引入两个数组mover[]、movec[],分别存储各种可能走法对当前位置的纵横增量。

整形变量step存放步骤号,start存放遍历次数,在numable函数和number函数中的语句k=(i+start)%N;中是用于定位,保证不会超过棋盘范围和八次遍历都不会走同样的路径test存放遍历成功次数。

在8×8方格的棋盘上,从任意指定的方格出发,为马寻找一条走遍棋盘每一格并且只经过一次的一条路径。

程序框图或流程图,程序清单与调用关系调用调用函数调用关系2.重要模块(next模块)的流程图: 否图2.2 流程图三、全部源程序清单#include<iostream.h>#include<iomanip.h>#include<stdlib.h>#define N 8//棋盘行列数#define INF 9999999int mover[]={-2,-1,1,2,2,1,-1,-2};//用来表示要走向该i行,需要移动的格子数int movec[]={1,2,2,1,-1,-2,-2,-1};//用来表示要走向该j列,需要移动的格子数class qi{private :int board[N+1][N+1];//用于保存走的次序int start;//测试次数int ber,bec;//用于保存输入(初始)的行列int step;//走的步数int test;//可以遍历成功的次数int r,c;//当前行列值int i,j;//循环变量int k;//下次可以查找的增量的个数public :qi();qi(int a,int b);int next(int r, int c);int numable(int r,int c,int nexta[]);//返回下次可以查找的增量int number(int r,int c);//返回下次可以查找的增量的个数bool begin(int a,int b);void set(int a,int b);};qi::qi(int a,int b){ber=a;bec=b;}qi::qi(){}void qi::set(int a,int b){ber=a;bec=b;}int qi::next(int r,int c){int nexta[20],num,num1=0,minnum,i,k;minnum=INF;//初始化minnumnum=numable(r,c,nexta);//下次可以查找的增量if(num==0)return -1; //没有出口for(i=0;i<=num-1;i++)//预测路径{num1=number(r+mover[nexta[i]],c+movec[nexta[i]]);if(num1<=minnum){minnum=num1;k=nexta[i];//存放预测路径中的格子}}return k;//出口为k}bool qi::begin(int a,int b){cout<<"输入行,列(0-7):"<<endl;ber=a;bec=b;start=0;test=1;while(start<8)//进行测试的次数{for(i=0;i<N;i++)//初始化board数组for(j=0;j<N;j++)board[i][j]=0;r=ber;//将当前行值赋给rc=bec;//将当前列值赋给cboard[r][c]=1;//先将初始位置赋值为一step=2;//一共走的步数while(1){if(step>N*N)//如果步数大于棋盘的格子数则表明遍历成功{cout<<"方案"<<test++<<":"<<endl;for(i=0;i<N;i++)//打印出该方案{for(j=0;j<N;j++)cout<<board[i][j]<<" ";cout<<endl;}cout<<endl;start++;//测试次数加一break;//进行下一次测试}k=next(r,c);//下次可以查找的增量的个数if(k==-1)//此路不通{start++;//测试次数加一break;//进行下一次测试}r=r+mover[k];//将当前格子行的位置赋值给rc=c+movec[k];//将当前格子列的位置赋值给cboard[r][c]=step;//将步数存入board中step++;//步数加一}}return true;}int qi::number(int r,int c){int i,k,a,b;int num=0;for(i=0;i<N;i++){k=(i+start)%N;//用于定位,保证不会超过棋盘范围和八次遍历都不会走同样的路径,并且用于控制8种可能着法的选择顺序a=r+mover[k];//由当前格子可以访问的行b=c+movec[k];//由当前格子可以访问的列if(a<N&&a>=0&&b>=0&&b<N&&board[a][b]==0)num++;//由当前格子可以访问,并且尚未访问过的格子数目}return num;}int qi::numable(int r,int c,int nexta[]){int i,k,a,b;int num=0;for(i=0;i<N;i++){k=(i+start)%N;//用于定位,保证不会超过棋盘范围和八次遍历都不会走同样的路径,并且用于控制8种可能着法的选择顺序a=r+mover[k];//由当前格子可以访问的行b=c+movec[k];//由当前格子可以访问的列if(a<=7&&a>=0&&b>=0&&b<=7&&board[a][b]==0)//下次可以访问的格子,并且尚未访问的格子{nexta[num]=k;//下次可以访问的格子num++;}}return num;}int main(){qi q;int a,b,d=1;char c;while(d!=0){cout<<"输入行,列(0-7):"<<endl;cin>>a>>b;q.begin(a,b);cout<<"是否继续(y&n):";cin>>c;if(c=='y'||c=='Y')d=1;elsed=0;system("cls");}return 0;}四、程序运行的测试与分析因为本程序最大的特点就是可以将所有可遍历成功的路径都显示出来,所以我用了两组测试数据分别对有八种成功遍历路径和小于八种成功遍历路径的情况进行说明。

数据结构课程设计马的遍历

数据结构课程设计马的遍历

课程设计说明书课程名称:数据结构设计题目:马的遍历院系:计算机科学与信息工程学院学生姓名:学号:专业班级:指导教师:2015 年 6 月7 日课程设计任务书马的遍历摘要:中国象棋中马采用“日”字走法,对棋盘上马所在的结点,一步内到达的结点最多有八个,所以可以采用类似图的深度优先遍历,以马所在点为初始点对整个棋盘进行遍历。

然后按遍历的顺序输出结点可以用一个二维数组chess[][]来表示棋盘,一开始用来存放步骤号,若走过了则把它赋值为0。

对于动态演示问题,只要在“马”的位置显示“马”,已经走过的位置显示“●”,未走过的位置显示“┌”“┬”“┐”“├”等制表符,然后清屏,显示下一步,再清屏,依次类推。

关键词:深度优先遍历;回溯法;数组存储棋盘;动态演示;目录1.设计背景 (1)1.1问题描述 (1)1.2基本要求 (1)2.设计方案 (1)2.1问题分析和任务定义 (1)2.2概要设计和数据结构的选择 (2)3. 方案实施 (3)3.1数据结构设计 (3)3.2功能函数设计 (4)3.3编码实现 (5)4. 结果与结论 (14)4.1输入初始数据 (14)4.2判断能否遍历 (14)4.3动态演示 (14)5. 收获与致谢 (15)6.参考文献 (15)1. 设计背景1.1 问题描述:中国象棋是10*9的棋盘,马的走法是“马走日”,这里忽略了“蹩脚马”的情况,使马的遍历问题简单化。

马在棋盘上遍历采用算法当中的优先算法和回溯法;从入口出发,按某一方向向前探索,若能走通并且从未走过,即某处可到达,则到达新店,否则探索下一个方向;如果发生“阻塞”的情况,就是后面走不通的情况,则沿原路返回到前一点,换一个方向再继续试探,知道找到一条通路,或无路可走又返回到入口点。

期盼中马的遍历采用数组进行存储,同时因为有回溯,所以采用栈的方法,并且为了最后打印方便,采用的是顺序栈的方法。

同时还有八个方向的数组,和为栈设计的每个点周围的八个方向那些可以走的数组。

第七次实验 马踏棋盘问题

第七次实验  马踏棋盘问题
四,实验内容与步骤
#include<stdio.h>
#include<stdlib.h>
typedef struct
{
int x;
int y; //棋盘上的坐标
}Coordinate;
int chessboard[8][8];; //棋盘
int curstep; //马跳的步骤序号
Coordinate fangxiang[8]= //马可走的方向
桂林电子科技大学
数学与计算科学学院综合性、设计性实验报告
实验室:06406实验日期:2015年05月29日
院(系)
信息与计算科学系
年级、专业、班
1300710226
姓名
庞文正
成绩
课程
名称
数据结构实验
实验项目
名 称
马踏棋盘问题
指导
教师
教师
评语
教师签名:
年 月 日
一 ,实验目的
加深对图的理解,培养解决实际问题的编程能力。根据数据对象的特性,学会数据组织的方
19(4,4)
20(5,4)
11(1,3)
12(2,3)
13(3,3)
14(4,3)
15(5,3)
6(1,2)
7(2,2)
8(3,2)
9(4,2)
10(5,2)
1(1,1)
2(2,1)
3(3,1)
பைடு நூலகம்4(4,1)
5(5,1)
综合起来,马踏棋盘问题就可以转化为图的遍历问题。
三,使用仪器,材料
XP系统电脑一台,vc++软件!
{
printf("输入数值越界,请重新输入!\n");

马踏棋盘-大学课程设计

马踏棋盘-大学课程设计

马踏棋盘一目的1、巩固和加深对线性表、栈、队列、字符串、树、图、查找、排序等理论知识的理解。

2、掌握现实复杂问题的分析建模和解决方法(包括问题描述、系统分析、设计建模、代码实现、结果分析等)。

3、提高利用计算机分析解决综合性实际问题的基本能力。

4、加强对基础知识的运用,做到学以致用。

5、二需求分析1、从键盘输入马起始的横坐标x和纵坐标y,其范围都是0-7。

2、马按走棋规则进行移动,要求每个方格只进入一次,走遍棋盘上全部64个方格。

3、一般说来,当马位于位置(i,j)时,可以走到下列8个位置之一( x-2,y+1),(x-1,y+2),(x+1,y+2),(x+2,y+1),(x+2,y-1)(x+1,y-2),(x-1,y-2),(x-2,y-1)4、求出马的行走路线,将数字1到64依次填入一个8X8的方阵,输出到文本中(文本中能清楚看到方阵)。

输出的形式;(1)以数组下标形式输入,代表起始位置,i表示行标,j表示列标。

(2)以棋盘形式输出,每一格打印马走的步数,这种方式比较直观。

3、程序所能达到的功能;(1)让马从任一起点出发都能够历遍整个8×8的棋盘。

(2)能寻找多条不同的行走路径。

4.测试数据,包括正确的输入及输出结果和含有错误的输入及其输出结果。

数据可以任定,只要 0<=X<7&&0<=Y<7 就可以了。

正确的输出结果为一个2维数组,每个元素的值表示马行走的第几步。

若输入有错,程序会显示“输入错误,请重新输入:”并且要求用户重新输入数据,直至输入正确为止。

三概要设计initstack(s) //构建一个空栈。

push(s,e) //在栈顶插入新的元素。

pop(s,e)//将栈顶元素弹出。

settop(s, e) //将e设为栈顶元素。

gettop(s, e)//将栈顶元素取出。

stackempty(s) //判断栈是否为空check(int x,int y)//判断点(x,y)是否在棋盘内weighting()//求棋盘中每一点的权值四详细设计1、名称详细内容详细内容详细内容详细内容详细内容详细内容详细内容详细内容详细内容详棋盘点的结构类型定义typedef struct{int x;该点的横坐标int y;该点的纵坐标int z;}elemtype;栈的类型定义typedef struct SNode{elemtype data;struct SNode *next;}SNode,*Linkstack;栈的初始化操作int initstack(Linkstack &s){s=(Linkstack)malloc(sizeof(SNode));if(!s){printf("初始化失败!");return 0;}s->next=NULL;return 1;}入栈操作int push(Linkstack &s,elemtype e){Linkstack p;p=(Linkstack)malloc(sizeof(SNode));if(!p) return 0;p->next=s->next;s->next=p;p->data=e;return 1;}出栈操作int pop(Linkstack &s,elemtype &e) {Linkstack p=s->next;if(p==NULL) return 0;s->next=p->next;e=p->data;free(p);return 1;}取栈顶元素操作gettop(Linkstack &s,elemtype &e) {Linkstack p=s->next;if(p==NULL) return 0;e=p->data;return 1;}判断栈是否为空操作int stackempty(Linkstack s){int flag=0;if(s->next==NULL)flag=1;return flag;}设为栈顶元素操作int settop(Linkstack &s,elemtype e) {if(s->next!=NULL){s->next->data=e;return 1;}else return 0;}void setmap(){int i,j,k,m,d1,d2,x1,x2,y1,y2,l1,l2; for(i=0;i<N;i++)//for 1{for(j=0;j<N;j++)//for 2{for(k=0;k<8;k++)map[i][j][k]=k;//默认8个方向顺时针赋值for(k=0;k<8;k++)//for 3 与 for 4 两个循环对方向索引按点的权值升序排列,不能到达的方向排在最后{for(m=k+1;m<8;m++) //for 4{d1=map[i][j][k];x1=i+HTry1[d1];y1=j+HTry2[d1];d2=map[i][j][m];x2=i+HTry1[d2];y2=j+HTry2[d2];l1=check(x1,y1);l2=check(x2,y2);if((l1==0&&l2)||(l1&&l2&&(weight[x1][y1]>weight[x2][y2]))){map[i][j][k]=d2;map[i][j][m]=d1; //交换两个方向值,按权值递增排列,不可到达的目标点(超出棋盘)的方向放在最后面}//end if}//end for 4}//end for 3}//end for 2}//end for 1}//end setmap()void path(int xx, int yy){ int c[N*N]={0},h[N*N]={0};Linkstack a;elemtype ptemp;elemtype pop_temp,get_temp;elemtype p,dest_p; //当前点和目标点int step=0,x,y,s,k=1,l=1,d =0;char ch;p.x = xx; p.y = yy;p.z = 0;//初始化出发点board[xx][yy]=1;initstack(a);push(a,p); //起始点的坐标和首选方向入栈while(1){if (step==63){output(a);exit(1);}if(stackempty(a)) break;gettop(a,p);x=p.x; y=p.y; d=p.z;if(d>=8)//该点所有方向已走完,退栈{board[x][y]=0; //抹去痕迹step--; //步数减一pop(a,pop_temp); //退栈gettop(a,get_temp); //取当前栈顶元素ptemp.x=get_temp.x;ptemp.y=get_temp.y;ptemp.z=get_temp.z+1;settop(a,ptemp); //更改方向gettop(a,p);} //end if (d>=8)if(d<8)//方向未走完{s=map[x][y][d];//map[x][y][0]未必是(x,y)点的HTry[0]方向,而是到该点可到的权值最小的点的方向即HTry[map[x][y][0]dest_p.x=x+HTry1[s];dest_p.y=y+HTry2[s];if(check(dest_p.x,dest_p.y)&&board[dest_p.x][dest_p.y]==0)//目标点在棋盘内且未被走过,则将目标点入栈同时标记当前点为已走过{h[step]=step;board[x][y]=1;step++;//步数加一dest_p.z=0;push(a,dest_p);//存入目标点,方向栈初始}else//目标点已被走过或目标点不在棋盘内,换方向{ //printf(" 进行");ptemp.x=p.x;ptemp.y=p.y;ptemp.z=d+1;//取下一个方向 settop(a,ptemp);//切换方向// gettop(a,p);//gettop(a,p);//x=p.x; y=p.y; d=p.z;检测重新将d赋值//printf("%d %d %d",x,y,d);}} //enf if(d<8)//printf("步数%d\n ",step);} //end while(1)}void output(Linkstack a){ Linkstack b;int c[8][8]={0},i,j,k=N*N,l=1,x,y;initstack(b);elemtype e;while(!stackempty(a)){pop(a,e);c[e.x][e.y]=k;k--;push(b,e);}gettop(b,e);x=e.x;y=e.y;printf("起始坐标:(%d,%d)\n",x,y);while(!stackempty(b)){ pop(b,e);printf("(%d,%d)",e.x,e.y);push(a,e);}printf("棋盘表示为:\n");for(i=0;i<8;i++){for(j=0;j<8;j++){printf("%2d",c[i][j]);printf(" ");if(j==7) printf("\n");}}}五调试分析1、设计gettop函数时误将栈顶元素取出,原因是多加了一条s->next=p->next语句,造成不应有的错误2、写settop(s)函数时,忘记了s仅为头结点误将e赋值给了s->data,而实际上应为s->next->data=e;由此造成的错误极难发现,这也进一步说明了基础知识的重要。

马的遍历问题

马的遍历问题

学院《数据结构与算法》课程设计报告书课程设计题目马的遍历问题院系名称计算机科学与技术系专业(班级)姓名(学号)指导教师完成时间一、问题分析和任务定义:国际象棋中马采用“日”字走法,对棋盘上马所在的结点,一步内到达的结点最多有八个,即假设马所在点的坐标为(i,j),那么其它八个结点的坐标为(i+1,j+2),(i+2,j+1),(i+2,j-1),(i+1,j-2),(i-1,j-2),(i-2,j-1),(i-2,j+1),(i-1,j+2)把这些点看作马所在点的邻接点,所以可以采用类似图的深度优先遍历,以马所在点为初始点对整个棋盘进行遍历。

然后按遍历的顺序输出结点棋盘的规格限制为8*8,输入数据为起始点的位置(0-7)。

输出数据为可以遍历成功的若干方案(本程序设置为至多八种)。

因为对图形学完全不了解,所以我没有动态显示,而是采取直接输出结果的策略。

二、概要设计和数据结构的选择:1.解决马的遍历问题,可以用一个二维数组board[][]来表示棋盘,一开始用来存放步骤号,若走过了则把它赋值为1。

另对马的8种可能走法设定一个顺序,如当前位置在棋盘的(i,j)方格,下一个可能的位置依次为(i+2,j+1)、(i+1,j+2)、(i-1,j+2)、(i-2,j+1)、(i-2,j-1)、(i-1,j-2)、(i+1,j-2)、(i+2,j-1),实际可以走的位置尽限于还未走过的和不越出边界的那些位置。

为便于程序的同意处理,可以引入两个数组mover[]、movec[],分别存储各种可能走法对当前位置的纵横增量。

整形变量step存放步骤号,start存放遍历次数,在numable函数和number函数中的语句k=(i+start)%N;中是用于定位,保证不会超过棋盘范围和八次遍历都不会走同样的路径test存放遍历成功次数。

在8×8方格的棋盘上,从任意指定的方格出发,为马寻找一条走遍棋盘每一格并且只经过一次的一条路径。

马踏棋盘 数据结构实践报告

马踏棋盘 数据结构实践报告

马踏棋盘问题摘要:马踏棋盘就是在国际象棋8X8棋盘上面,按照国际象棋规则中马的行进规则,实现从任意初始位置,每个方格只进入一次,走遍棋盘上全部64个方格。

理解栈的“后进先出”的特性以及学会使用回溯。

关键字:马踏棋盘、递归、栈、回溯1.引言马踏棋盘就是在国际象棋8X8棋盘上面,按照国际象棋规则中马的行进规则,实现从任意初始位置,每个方格只进入一次,走遍棋盘上全部64个方格。

编制程序,求出马的行走路线,并按求出的行走路线,将数字1,2….64依次填入一个8X8的方阵,并输出它的行走路线。

输入:任意一个起始位置;输出:无重复踏遍棋盘的结果,以数字1-64表示行走路线。

2.需求分析(1)需要输出一个8X8的棋盘,可以采用二维数组的方法实现。

(2)输入马的起始位置,必须保证输入的数字在规定范围内,即0<=X<=7,0<=Y<=7。

(3)保证马能走遍整个棋盘,并且不重复。

(4)在棋盘上输出马的行走路线,标记好数字1、2、3直到64。

3.数据结构设计采用栈数组为存储结构。

#define maxsize 100struct{int i;int j;int director;}stack[maxsize];4.算法设计4.1 马的起始坐标void location(int x,int y) //马的位置坐标的初始化{top++;stack[top].i=x; //起始位置的横坐标进栈stack[top].j=y; //起始位置的竖坐标进栈stack[top].director=-1;a[x][y]=top+1; //标记棋盘Try(x,y); //探寻的马的行走路线}4.2 路径探寻函数void Try(int i,int j){ int count,find,min,director;int i1,j1,h,k,s;intb[8]={-2,-2,-1,1,2,2,1,-1},c[8]={1,-1,-2,-2,-1,1,2,2};//存储马各个出口相对当前位置行、列坐标的增量数组int b2[8],b1[8];for(h=0;h<=7;h++)//用数组b1[8]记录当前位置的下一个位置的可行路径的条数{ count=0;i=stack[top].i+c[h];j=stack[top].j+b[h];if(i>=0&&i<=7&&j>=0&&j<=7&&a[i][j]==0)//如果找到下一个位置{for(k=0;k<=7;k++){i1=i+c[k];j1=j+b[k];if(i1>=0&&i1<=7&&j1>=0&&j1<=7&&a[i1][j1]==0) //如果找到下一个位置count++; //记录条数}b1[h]=count; //将条数存入b1[8]中}}for(h=0;h<=7;h++)//根据可行路径条数的大小,从小到大排序,并放入数组b2[8]中{min=9;for(k=0;k<=7;k++)if(min>b1[k]){min=b1[k];b2[h]=k;s=k;}b1[s]=9;}find=0;director=stack[top].director;for(h=director+1;h<=7;h++)//向8个方向进行寻找{i=stack[top].i+c[b2[h]];j=stack[top].j+b[b2[h]];if(i>=0&&i<=7&&j>=0&&j<=7&&a[i][j]==0){stack[top].director=h; //存储栈的寻找方向top++; //进栈stack[top].i=i;stack[top].j=j;stack[top].director=-1;//重新初始化下一栈的方向a[i][j]=top+1;find=1; //找到下一位置break;}}if(find!=1){a[stack[top].i][stack[top].j]=0; //清除棋盘的标记top--; //退栈}if(top<63)Try(i,j); //递归}4.3输出函数void display(){int i,j;for(i=0;i<=7;i++){ for(j=0;j<=7;j++)printf("\t%d ",a[i][j]); //输出马的行走路线printf("\n\n");}printf("\n");}5.程序实现5.1 主函数void main(){int i,j,x,y;for(i=0;i<=7;i++) //棋盘的初始化for(j=0;j<=7;j++)a[i][j]=0;printf("输入X Y (0=<X<=7,0=<Y<=7)\n");scanf("%d%d",&x,&y);if(x>=0&&x<=7&&y>=0&&y<=7)//判断输入的起始位子是否正确{location(x,y);display();}else printf("错误\n");}5.2运行结果(1)当输入不符合要求时(2)正确输入时5.3 算法分析(1)马的起始坐标一开始先建立一个栈数组,里面包括横坐标和竖坐标还有方向。

马踏棋盘算法

马踏棋盘算法

马踏棋盘算法介绍1.马踏棋盘算法,也称骑⼠周游问题2.规则:将马随机放在国际象棋的 8×8 棋盘[0~7][0~7]的某个⽅格中,马按⾛棋规则(马⾛⽇字)进⾏移动,要求每个⽅格只进⼊⼀次,⾛遍棋盘上全部 64 个⽅格3.基本思想:图的深度优先搜索 + 贪⼼算法(优化)步骤1.创建⼀个⼆维数组代表棋盘2.将当前位置设置为已经访问,把当前马在棋盘的位置标记为第⼏步(step),然后根据当前位置,计算马还能⾛哪些位置,并放⼊ArrayList,最多有8个位置3.获取到ArrayList后,⽤贪⼼算法优化4.遍历ArrayList中存放的所有位置,判断哪个位置可以⾛通,如果⾛通,就继续,⾛不通,就回溯5.判断是否⾛完整个棋盘,使⽤step和应该⾛的步数⽐较,如果没有达到数量,则表⽰没有完成任务,并将整个棋盘置0贪⼼算法优化ArrayList1.基本思想:根据当前这个⼀步的所有的下⼀步的选择位置,进⾏⾮递减(即不严格递增)排序,减少回溯的次数步骤(1)传⼊Comparotor,重写ArrayList的sort⽅法(2)获取ArrayList所有位置的通路个数,按⾮递减排序(3)即当前位置的下⼀步的下⼀步通路最少,就优先选择代码实现import java.awt.*;import java.util.ArrayList;import java.util.Arrays;import parator;public class KnightTravel {//骑⼠周游问题public int row;//棋盘的⾏数public int column;//棋盘的列数public int[][] chessboard;//棋盘public boolean[][] visited;//标记棋盘的各个位置是否被访问过,true:已访问public boolean finished;//标记是否棋盘的所有位置都被访问,若为true,表⽰算法计算成功public int step = 1;//初始为第⼀步public static void main(String[] args) {KnightTravel knight = new KnightTravel(8, 8);long start = System.currentTimeMillis();knight.travel(knight.chessboard, 0, 0, knight.step);long end = System.currentTimeMillis();System.out.println("共耗时: " + (end - start) + " 毫秒");knight.result();}public KnightTravel(int row, int column) {this.row = row;this.column = column;this.chessboard = new int[row][column];this.visited = new boolean[row][column];}public void result() {//打印算法结果for (int[] row : chessboard) {System.out.println(Arrays.toString(row));}}//马踏棋盘算法//chessboard:棋盘,row:马⼉当前的位置的⾏,从0开始,column:马⼉当前的位置的列,从0开始,step:第⼏步,初始位置是第1步 public void travel(int[][] chessboard, int row, int column, int step) {chessboard[row][column] = step;visited[row][column] = true; //标记该位置已经访问//获取当前位置可以⾛的下⼀个位置的集合ArrayList<Point> access = next(new Point(column, row));sort(access);//对access进⾏⾮递减排序while (!access.isEmpty()) {Point next = access.remove(0);//取出下⼀个可以⾛的位置if (!visited[next.y][next.x]) {//判断该点是否已经访问过travel(chessboard, next.y, next.x, step + 1);}}if (step < this.row * this.column && !finished) {//⽆路可⾛且未⾛完,就回溯到上⼀位置chessboard[row][column] = 0;visited[row][column] = false;} else {//成功⾛完时,finished是防⽌回溯时将最优解覆盖掉finished = true;}}//根据当前位置(curPoint),计算马还能⾛哪些位置(point),并放⼊⼀个集合中(ArrayList), 最多有8个位置public ArrayList<Point> next(Point curPoint) {//储存马在当前位置的通路ArrayList<Point> access = new ArrayList<>();//Point对象中,属性x代表列,属性y代表⾏Point point = new Point();//以下操作,判断马的8个⽅向是否可⾏,并记录通路位置,但不记录该位置是否已访问if ((point.x = curPoint.x - 2) >= 0 && (point.y = curPoint.y - 1) >= 0) {access.add(new Point(point));}if ((point.x = curPoint.x - 1) >= 0 && (point.y = curPoint.y - 2) >= 0) {access.add(new Point(point));}if ((point.x = curPoint.x + 1) < column && (point.y = curPoint.y - 2) >= 0) {access.add(new Point(point));}if ((point.x = curPoint.x + 2) < column && (point.y = curPoint.y - 1) >= 0) {access.add(new Point(point));}if ((point.x = curPoint.x + 2) < column && (point.y = curPoint.y + 1) < row) {access.add(new Point(point));}if ((point.x = curPoint.x + 1) < column && (point.y = curPoint.y + 2) < row) {access.add(new Point(point));}if ((point.x = curPoint.x - 1) >= 0 && (point.y = curPoint.y + 2) < row) {access.add(new Point(point));}if ((point.x = curPoint.x - 2) >= 0 && (point.y = curPoint.y + 1) < row) {access.add(new Point(point));}return access;}//根据当前这个⼀步的所有的下⼀步的选择位置,进⾏⾮递减(不严格递增)排序, 减少回溯的次数public void sort(ArrayList<Point> access) {access.sort(new Comparator<Point>() {@Overridepublic int compare(Point o1, Point o2) {int count1 = next(o1).size();int count2 = next(o2).size();if (count1 < count2) {return -1;} else if (count1 == count2) {return 0;} else {return 1;}}});}}。

数据结构马踏棋盘

数据结构马踏棋盘

数据结构马踏棋盘第一点:马踏棋盘的起源与发展马踏棋盘,是一种源自中国传统的棋类游戏,具有悠久的历史和丰富的文化内涵。

它是在象棋的基础上演变而来的一种棋类运动,以马作为主要棋子,通过马的移动来占领对方的棋盘。

马踏棋盘不仅具有高度的策略性和技巧性,而且蕴含着深厚的哲学思想和人生哲理。

从历史角度看,马踏棋盘的起源可以追溯到中国古代的战国时期。

当时,诸侯割据,战争频繁,人们为了娱乐和消磨时间,便创造了这种棋类游戏。

随着时间的推移,马踏棋盘逐渐在全国各地流传开来,并逐渐形成了不同的地域流派和玩法。

从文化角度看,马踏棋盘不仅是一种游戏,更是一种艺术。

它的棋盘布局、棋子造型、规则设计等方面都蕴含着丰富的中国传统文化元素。

例如,棋盘的布局模仿了中国古代的宫殿建筑,棋子的造型则借鉴了古代兵器和宫廷用品。

同时,马踏棋盘的规则设计也体现了中国古代的哲学思想,如阴阳、五行等。

第二点:马踏棋盘的策略与技巧马踏棋盘作为一种策略性棋类游戏,其胜负往往取决于玩家的策略和技巧。

在游戏中,玩家需要充分运用自己的智慧和思维,通过巧妙的布局和战术,来实现占领对方棋盘的目的。

首先,玩家需要掌握马踏棋盘的基本规则和棋子的行走方式。

马踏棋盘的棋子行走方式与象棋有所不同,马的移动方式是“日”字形,即每次移动可以横向或纵向移动一格,然后横向或纵向移动一格,类似于马的奔腾。

玩家需要熟练掌握马的行走方式,才能在游戏中更好地发挥其作用。

其次,玩家需要学会运用不同的战术和策略。

在马踏棋盘游戏中,玩家可以通过设置陷阱、封锁对方棋子、保护自己的棋子等方式来达到胜利的目的。

例如,玩家可以利用棋盘上的障碍物来设置陷阱,让对方棋子无法移动或被迫移动到不利的位置。

同时,玩家还需要保护自己的棋子,避免被对方轻易攻破。

最后,玩家需要具备良好的思维和应变能力。

在马踏棋盘游戏中,局势变化无常,玩家需要能够迅速分析局势,制定出合理的策略和方案。

同时,玩家还需要具备较强的应变能力,能够灵活应对各种突发情况,从而取得胜利。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

安徽工程大学信息10 课程设计马踏棋盘的求解及演示设计摘要数据结构是计算机科学与技术专业的一门核心专业基础课程,是一门理论性强、思维抽象、难度较大的课程。

我认为学习数据结构的最终目的是为了获得求解问题的能力。

对于现实世界中的问题,我们应该能从中抽象出一个适当的数学模型,该数学模型在计算机内部用相应的数据结构来表示,然后设计一个解此数学模型的算法,再进行编程调试,最后获得问题的解答。

《数据结构》课程设计是计算机科学技术专业集中实践性环节之一,是学习完《数据结构》课程后进行的一次全面的综合练习。

开设本课程设计实践的主要目的就是要达到理论与实际应用相结合,提高学生的动手能力,完成计算机应用能力的培养;本课程设计主要解决马踏棋盘的问题,找出踏遍棋盘的多种路径,并实现动态要是过程。

马踏棋盘问题,实际上是图论中的哈密顿通路问题,是典型的NP问题,求解的问题与算法设计有很大关系,如果采取穷举搜索的话,很容易陷入海量搜索的状态,耗费巨大的时间,使问题几乎不可解,因此马在棋盘上遍历采用算法当中的深度优先算法和启发式贪心算法,用栈来存储遍历过程,通过对栈的使用实现对所有路径的搜索。

在调试过程发现,启发式贪心算法,针对于马踏棋盘问题有着极大的好处,就是无论从棋盘上哪个点开始,找到一条遍历完棋盘的通路是不需要回溯的,也就节省了大量的时间,而试探性的操作对于每个点都也只有168步,所以求出所有路径在不到一秒的时间内完成。

关键词:马踏棋盘;骑士周游;哈密顿通路;NP-完全问题;贪心算法;回溯法;目录马踏棋盘的求解及演示设计 (1)目录 (2)第一章引言 (3)第二章需求分析 (4)2.1问题描述 (4)2.2基本要求 (4)2.3具体需求 (4)2.4开发环境 (4)第三章概要设计 (5)3.1 系统概述 (5)3.2 系统描述 (6)3.3逻辑设计 (6)第四章详细设计 (7)4.1 功能模块设计 (7)4.2 数据结构设计 (7)4.3算法设计 (9)第五章调试与分析 (13)5.1 调试分析 (13)第六章系统试用说明 (14)6.1 系统试用说明 (14)第七章总结与体会 (14)参考文献 (15)第一章引言本课程设计主要研究马踏棋盘的问题,即骑士周游问题,是将马随机放在国际象棋的8×8棋盘的某个方格中,“马”按照走棋规则进行移动,要求每个方格只进入一次,走遍棋盘上全部64个方格。

许多知名的数学家,如德莫弗(De Moivre)、欧拉(Euler)与范德蒙德(Vandermonde)等人,在过去的200年中都研究过这个问题,今天从数据结构的角度,解决这一问题。

力求以最快的速度,即最高的效率来解决问题。

已知穷举法是几乎不可能完成的,而与解决迷宫问题的回溯法,也要占用大量的时间,这里采用贪心算法来解决这一问题,并找出多有的遍历路径。

第二章需求分析2.1 问题描述马随机放在国际象棋的8×8棋盘的某个方格中,“马”按照走棋规则进行移动,要求每个方格只进入一次,走遍棋盘上全部64个方格。

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

2.2基本要求设计合适的数据结构,编制递归以及非递归程序,求出马的行走路线,并按求出的马的行走路线,将路线1,2,…,64依次填入一个8×8的方阵,输出之,若有多种走法,则能将全部的输出。

必须要能够将踏遍棋盘的过程显示在计算机屏幕上。

要求:(1)描述设计所涉及的数据模型,设计高效的数据结构完成总体设计,搭好框架,确定人机对话的界面(要求界面上能动态体现出演示的过程),实现功能;(2)界面友好,函数功能要划分好(3)要有算法设计的流程图(4)程序要加必要的注释(5)要提供程序测试方案2.3具体需求1、首先要找到马踏棋盘棋盘的多条路径。

2、实现马踏棋盘的动态演示过程。

3、优化算法,提高算法效率,以递归与非递归的方式实现2.4开发环境开发环境:Windows 8辅助工具:Visual Studio 2012 ,MyEclipse 10.5运行环境:Windows XP/Vista/7/8第三章 概要设计3.1 系统概述3.113.12 主函数main()的执行流程求解多条路径子系统:自动演示路径子系统通过VS2012完成的寻找多条路径的子系统,通过java来实现马踏棋盘的动态演示子系统。

在寻找多条路径的子系统中,通过启发式贪心算法,将某点的下一步最少通往其它落脚点,将该点确定为最佳落点。

每次只走下一步通向其他点最少的点。

用栈记录探寻的过程,将走过的点标记为1,试探而没有走的点标记为0.最后通过寻找出栈标志为0的点来寻找其他路径。

在动态显示模块式通过java的线程机制是先的自动动画演示。

3.3逻辑设计抽象数据类型棋盘上某点的位置坐标结构体Postion把个方向试探的增量位置数组direct[8]棋盘某点通向其他点的可到达数的二位数组access[8][8]链栈用来记录可到达下一位置坐标的数组:nextPath[8];用来记录整个遍历过程的数组: tourpos[64];第四章详细设计4.1 功能模块设计4.1.2创建模块本模块创建棋盘,以及棋盘上每一点的可到达数,一个向8个方向试探的增量数组。

以及记录整个遍历流程的链栈。

选择或设计数据结构的存储结构,实现存储结构的基本运算、设计的模块构成、各模块的简要说明、流程图、调用关系表等。

在这个过程中,要综合考虑系统功能,使得系统结构清晰、合理、简单和易于调试,抽象数据类型的实现尽可能做到数据封装,基本操作的规格说明尽可能明确具体。

详细设计的结果是对数据结构和基本操作作出进一步的求精,写出数据存储结构的类型定义,写出函数形式的算法框架。

4.1.3操作模块实现对棋盘的周游,并找到多条路径4.1.4 显示模块将找到的所有路径显示在屏幕上,并统计找到的路径数。

4.1.5自动演示模块通过Java的Applet和线程机制,实现对找到的路径进行动态演示。

4.2 数据结构设计4.2.1数据设计定义棋盘上某点的位置坐标结构体Postiontypedef struct{int x;int y;}Postion;定义把个方向试探的增量位置数组Postion direct[8]={{1,2},{2,1},{2,-1},{1,-2},{-1,-2},{-2,-1},{-1,2},{-2,1}};定义棋盘某点通向其他点的可到达数的二位数组int access[8][8] = {{2,3,4,4,4,4,3,2},{3,4,6,6,6,6,4,3},{4,6,8,8,8,8,6,4},{4,6,8,8,8,8,6,4},{4,6,8,8,8,8,6,4},{4,6,8,8,8,8,6,4},{3,4,6,6,6,6,4,3},{2,3,4,4,4,4,3,2}};定义一个以某一棋盘上的点和标志的类型,作为栈的存储数据typedef struct{Postion p;int flag;} DataType;定义一个链栈:typedef struct node//定义结点结构{DataType data;struct node *next;}StackNode,*PStackNode;////////////////////////////////////////typedef struct//定义一个栈{PStackNode top;}LinkStack,*PLinkStack;用来记录可到达下一位置坐标的数组:Postion nextPath[8];用来记录整个遍历过程的数组: Postion tourpos[64];4.3算法设计寻找下一条路径: 流程图:略:算法描述:应考察每一方格的可到达性。

使用数组accessibility []表示可达到数,并当马踏棋盘时,程序动态修正剩余格子的可达到数。

accessibility [ arrayPos ] = 0 表明格子已经被占据。

算法:void next_Path(Postion P ) { Postion testPos;for (int i = 0 ; i < 8 ; i++ ) {//有八种到达的情况 testPos.x = P .x + direct[ i ].x;//得出X,Y 坐标的测试位置testPos.y = P .y + direct[ i ].y;if (checkPath(testPos)) {//判断测试位置是否在棋盘内nextPath[arrayPos]=testPos ;//由测试位置给出正确X,Y 坐标accessibility [ arrayPos ] = access [testPos.x][testPos.y]; //利用对应的X,Y 坐标得出相应的可到达的路径总数if (accessibility [ arrayPos ] > 0 ) // accessibility [ arrayPos ] = 0表明格子已经被占据arrayPos ++ ; }//寻找空格子结束}// 结束for 循环,寻找结束countAccessibility = arrayPos ;//统计可达到数 if (countAccessibility > 0 ) {sortAll(); }arrayPos = -1 ;}//////////////////////////////////////////////////////////////// 2.使用冒泡法来查询最小数。

voidsortAll (){ //冒泡排序法.冒泡排序的基本概念是:依次比较相邻的两个数,将大数放在前面,小数放在后面。

//保持稳定性int temp;Postion temps;for ( int i = 0 ; i < countAccessibility - 1 ; i ++ ){for ( int j = i + 1; j < countAccessibility ; j ++ ){if ( accessibility [ i ] > accessibility [ j ] ){temps=nextPath[i];nextPath[i]=nextPath[j];nextPath[j]=temps;temp = accessibility [ i ];accessibility [ i ] = accessibility [ j ];accessibility [ j ] = temp;}//end of if}// end of inner for}// end of outer for}// end of sortAll3.//////////////////////////////////////////////3、向下一步移动,将当前要走的结点入栈,标记为1,其他可到达但没有走的点入栈,标记为0 如果当前坐标走过,那么它可以到达的其它点的可到达数应该-1最后将该点的可到达数更新为0void domoving(Postion P){for ( int i = 0 ; i < countAccessibility ; i ++ ){DataType q;q.p=nextPath[i];if(i==0){q.flag=1;} else{q.flag=0;}Push_LinkStack(S,q);access[ nextPath[i].x ][ nextPath[i].y ] -- ;}//直到没有路径了access[ P.x ][ P.y] = 0 ;//当前位置置0}4、打印路径:打印8×8棋盘,在棋盘中显示马跳的步骤:void fprint(){ //输出路径int order[8][8]={0}; //-----初始化for(int k=0;k<64;k++){order[tourpos[k].x][tourpos[k].y]=k;}cout<<"\n 棋盘表示\n";cout<<" 0 1 2 3 4 5 6 7\n" ;cout<<" +----+----+----+----+----+----+----+----+\n";for(int i=0;i<8;i++){printf(" ");printf("%2d",i);for(int j=0;j<8;j++){printf("| %2d ",order[i][j]);}printf("|");printf("\n");if(i==7)printf(" +----+----+----+----+----+----+----+----+");elseprintf(" +----+----+----+----+----+----+----+----+");printf("\n");}printf(" ");}5、寻找其他路径:算法描述:将栈中存储的路径出栈,判断标记是否为0,并累计标记为1的个数count_next,即走过的步数,方便撤销走过的步骤,根据count_next来撤销走过的步骤,先将在access[][]撤销,即还原为1,将当前为flag为0的复制到下一步的tourpos[]数组中,之后将tourpos[]后面的步骤还原为0,再结束后,在寻找下一条路径,若找不到,则继续出栈,向前回溯。

相关文档
最新文档