java连连看含代码.docx
《java连连看含代码.docx》由会员分享,可在线阅读,更多相关《java连连看含代码.docx(15页珍藏版)》请在冰点文库上搜索。
java连连看含代码
JAVA连连看游戏
一、功能描述:
通过JAVA编一个连连看程序,通过鼠标点击使相同两个图像消掉。
程序实现以下几个功能:
1、判断鼠标点击的两张图片是否相同;
2、判断2张图片是否可以相连;
3、判断时间;
4、判断是否使用炸弹,炸弹剩余数目,自动生成路径消除两张相同图片;
5、判断剩余图片,是否胜利。
二、方案:
概要设计:
程序分为6个部分:
第一:
主窗口部分(MainFrame)定义了程序用函数,实现了程序菜单(initMenuBar)的使用。
第二:
按键部分(ChessButton)定义按键的位置,代表的值。
第三:
游戏部分(MapUI)判断点击的图片,判断两图片是否可连,是否相同。
判断是否胜利。
实现炸弹功能。
第四:
数组(Settings)确定了游戏各种参数属性。
第五:
取值部分(ArrayPoint)定义图片的值。
第六:
算法部分(Map)通过算法确定两张图片是否连通。
详细设计:
运行效果与程序发布:
本程序含有6个JAVA源程序,一个图片文件夹。
通过JCreatorPro运行及修改程序。
把ChessButton.java,MainFrame.java和MapUI.java文件保存在同一文件夹(如:
D:
\lianliankan\)。
把Settings.java放入一层文件加的\cn\elva文件夹下(如:
D:
\lianliankan\cn\elva)。
把ArrayPoint.java和Map.java放入文件夹的\cn\elva\model文件夹中。
在文件夹中建立一个叫Resource的文件夹存放图片。
运行JCreatorPro编译JAVA程序,生成相应的字节码文件(.class)文件。
然后,用java解释器运行主类:
D:
\lianliankan\javaMainFrame。
功能模块图如上。
程序通过对用户点击的图片进行判断,确定两张图片的路径,判断两张图片是否相同,是否可以相连,如果可以相连并且两张图片相同,那么消除两张图片,否则认为用户没点图片,重新选择。
系统会在用户开始的时候进行计时,如果用户在限定时间内没有完成(还有图片枚消除),那么系统提示用户失败信息,反之(图片全部消除),提示用户胜利信息。
在游戏过程中,用户可以使用炸弹,如果炸弹存在(炸弹数部为零)那么消除2块同样的图片,否则提示用户没有炸弹。
定义程序的必要变量的初值使每回开始新游戏,这些初值都会还原:
行数:
publicstaticfinalintROWS=8;
列数:
publicstaticfinalintCOLUMNS=8;
图片后缀名:
publicstaticfinalStringRELEX=".gif";
每局所花时间(秒):
publicstaticfinalintPERTIME=600;
判断的时间间隔:
publicstaticfinalintPER=1;
炸弹的使用次数:
publicstaticfinalintBOMBCOUNT=3;
把每一个图片位置都定义为一个按钮,这样在鼠标点击的时候就能确定用户点击的是哪张图片。
publicclassChessButtonextendsJButton
{
//按钮所对应的数组中的值和位置,用ArrayPoint结构来表示
protectedArrayPointpoint=null;
/**
*构造函数,指定按钮所代表的值和位置
*@paramrow所在行号
*@paramcol所在列号
*@paramvalue代表的值
*/
publicChessButton(introw,intcol,intvalue)
{this(newArrayPoint(row,col,value));}
/**
*构造函数
*@parampoint值和位置的数据结构
*/
publicChessButton(ArrayPointpoint)
{this.point=point;
Stringname="Resource/"+point.getValue()+Settings.RELEX;
URLurl=ChessButton.class.getResource(name);
//System.out.println(url);
ImageIconicon=newImageIcon(url);
this.setIcon(icon);}
/**
*构造函数,使用默认值
*/
publicChessButton()
{this(newArrayPoint(0,0,0));
/**
*返回当前按钮代表的位置和值
*@returnpoint
*/
publicArrayPointgetPoint()
{returnpoint;}
/**
*设置此按钮所代表的位置和值
*@parampoint要设置的point
*/
publicvoidsetPoint(ArrayPointpoint)
{this.point=point;}}
设计算法排列图片,设计算法判断两张图片是否可以相连
/*@authorAXL数据部分,一个内部数组来表示页面上的具体情况/
publicclassMap
{publicstaticintLEFTCOUNT=Settings.ROWS*Settings.COLUMNS;
//让其最外层的数据不显示,可以解决边框消除不掉的情况
privateint[][]map=newint[Settings.ROWS+2][Settings.COLUMNS+2];
//privateArrayPointprePoint;
//privateArrayPointcurrPoint;
//出现的不同图片个数
privateintmaxKinds=4;
publicMap()
{init();}
publicint[][]getMap()
{returnmap;}
/*实现了二维数组的产生/
privatevoidinit()
{int[]tempArr=newint[Settings.ROWS*Settings.COLUMNS];
intlen=tempArr.length;
//根据图片的种类数来确定数组大小,如有64张图片,每四个为一样的,则需要图片数为64/4=16
for(inti=0;i{tempArr[i*4]=i+1;
tempArr[i*4+1]=i+1;
tempArr[i*4+2]=i+1;
tempArr[i*4+3]=i+1;}
//打乱一维数组内数据的排列
random(tempArr);
//填充到二维数组中
for(inti=1;i{for(intj=1;j{this.map[i][j]=tempArr[(i-1)*Settings.COLUMNS
+(j-1)];}}}
/*将数组进行重排,使其成无序状态
*@paramarray要重排的数组/
privatevoidrandom(int[]array)
{Randomrandom=newRandom();
intlen=array.length;
for(inti=len;i>0;i--)
{intj=random.nextInt(i);
inttemp=array[i-1];
array[i-1]=array[j];
array[j]=temp;}}
/*判断是否在一条直线上,这里不去比较两者值是否相等,主要用于后面两个拐点的情况
*@paramp1之前的点
*@paramp2当前所点的点
*@returntrue相通,false不通/
publicbooleanoneLineWithoutValue(ArrayPointp1,ArrayPointp2)
{if(horizonMatch(p1,p2))
{returntrue;}
elseif(verticalMatch(p1,p2))
{returntrue;}
returnfalse;}
/*判断是否在一条直线上,其中包括了垂直和水平两种情况
*@paramp1之前的点
*@paramp2当前所点的点
*@returntrue相通,false不通/
publicbooleanoneLine(ArrayPointp1,ArrayPointp2)
{if(p1.value!
=p2.value)
returnfalse;
if(oneLineWithoutValue(p1,p2))
returntrue;
returnfalse;}
/*竖线上的判断
*@paramp1之前的点
*@paramp2当前所点的点
*@returntrue相通,false不通/
publicbooleanverticalMatch(ArrayPointp1,ArrayPointp2)
{if(p1.j!
=p2.j)
returnfalse;
if(p1.i>p2.i)
{ArrayPointtemp=null;
temp=p1;
p1=p2;
p2=temp;}
//之间的相隔的棋子数
intspaceCount=p2.i-p1.i;
//如果相邻,直接消除
if(spaceCount==1&&p1.value==p2.value)
returntrue;
for(inti=p1.i+1;i{ArrayPointpoint=newArrayPoint(i,p1.j,map[i][p1.j]);
//只要其值为0就表示没有棋子
if(point.value!
=0)
returnfalse;}
returntrue;}
/*水平方向的判断
*@paramp1之前所选的点
*@paramp2当前选中的点
*@returntrue相通,false不通/
publicbooleanhorizonMatch(ArrayPointp1,ArrayPointp2)
{//如果行行号不等的话,刚不是水平方向的结果
if(p1.i!
=p2.i)
returnfalse;
if(p1.j>p2.j)
{ArrayPointtemp=null;
temp=p1;
p1=p2;
p2=temp;}
//水平相隔棋子数
intspaceCount=p2.j-p1.j;
//如果相邻,直接消除
if(spaceCount==1&&p1.value==p2.value)
returntrue;
for(inti=p1.j+1;i{ArrayPointp=newArrayPoint(p1.i,i,map[p1.i][i]);
if(p.value!
=0)
returnfalse;}
returntrue;}
/*判断前后点击的是不是同一个点,i,j相同就是一个点
*@paramp1之前所选的点
*@paramp2当前选中的点
*@returntrue同一个点,false不同点/
privatebooleanisSameOne(ArrayPointp1,ArrayPointp2)
{if(p1.i==p2.i&&p1.j==p2.j)
returntrue;
else
returnfalse;}
/*带一个拐点的情况,但不比较值的大小是否相等
*@paramp1初始点
*@paramp2结束点
*@returntrue相通,false不通*/
publicbooleanoneConnerWithoutValue(ArrayPointp1,ArrayPointp2)
{//获取P1水平方向的拐点
ArrayPointp1H=newArrayPoint(p1.i,p2.j,map[p1.i][p2.j]);
//获取P1垂直方向的拐点
ArrayPointp1V=newArrayPoint(p2.i,p1.j,map[p2.i][p1.j]);
if(horizonMatch(p1,p1H)&&(p1H.value==0))
{if(this.verticalMatch(p1H,p2))
returntrue;}
if(verticalMatch(p1,p1V)&&(p1V.value==0))
{if(horizonMatch(p1V,p2))
returntrue;}
returnfalse;}
/*带一个拐点的情况
*@paramp1初始点
*@paramp2结束点
*@returntrue相通,false不通*/
publicbooleanoneConner(ArrayPointp1,ArrayPointp2)
{//获取P1水平方向的拐点
ArrayPointp1H=newArrayPoint(p1.i,p2.j,map[p1.i][p2.j]);
//获取P1垂直方向的拐点
ArrayPointp1V=newArrayPoint(p2.i,p1.j,map[p2.i][p1.j]);
if(p1.value!
=p2.value)
returnfalse;
if(oneConnerWithoutValue(p1,p2))
returntrue;
returnfalse;}
/*带两个拐点的情况,分四个方向走,上下左右,只要一个方向通过,即通过
*@paramp1初始点
*@paramp2结束点
*@returntrue相通,false不通*/
publicbooleantwoConner(ArrayPointp1,ArrayPointp2)
{if(p1.value!
=p2.value)
returnfalse;
intcount=0;
ArrayPointtemp=null;
//左
for(intcol=p1.j-1;col>=0;col--)
{temp=newArrayPoint(p1.i,col,map[p1.i][col]);
if((temp.value==0)&&this.oneLineWithoutValue(p1,temp))
{if(this.oneConnerWithoutValue(temp,p2))
returntrue;}
else
break;}
右、上和下的方法一样,代码相似。
在此不给出方法。
/*判断两点是否匹配,包括直线,一个拐点,两个拐点三种情况
*@paramp1初始点
*@paramp2结束点
*@returntrue相通,false不通*/
publicbooleanmatch(ArrayPointp1,ArrayPointp2)
{if(this.isSameOne(p1,p2))
returnfalse;
if(oneLine(p1,p2))
{map[p1.i][p1.j]=0;
map[p2.i][p2.j]=0;
LEFTCOUNT-=2;
returntrue;}
if(oneConner(p1,p2))
{map[p1.i][p1.j]=0;
map[p2.i][p2.j]=0;
LEFTCOUNT-=2;
returntrue;}
if(twoConner(p1,p2))
{map[p1.i][p1.j]=0;
map[p2.i][p2.j]=0;
LEFTCOUNT-=2;
returntrue;}
returnfalse;}}
设计算法是图片可以消除,设计炸弹算法,使用户可以使用炸弹。
publicclassMapUIextendsJPanelimplementsActionListener
{privatestaticfinallongserialVersionUID=1L;
//privateintbombCount=Settings.BOMBCOUNT;
//棋子数组,用按钮来表示
privateChessButton[]chesses=null;
//数据模型
privateMapmap=newMap();
//判断当前点击的棋子是否是第二次选中的
privatebooleantwo=false;
//前面点的那个棋子
privateArrayPointpriviousPoint;
//第二次选中的棋子
privateArrayPointcurrPoint;
/**构造函数*/
publicMapUI()
{super();
initialize();}
/**初始化函数
*@returnvoid/
privatevoidinitialize(){
initChesses();
GridLayoutgridLayout=newGridLayout(Settings.ROWS+2,
Settings.COLUMNS+2);
gridLayout.setHgap
(2);
gridLayout.setVgap
(2);
this.setLayout(gridLayout);
this.setSize(300,200);
//放置按钮,按行
for(introw=0;row{for(intcol=0;coladd(chesses[row*(Settings.COLUMNS+2)+col]);}}
privatevoidinitChesses()
{int[][]values=map.getMap();
//初始化棋子,和数据模型里保持一样
this.chesses=newChessButton[(Settings.ROWS+2)
*(Settings.COLUMNS+2)];
for(introw=0;row<10;row++)
{for(intcol=0;col<10;col++)
{//通过二维的数据模型坐标得到一维的棋子坐标
intindex=row*(Settings.COLUMNS+2)+col;
//对棋子的数据模型,即ArrayPoint对象进行设置,指定此棋子具体的位置和值
chesses[index]=newChessButton(row,col,values[row][col]);
//添加监听器
chesses[index].addActionListener(this);
//将外围的一圈设为不可见,行,列为0和为最大值的情况
if(row==0||row==(Settings.ROWS+2-1)||col==0
||col==(Settings.COLUMNS+2-1))
chesses[index].setVisible(false);}}}
publicvoidclearCheese(ArrayPointpriviousPoint,ArrayPointcurrPoint)
{//处理匹配,看两点中否联通获得数据模型中的数组
int[][]values=map.getMap();
//将模型中对应的棋子设为0
values[priviousPoint.getI()][priviousPoint.getJ()]=0;
values[currPoint.getI()][currPoint.getJ()]=0;
//使两个已经消除的按钮不可见
intindex1=priviousPoint.getI()*(Settings.COLUMNS+2)
+priviousPoint.getJ();
intindex2=currPoint.getI()*(Settings.COLUMNS+2)
+currPoint.getJ();
chesses[index1].setVisible(false);
chesses[index2].setVisible(false);
//如果棋子总数已为0,则程序结束
if(map.LEFTCOUNT==0)
{JOptionPane.showMessageDialog(this,"恭喜您通过!
!
");}}
/*事件监听器处理函数,也是处理棋子消除的地方/
publicvoidactionPerformed(ActionEvente)
{//获得当前的柜子
ChessButtonbutton=(ChessButton)e.getSource();
//