骑士游历JAVA程序设计课程设计报告.docx
《骑士游历JAVA程序设计课程设计报告.docx》由会员分享,可在线阅读,更多相关《骑士游历JAVA程序设计课程设计报告.docx(20页珍藏版)》请在冰豆网上搜索。
![骑士游历JAVA程序设计课程设计报告.docx](https://file1.bdocx.com/fileroot1/2023-1/30/e9dfa1a4-bb0a-4bde-9560-8d270621d86f/e9dfa1a4-bb0a-4bde-9560-8d270621d86f1.gif)
骑士游历JAVA程序设计课程设计报告
一设计课题名称
骑士游历程序的开发
二 设计目的与意义
Java是目前最流行的软件开发语言之一,有SunMicrosystem公司推出,成为网络上的“世界语”。
Java适合开发基于多媒体、与平台无关、面向对象的方法进行的基于Internet、Intranet、Extranet的Applet和应用程序。
Java课程设计是计算机科学与技术专业学生必做的集中实践性环节之一,是学习完《Java程序设计》课程后进行的一次全面的综合练习。
其目的在于通过课程设计,使学生能够得到较系统的技能训练,从而巩固和加深对Java编程的基础理论知识的理解,培养学生综合运用所学理论解决实际问题的能力,使学生成为具有扎实的计算机理论基础和较强的独立动手能力的复合型、应用型人才。
三系统描述
骑士游历问题是一个古老而著名的问题,它最初是由大数学家Euler提出的.
问题是这样的:
国际象棋中的棋子(叫作骑士)在一个空棋盘内移动,问它能否经过64格中的每一格且只经过一次?
(骑士按L行移动,即在某方向前进两格接着在与原方向垂直的方向上前进一格)
本程序实现了骑士游历问题的求解,并能够演示起始位置在棋盘上任何位置的游历问题的实现.程序采用动态的图形演示,使算法的描述更形象,更生动,使教学能产生良好的效果.
本程序采用Applet来编制整个程序,这样既可以使大家对算法的实现有了一定的了解,也可以熟悉一下Java图形界面,Applet以及Java语言的命名规范.作为本书的第一例子,希望能让大家熟悉Java的基本语言结构和强大的开发能力.
在骑士游历的课程设计中,我们严格按照面向对象的思想进行开发,其中有AccessibleSquare类,MyPanel类和KnightsTour类.读者应注意各个类之间的关系,以便更深入地理解Java中类的思想.
四运行环境
本程序是在windowsxp,JBuild9的环境下运行的.
五系统的分析与设计
此次骑士游历问题,在JBuild9集成开发环境下完成编写调试等工作.
JBuilder是Borland公司开发的针对java的开发工具,使用JBuilder将可以快速,有效的开发各类java应用,它使用的JDK与sun公司标准的JDK不同,它经过了较多的修改,以便开发人员能够像开发Delphi应用那样开发java应用。
JBuilder的核心有一部分采用了VCL技术,使得程序的条理非常清晰,就算是初学者,也能完整的看完整个代码。
JBuilder另一个特点是简化了团队合作,它采用的互联网工作室技术使不同地区,甚至不同国家的人联合开发一个项目成为了可能。
Jbuilder9是功能强大的可视化Java集成开发工具,可以快速开发包括复杂企业级应用系统的各种Java程序,包括独立运行程序、Applet程序、Servlet、JSP、EJB、WebService等,最新的Jbuilder9版本支持Sun的J2SE1.4和J2EE1.4。
使用可视化工具开发程序有很多好处,其中最显著的是能够快速生成程序框架、设计图形界面、调试程序等,此外Jbuilder9内置了对一些企业级服务器的支持,包括Borland服务器、Bea公司的WebLogic服务器、IBM的WebSphere服务器和iPlanet服务器。
Jbuilder9在以前版本的基础上,增强和增加了许多功能。
JBuilder9的代码预览功能(CodeInsight)可以在编辑器中显示一个与上下文相关的弹出窗口。
它可以帮助用户快速、准确地编写Java代码。
例如,单击一个对象,马上在相应位置出现其所有的属性和方法等内容,用户可以快速地选择所需要的内容。
代码预览功能可帮助用户显示与上下文相关的数据成员与方法列表(MemberInsight)、当前代码中要使用的方法的参数列表(ParameterInsight)、可以通过当前类路径访问的类列表(ClassInsight)、结构窗口中的错误(ErrorInsight)以及在调试时显示变量值及表达式的值。
5.1创建骑士游历程序
在对Jbuilder9的基本常识有了初步的了解后,就可以起步创建骑士游历程序了。
创建过程如下:
(1)单击桌面图标,启动Jbuilder9开发平台进入一个新的工程界面。
(2)命名新的工程并保存文件,方法是单击菜单FileNewProject,出现一个对话框窗口,将工程名为Knighttour,选择保存工程文件目录之后,单击Finish按钮完成骑士游历工程的创建。
5.2程序的基本组成
下面着重介绍一下骑士游历程序的界面、程序结构以及程序效果显示图。
程序运行的界面上主要包括6个按钮:
(1)Info:
帮助信息。
(2)Start:
开始游历。
(3)Stop:
停止游历。
(4)Exit:
退出游历。
(5)NextTour:
重新开始一个新的游历。
(6)NextMoving:
骑士要走的下一步
5.3程序结构说明
整个程序界面由三部分组成,上方是由Info、Start、Stop和Exit四个按钮的工具栏,可以执行相应的操作;中间是骑士游历效果显示图,动态演示骑士游历的过程;最下边一排是NextTour和NextMoving两个按钮,单击NextTour按钮,可重新开始一个新的游历,单击NextMoving按钮,可显示骑士要走的下一步。
如图5-1所示。
(这是骑士在第一个格子起始位置进行游历的情况,如果想在其他位置开始游历,直接单击NextTour按钮就可以了,程序实现的骑士骑士位置的方式是按照顺序从第一列第一个开始、直到组后一列、最后一行)。
另外,可以由边框颜色的不同,判断骑士初始的位置、上一步所走的位置和现在所处的位置。
单击NextMoving按钮可以显示骑士游历的下一步。
连续单击直到64个格子全部走完,可以清晰地显示整个游历的过程。
图5-2显示的是骑士起始位置在第一个格子的游历的一个中间状态。
当然,骑士可以在棋盘的任何位置开始,操作者可以自己运行程序,以获得更深的认识。
图5-1骑士在第一个格子的请况图5-2骑士在第一个格子游历的中间状态
本程序由三个类组成一个工程文件.其中KnightsTour是主类,或者说是控制类,AccessibleSquare类主要是算法实现,MyPanel实现图形化显示结果.
程序的运行关系如图5-3.
图5-3程序运行关系图
5.4AccessibleSquare算法实现
AccessibleSquare类主要是算法实现,采用启发式算法.
先把八个可能走的方向用两个数组(horizontal[]和vertical[])表示出来,选择走哪个方向就在原坐标上进行相应的加法,表示骑士到了一个新的位置.horizontal[]和vertical[]表示骑士8个方向走L形状所需的X坐标和Y坐标的变化量:
horizontal[]={2,1,-1,-2,-2,-1,1,2},vertical[]={-1,-2,-2,-1,1,2,2,1}.坐标图如下:
6
5
4
3
2
1
8
7
图5-4骑士游历走向坐标图
(1)由于程序采用启发式算法,应考察每一方格的可到达性.使用数组accessibility[]表示可达到数,并当骑士游历时,程序动态修正剩余格子的可达到数.accessibility[arrayPos]=0表明格子已经被占据.
(2)使用冒泡法来查询最小数.冒泡排序的基本概念是:
依次比较相邻的两个数,将大数放在前面,小数放在后面。
即首先比较第1个和第2个数,将大数放前,小数放后。
然后比较第2个数和第3个数,将大数放前,小数放后,如此继续,直至比较最后两个数,将大数放前,小数放后,此时第一趟结束,在最后的数必是所有数中的最小数。
重复以上过程,仍从第一对数开始比较(因为可能由于第2个数和第3个数的交换,使得第1个数不再大于第2个数),将大数放前,小数放后,一直比较到最小数前的一对相邻数,将大数放前,小数放后,第二趟结束,在倒数第二个数中得到一个新的最小数。
如此下去,直至最终完成排序。
由于在排序过程中总是大数往前放,小数往后放,相当于气泡往上升,所以称作冒泡排序。
5.5图形化界面
由于目前用户对界面的要求逐步提高,因此,现在的可视化编程已经取代了传统的用户界面的设计方法。
而在可视化编程中,人机之间的直接联系主要是通过一些窗口和对话框来实现。
JBuilder9也不例外,它也是通过这些窗口和对话框来实现窗体。
用户需要的控件则可以直接放置在窗体上,利用这些控件来实现复杂的功能。
用户界面设计器是用户在编写程序过程中最常用到的工具。
用户在进行界面设计时,只需单击文件视图标签中的Design页,就会出现该用户界面设计器。
用户可以利用JBuilder提供的各种控件来搭建自己的程序界面。
而且同时,JBuilder9还为这些界面自动生成了相应的代码,为用户提供了程序的环境。
接下来,就要由用户设置属性,来编写一些实现用户特定功能的代码。
这在很大程度上减少了用户界面设计的复杂度,使用户的主要精力投入到如何实现和加强功能上来。
本程序是Applet的图形界面以及如何利用图形用户界面的控件接受用户信息,并用图形或图像显示结果.
(1)MyPanel函数实现图形化显示结果,MyPanel类就是画图类.首先用两种不同颜色的方块(WHITE和BIACK)显示出棋盘,还有其他两种方块(WKNIGHT和BKNIGHT),这两种方块上都有骑士,但颜色不一样.在骑士游历过程中不断用后来两种有骑士的方块代替前两种方块,其中需要注意的是保持棋盘的颜色一致性.如5-3图所示.将其设置为静态变量,方便使用,防止修改时出错.
5-5骑士游历游戏中的棋盘用图
(2)其次就是要显示骑士起始位置,刚走过的步的位置和现在的位置,用边框的不同来加以区别,采用函数g.setColor(Color.green)(刚走过的步显示为绿色)和g.setColor(Color.biue)(当步显示为蓝色)实现.这个类的对象在主类KnightsTour中被实例化.
5.6主调用程序的设计和开发
KnightsTour类是控制类,它完成对算法类和画图类的调用.由于JAVA的GUI编程是事件驱动的,因此在KnightsTour类中,通过监听前面介绍的几个Button的事件相应,完成程序的调用过程.
采用二维数组表示初始位置位于某个位置的可达到数,即以棋盘任意一点为初试位置,骑士游历完整个棋盘的路径数.利用access[][]数组来表示这个二维数组.
{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}};
本程序中在KnightsTour类中添加了两个按钮
JButtonnextMoving=newJButton("下一步");
JButtonnextTour=newJButton("新起点重新开始");
用于用户对游戏进行操作,这两个按钮分别有事件响应.
5.7程序的源程序
packagegao;
importjava.awt.*;
importjava.awt.event.*;
importjavax.swing.*;
importjava.awt.image.*;
publicclassKnightsTourextendsJApplet{
//初始位置位于某个位置的可达到数采用二维数组表示
//即以棋盘任意一点为初试位置,骑士游历完整个棋盘的路径数
publicstaticintaccess[][]={
{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}};
publicstaticintaccessbak[][]=arrayCopy(access);
intcountMoving=-1;
inttourXpos[]=newint[64];//游历中,X,Y都有64个位置
inttourYpos[]=newint[64];
privateintrecordXpos[][];privateintrecordYpos[][];
privateintrecordCount=-1;
privateintstartx;privateintstarty;
privatebooleansuccess=false;
MyPanelmyPanel;//声明MyPanel的一个对象
publicvoidtour(intxpos,intypos){//成员函数
//intx,y;
countMoving++;
//如果64个格子都被走过,则返回
if(countMoving==63)
{tourXpos[countMoving]=xpos;
tourYpos[countMoving]=ypos;
success=true;
countMoving--;
return;
}
AccessibleSquaresnextSquare=newAccessibleSquares(xpos,ypos);
//初试化AccessibleSquares对象,给nextSquare分配内存
while(nextSquare.hasMoreAccessible())
//利用AccessibleSquares()对象调用hasMoreAccessible()成员函数
{//开始移动
nextSquare.domoving();//调用nextSquare.domoving()函数
//把这一步记录下来
tourXpos[countMoving]=xpos;
tourYpos[countMoving]=ypos;
//尝试下一步的移动
nextSquare.nextAccessible();
tour(nextSquare.getXpos(),nextSquare.getYpos());
//如果64个格子都被走过,则返回
if(success)
{countMoving--;
return;}
//如果失败,则从起始位置从新开始
nextSquare.undomoving();
}
countMoving--;
}//游历方法结束
//定义棋盘行和列
//先定义一行棋盘
publicstaticint[]arrayCopy(intarray1[])//定义一个整形数组arrayCopy
{int[]array2=newint[array1.length];
for(introw=0;row{array2[row]=array1[row];};
returnarray2;
}
//复制数组,即定义出棋盘列
publicstaticint[][]arrayCopy(intarray1[][])
{int[][]array2=newint[array1.length][array1[0].length];
for(introw=0;row{for(intcolumn=0;column{array2[row][column]=array1[row][column];};
};
returnarray2;
}
//棋盘数组函数初始化
publicvoidinitialArray(intchessBoard[][])
{for(introw=0;row<8;row++)
{for(intcolumn=0;column<8;column++)
{chessBoard[row][column]=0;};
};
}
publicstaticvoidmain(Stringargs[]){
KnightsTourapplication=newKnightsTour();
application.tour(0,0);
}
publicvoidinit(){
recordCount=-1;
recordXpos=newint[64][64];recordYpos=newint[64][64];
for(introw=0;row<8;row++){
for(intcolumn=0;column<8;column++){
success=false;
countMoving=-1;
startx=row;starty=column;
access=arrayCopy(accessbak);
tour(row,column);
recordCount++;
recordXpos[recordCount]=arrayCopy(tourXpos);
recordYpos[recordCount]=arrayCopy(tourYpos);
}
}
recordCount=0;
myPanel=newMyPanel(recordXpos[0],recordYpos[0]);
JPanelbuttonPanel=newJPanel();
JButtonnextMoving=newJButton("下一步");
JButtonnextTour=newJButton("新起点重新开始");
buttonPanel.add(nextTour);
buttonPanel.add(nextMoving);
getContentPane().add(buttonPanel,BorderLayout.SOUTH);
getContentPane().add(myPanel);
nextMoving.addActionListener(
//匿名内部类,定义了actionPerformed函数,调用showNext函数响应NextMovingButton事件
newActionListener(){
publicvoidactionPerformed(ActionEvente){
myPanel.showNext();}
}
);//endcalltoaddActionListener
nextTour.addActionListener(
//内部类定义了actionPerformed函数,响应NextTourButton事件
newActionListener(){
publicvoidactionPerformed(ActionEvente){
if(recordCountrecordCount++;
}else{recordCount=0;}
myPanel.initboard(recordXpos[recordCount],
recordYpos[recordCount]);
myPanel.repaint();
}
}
);//endcalltoaddActionListener
}
publicvoidpaint(Graphicsg)
{super.paint(g);}
}//endofclassKnightsTour
classAccessibleSquares{
//骑士8个方向走L形状所需的X坐标和Y坐标的变化量
privatestaticinthorizontal[]={2,1,-1,-2,-2,-1,1,2};
privatestaticintvertical[]={-1,-2,-2,-1,1,2,2,1};
privateintxpos[];//骑士所处X轴的坐标
privateintypos[];//骑士所处y轴的坐标
privateintaccessibility[];//表示可达到数
privateintownxpos,ownypos;
privateintownAccessibility;
privateintarrayPos;
privateintcountAccessibility;
publicAccessibleSquares(intx,inty){//构造函数
inttestXPos;inttestYPos;
xpos=newint[8];//骑士所处X轴的坐标
ypos=newint[8];
accessibility=newint[8];
arrayPos=0;
ownxpos=x;ownypos=y;
ownAccessibility=KnightsTour.access[x][y];
for(inti=0;itestXPos=x+horizontal[i];//得出X,Y坐标的测试位置
testYPos=y+vertical[i];
if((testXPos>=0)&(testXPos<8)&
(testYPos>=0)&(testY