马踏棋盘数据结构与算法课程设计.docx
《马踏棋盘数据结构与算法课程设计.docx》由会员分享,可在线阅读,更多相关《马踏棋盘数据结构与算法课程设计.docx(21页珍藏版)》请在冰豆网上搜索。
马踏棋盘数据结构与算法课程设计
《数据结构与算法设计》
课程设计任务书
题目
马踏棋盘问题研究
学生姓名
学号
专业班级
数学0901
设
计
内
容
与
要
求
【问题描述】
将马随机地放在国际象棋的8*8棋盘某个方格中,然后令马按走棋规则开始进行移动。
马将棋盘上的每个方格进入且只进入一次,走遍全部64个方格。
【软件功能】
1.用户可以输入一个起始位置。
2.有一个正确的起始位置后,用户可以得到一个棋盘,棋盘上的每个位置都将标有1-64中的某一个数字。
3.再输入一个起始位置后,将会得到一个新的棋盘。
4.利用GUI实现简单的图形用户界面
【算法思想】
1.由键盘输入起始的x坐标和y坐标
2.判断坐标位置是否合法,如果不合法,则提示用户重新输入,如果合法,则将坐标保存在马类中,并且将步数记录为第1步,将棋盘类入栈保存。
接着调用探寻下一步路径的函数。
3.马将向可以走的方向进行尝试,如果尝试的这个位置可以行走,即马还没有走过,则记录下此位置以及是第几步所走的位置,并入栈保存。
4.再次调用探寻路径的函数,并且做步骤3中的做法。
5.直到马将棋盘上的64个方格都走完,则停止调用探寻路径的函数。
此时,开始输出马所走的位置。
即开始出栈。
6.栈遵循后进先出的原则,故出栈时,首先输出的是马走的最后一个位置,此时,在棋盘上对应的位置输入所记录的步数。
依次循环出栈,当栈为空时,即输出完毕,得到一章带有马所走过的位置的棋盘。
程序结束。
【提交成果】
1.“《数据结构与算法设计》课程设计任务书”一份,打印装袋;
2.“《数据结构与算法设计》课程设计报告”一份,打印装袋;
3、上面两项内容的word文档,通过电子邮件交到指导教师。
起止时间
2012年6月18日至2012年7月1日
指导教师签名
2012年6月18日
系(教研室)主任签名
2012年6月18日
学生签名
年月日
注明:
内容限1页
数据结构与算法设计课程设计
专业数学与应用数学班级数学0901学号姓名完成日期指导教师
1、程序设计说明书
【设计题目】马踏棋盘问题研究
【问题描述】
将马随机地放在国际象棋的8*8棋盘某个方格中,然后令马按走棋规则开始进行移动。
马将棋盘上的每个方格进入且只进入一次,走遍全部64个方格。
【软件功能】
1.用户可以输入一个起始位置。
2.有一个正确的起始位置后,用户可以得到一个棋盘,棋盘上的每个位置都将标有1-64中的某一个数字。
3.再输入一个起始位置后,将会得到一个新的棋盘。
4.利用GUI实现简单的图形用户界面
【算法思想】
1.由键盘输入起始的x坐标和y坐标
2.判断坐标位置是否合法,如果不合法,则提示用户重新输入,如果合法,则将坐标保存在马类中,并且将步数记录为第1步,将棋盘类入栈保存。
接着调用探寻下一步路径的函数。
3.马将向可以走的方向进行尝试,如果尝试的这个位置可以行走,即马还没有走过,则记录下此位置以及是第几步所走的位置,并入栈保存。
4.再次调用探寻路径的函数,并且做步骤3中的做法。
5.直到马将棋盘上的64个方格都走完,则停止调用探寻路径的函数。
此时,开始输出马所走的位置。
即开始出栈。
6.栈遵循后进先出的原则,故出栈时,首先输出的是马走的最后一个位置,此时,在棋盘上对应的位置输入所记录的步数。
依次循环出栈,当栈为空时,即输出完毕,得到一章带有马所走过的位置的棋盘。
程序结束。
【逻辑结构设计】
由用户输入起始位置,如果,输入合法,即输入的起始位置在棋盘中,则此位置即为马开始行走的起点,以此点为起点,以象棋中马的走法开始在棋盘中,找寻可以行走的位置,每个位置只能走一次,直到马将棋盘中的64个位置全都走过之后,在棋盘上显示出马行走的轨迹;当用户在此输入一个合法的起始位置时,则可以得到一个新的棋盘。
【存储结构设计】
马的抽象数据类型:
publicclassHorse{
publicintstep;//马行走的步数
publicintx=0;//马在棋盘上的横坐标
publicinty=0;//马仔棋盘上的纵坐标
publicHorse(){}//无参构造
publicintgetStep();//获取步数
publicvoidsetStep(intstep);//设置步数
publicintgetX();//获取x坐标
publicvoidsetX(intx);//设置x坐标
publicintgetY();//获取y坐标
publicvoidsetY(inty);//设置y坐标
}
栈的抽象数据类型:
publicclassStack{
inttop;//栈顶指针
Horseelements[];//栈元素数组
intStackSize;//栈最大容量
publicStack();/构造函数1
publicStack(intStackSize);//构造函数2
publicbooleanIsEmpty();//栈空否
publicbooleanIsFull();//栈满否
publicvoidPush(Horseitem);//进栈
publicHorsePop();//出栈
publicHorseGetTop();//取栈顶
publicvoidMakeEmpty();//置空栈
}
【基本操作设计】
此程序功能简单,由于只需要用户输入一个起始位置的坐标即可,故设计了两个输入框用来输入起始位置的x坐标和y坐标,然后设计了一个按钮,用来开始计算马的行走轨迹及显示。
【模块流程图】
【界面设计】
(1).主界面
(2)用户输入错误时的错误提示界面
【用户手册】
(1)输入正确的起始位置坐标.x和y
(2)坐标的建立方向为:
x坐标:
从上到下,从1开始到8结束,即x代表第x行
y坐标:
从左到右,从1开始到8结束,即y代表第y列
2、程序上机调试报告
【语法错误及其排除】
(1)空指针异常。
在测试代码时经常遇见这个错误,原因是,变量没有被正确调用。
调试这个错误时很麻烦的,需要一点一点去检查出现错误的语句以及相关的语句。
经过仔细检查,果然是我在调用变量时出现的错误,一点点修改后,程序终于跑通了。
(2)数组下标越界异常。
在使用数组时,定义好了数组的长度,数组的下标也就给定了,就是0-(长度-1),但我的使用时,将数组中的最后一项的下标直接给成了数组的长度,出现了错误。
修改后经测试,程序运行良好。
【算法错误及其排除】
(1)标记好马儿尝试的方向后,编译运行,但是运行结果却不符合程序所要求的结果,说明在算法上肯定有错误,检查发现,马儿走的坐标没有控制后,马儿就会踏出棋盘以外,这样输出的结果就不对。
调整后,输入结果正确。
(2)棋盘走过的位置没有被标记,使得在计算时出现了重复的位置。
在走过的位置被标记之后,标记的位置马儿就不会再去走,这样就不会出现重复的位置。
【测试数据】
测试数据1:
起始坐标(3,4)
测试数据2:
起始坐标(9,9)
【输出结果】
对于测试数据1:
对于测试数据2:
【程序性能评价】
此程序的功能有些简单,但关键在于对于马儿行走的路径的计算上,在计算时对内存的使用有些大。
故此程序注重的是算法的设计与计算。
【性能改进方向】
此程序还有可以改进的地方,由问题可知,此棋盘的格子数是给定的,即指定了一个8*8的棋盘。
改进的地方就在于,我们还可以设计为棋盘的格子数由用户输入,即由用户自己来确定棋盘的大小。
【收获及体会】
通过本次程序的编写,能够掌握栈的性质以及它的应用。
这次实验花了很多时间才完成,其实本应该早完成的,在检查的过程中有多多少少修改完美了一下,不过算法思想却没有改变。
课程设计是把我们所学的理论知识进行系统的总结并应用于实践的良好机会,有利于加强我们用知识理论来分析实际问题的能力,进而加强了我们对知识认识的实践度,巩固了我们的理论知识,深化了对知识的认识,并为走向社会打下一个良好的基础。
3、源程序代码
(1)马类
publicclassHorse{
publicintstep;//马行走的步数
publicintx=0;//马在棋盘上的横坐标
publicinty=0;//马仔棋盘上的纵坐标
publicintgetStep(){
returnstep;
}
publicvoidsetStep(intstep){
this.step=step;
}
publicintgetX(){
returnx;
}
publicvoidsetX(intx){
this.x=x;
}
publicintgetY(){
returny;
}
publicvoidsetY(inty){
this.y=y;
}
}
(2)顺序存储栈
//顺序存储栈
importjava.io.*;
//***“顺序栈”类的定义***//
publicclassStack{
inttop;//栈顶指针
Horseelements[];//栈元素数组
intStackSize;//栈最大容量
//构造函数1
publicStack(){
StackSize=10;//缺省大小
elements=newHorse[StackSize];//数组
top=-1;//空栈标志
}
//构造函数2
publicStack(intStackSize){
this.StackSize=StackSize;
elements=newHorse[StackSize];//数组
top=-1;//空栈标志
}
//栈空否
publicbooleanIsEmpty(){
returntop==-1;
}
//栈满否
publicbooleanIsFull(){
returntop==StackSize-1;
}
//进栈
publicvoidPush(Horseitem){
if(IsFull())return;//栈满
//栈顶指针首先上抬,在栈顶位置存入新元素
elements[++top]=item;
}
//出栈
publicHorsePop(){
//栈空,出栈失败
if(IsEmpty())returnnull;
//送出栈顶元素,栈顶指针下移
returnelements[top--];
}
//取栈顶
publicHorseGetTop(){
//栈空
if(IsEmpty())returnnull;
//送出栈顶元素,栈顶指针不动
returnelements[top];
}
//置空栈
publicvoidMakeEmpty(){
top=-1;
}
}
(3)计算棋盘中个点可走路径的类
publicclassJiSuan{//计算棋盘中各点可走路径
publicvoidinit(int[][]way){
inti,j,k,x,y;
intpath[][]={{0,0,0},{1,1,2},{2,1,-2},
{3,-1,2},{4,-1,-2},{5,2,1},
{6,2,-1},{7,-2,1},{8,-2,-1}};
//存放马的行走规则,为了使坐标和棋盘一一对应定义8¡Á3数组
for(i=1;i<=8;i++)
//先初始各点可走路径为零
for(j=1;j<=8;j++)
way[i][j]=0;
for(i=1;i<=8;i++)
//计算各点可走路径,如果合法便存储
for(j=1;j<=8;j++)
for(k=1;k<=8;k++){
x=i;
y=j;
x=x+path[k][1];
y=y+path[k][2];//x,y代表走下一步后的坐标,通过k的增长,改变行走的方向
if(x>=1&&x<=8&&y>=1&&y<=8)//判断是否落在棋盘内,否则不存储
way[i][j]++;
}
}//init
}//jisuan
(4)计算马儿行走路径的类
publicclassShuChu{
Stackstack=newStack(64);
publicStackcalcu(int[][]way,inta,intb){
intz,x,y,m,n,k,min;
inti=0;
intj=0;
intpath[][]={{0,0,0},{1,1,2},{2,1,-2},{3,-1,2},
{4,-1,-2},{5,2,1},{6,2,-1},{7,-2,1},
{8,-2,-1}};//存放马的行走规则,为了使坐标和棋盘一一对应定义8¡Á3数组
m=a;
n=b;
if(m>=1&&m<=8&&n>=1&&n<=8)//判断输入位置是否合法
{
for(z=1;z<=64;z++)//分64次写入
{
Horsehorse=newHorse();
min=8;//初始可选路径最小值为8
way[m][n]=0;//走过的点可选路径设为0,没走过设为可选路径数
for(k=1;k<=8;k++)//走最小可选路径数的点
{
x=m+path[k][1];
y=n+path[k][2];//x,y代表走下一步后的坐标,通过k的增长,改变行走的方向
if(x>=1&&x<=8&&y>=1&&y<=8)
if(way[x][y]!
=0)//没走过的点
{
--way[x][y];//可选路径数减1,因为本点刚走过
if(way[x][y]{
min=way[x][y];//使a[x][y]存放最小可选路径数的点
i=x;
j=y;
}
}
}//for
horse.setX(m);//将x坐标存入马类中
horse.setY(n);//将y坐标存入马类中
horse.setStep(z);//将步数存入马类中
stack.Push(horse);//入栈
m=i;
n=j;//下一个点的坐标
}//for“64次”
returnstack;
}//判断合法
else
System.out.println("错误:
坐标超出棋盘边界!
");
returnnull;
}//calu
}//shuchu
(5)GUI图形用户界面类
packageyanghao;
importjava.awt.*;
importjava.awt.event.ActionEvent;
importjava.awt.event.ActionListener;
importjavax.swing.*;
publicclassJframeextendsJFrameimplementsActionListener{
int[][]seed=newint[9][9];//存储从栈中接收的步数的二维数组
JButtonjb;//定义的按钮
JLabeljl1,jl2;//定义的标签
JTextFieldjtf1,jtf2;//定义的输入框
publicJframe(){//窗体构造函数
setLayout(newBorderLayout());
JPaneljp=newJPanel();
jb=newJButton("确定");
jb.addActionListener(this);
jl1=newJLabel("x:
");
jl2=newJLabel("y:
");
jtf1=newJTextField(5);
jtf2=newJTextField(5);
jp.add(jl1);
jp.add(jtf1);
jp.add(jl2);
jp.add(jtf2);
jp.add(jb);
add(jp,BorderLayout.NORTH);
this.setTitle("马踏棋盘");//设置标题
this.setSize(600,600);//设置界面的大小
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
publicvoidpaint(Graphicsg){//创建Graphics画图
super.paint(g);
g.setColor(Color.black);
g.drawRect(100,100,400,400);//画棋盘边界
for(inti=1;i<=4;i++)
for(intj=1;j<=4;j++)
g.fillRect(100*j+50,100*i,50,50);//画棋盘黑格1
for(inti=1;i<=4;i++)
for(intj=1;j<=4;j++)
g.fillRect(100*j,100*i+50,50,50);//画棋盘黑格2
g.setColor(Color.blue);
Fontnum=newFont("楷体",Font.BOLD,25);
g.setFont(num);//设置字体
for(inti=1;i<=8;i++){
for(intj=1;j<=8;j++){
if(seed[i][j]!
=0)
g.drawString(seed[i][j]+"",50*j+65,50*i+85);
}
}
}//打印棋盘格中数字
//按钮的监听类
publicvoidactionPerformed(ActionEvente){
Stringcomm=e.getActionCommand();
if("确定".equals(comm)){
Stringreg="^\\d{1}$";//正则表达式
Stringstrx=jtf1.getText();//接收输入框1输入的字符串
Stringstry=jtf2.getText();//接收输入框2输入的字符串
if(!
strx.matches(reg)||!
stry.matches(reg)||strx==""||stry==""){//输入的字符串是否为一位数字
//提示输入错误
Object[]options={"确定","取消"};
JOptionPane.showOptionDialog(null,"请输入正确的x和y值(1-8的范围内)","输入错误",
JOptionPane.DEFAULT_OPTION,
JOptionPane.WARNING_MESSAGE,null,options,options[0]);
}else{
//输入的字串为一位数字
intx=Integer.parseInt(strx);//将字符串转成int类型
inty=Integer.parseInt(stry);//将字符串转成int类型
if(x>0&&y<9&&y>0&&y<9){//输入的数字满足要求与否
start(x,y);//开始计算
this.repaint();//重绘界面
}else{
//提示输入错误
Object[]options={"确定","取消"};
JOptionPane.showOptionDialog(null,"请输入正确的x和y值(1-8的范围内)",
"输入错误",JOptionPane.DEFAULT_OPTION,
JOptionPane.WARNING_MESSAGE,null,options,
options[0]);
}
}
}
}
privatevoidstart(intx,inty){
int[][]way=newint[9][9];//初始化可算路径数数组
JiSuanad=newJiSuan();
ad.init(way);//运行计算类
ShuChuaw=newShuChu();
Stackstack1=aw.calcu(way,x,y);//运行输出类
while(!
stack1.Is