资源描述
面向对象的课程设计与分析(java)——拼图游戏 (学号。。。班级。。。姓名。。。)
目录
一、 题目介绍.... 3
1、题目.............................................................................................3
2、任务..............................................................................................3
3、要求...............................................................................................3
二、需求分析.............................................................................3
三、 概要设计..............................................................................4
1、功能分析.......................................................................................4
2、界面初始化...................................................................................4
3、事件处理(1)鼠标事件.............................................................4
4、事件处理(2)键盘事件.............................................................5
5、状态判断.......................................................................................5
6、程序流程图...................................................................................5
四、 详细设计.............................................................................6
1、.html代码设计............................................................................6
2、.java代码设计............................................................................6
五、调试结果.............................................................................19
第一个大图的拼图界面..........................................................................19
第一个拼图全图预览..............................................................................19
第二个大图的拼图界面..........................................................................20
第二个拼图全图预览..............................................................................20
第三个大图的拼图界面..........................................................................21
第三个拼图全图预览..............................................................................21
六、心得总结.............................................................................22
七、参考资料 ...........................................................................22
一、 题目介绍
1、 题目:
拼图游戏设计
2、 任务:
利用java的图形用户界面设计,设计一个拼图游戏界面,能够实现基本的游戏功能。
3、 要求:
(1)游戏者可以选择不同的图片。
(2)按完成的时间计算成绩。
(3)记录拼图完成的总步数。
二、 需求分析
拼图游戏是一个简单的小程序,游戏规则如下:
将一张大图打散成9张小图,然后在游戏里任意挑8张图,贴在3行3列的矩阵中的任意位置。通过鼠标或键盘的方向键移动打乱的8张图片,让其复原成原来的顺序,玩家就胜利了,游戏就结束了。在游戏结束之后,算出玩家的得分。
三、概要设计
1、功能分析
由于要计算游戏的时间,需要引入线程,通过实现Runnable接口和创建Thread类来实现线程的功能。使用多线程机制来计算时间的流逝。引入AWT绘图包,实现图片的绘制。 引入事件处理机制,要求对鼠标事件,键盘事件进行相应,实现移动图片,预览全图等功能。
按键“Y”实现临时的原图整体预览。
按键“1或者2或者3”实现大图选择、
2、 界面初始化
调用public void init()通过接收html数据,加载三张源图片,安装媒体监视器和鼠标键盘监听器,实现界面初始化;
调用public void initData()将加载的一张大图分割成九个随机分布的小图部分;
调用public void paint(Graphics g)划分提示信息区域和拼图区域;
3、 事件处理
(1) 鼠标事件
调用public void mouseClicked(MouseEvent e)方法实现鼠标事件处理。
调用Public int directionCanMove(int nCol,int nRow)方法检测那个方向没有拼图而可以向之移动。
调用public void move(int nCol,int nRow,int nDirection)方法实现鼠标激活拼图移动。
(2) 键盘事件
调用public void keyPressed(KeyEvent e)方法实现键盘事件处理。
调用public void initImageAgain(int nImgNo)方法实现重新加载另一张大图。
调用public boolean move(int nDirection)方法实现判断指定拼图是否可以往方向nDirection移动。
4、状态判断
动过调用public void checkStatus()方法来
检测拼图状态,判断是否拼图成功,确定游戏是否结束。
5、附加功能
调用public void run()方法,给游戏过程添加计时进程。
6、程序流程图
四、 详细设计
1、 编写.html代码
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>
拼图游戏
</title>
</HEAD>
<body>
拼图游戏
<hr>
这是一个拼图游戏。玩家应该将打散的小图拼成一张大图。<br>
玩家可以通过鼠标和键盘来移动小图,移动的次数和拼成<br>
一张大图所化费的时间作为游戏得分的依据。<br>
成绩=1000-时间(秒)-移动步数*10<br>
按F1键重新开始该游戏,按Y健可以预览整个的图片
<hr>
<applet code="pintu.class" width="480" height="360">
<!-- param标签 NumOfImg param的标签表示有多少张图片
剩下的param标签为每张图的名字
-->
<param name=NumOfImg value="3">
<param name=Image1 value="pintu">
<param name=Image2 value="pintu2">
<param name=Image3 value="pintu3">
</applet>
</body>
</html>
2、 编写.java代码
1、界面设计和附加功能
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import .*;
//Download by
public class pintu extends Applet implements MouseListener,KeyListener,Runnable
{
Image[] m_Image=new Image[9];
//9个用来装入每个拼图的图片对象
Image m_ImgAll;
//总的大图片
int m_nImageNo[][]=new int[3][3];
////标志现在各个拼图的排列情况
final int NO_IMAGE=-1;
//此位置没有拼图,表示空白拼图
final int IMAGE_WIDTH=120;
//每张拼图的宽
final int IMAGE_HEIGHT=120;
////每张拼图的高
final int DIRECTION_UP=1;
final int DIRECTION_DOWN=2;
final int DIRECTION_LEFT=3;
final int DIRECTION_RIGHT=4;
final int DIRECTION_NONE=-1;
final int DELTAX=120;
//标志提示信息区的宽度
boolean bWantStartNewGame=false;
//游戏是否结束,是否需要开始新游戏
int nStep=0;
//已经走的步数
int nTime=0;
//已经玩过的时间,以秒为单位
Thread thTimer;
//计时器线程
int nScore=0;
//玩家所得的分数
int m_nNumOfImg=0;
//拼图底图所使用的图片的个数
String m_sImgName[]=new String[9];
//记录拼图底图的名字
boolean bOnShowAll=false;
//预览的开关
AudioClip m_audioClip1,m_audioClip2;
//装载要播放的声音对象
public void init()/
{
String param=getParameter("NumOfImg");
try
{
m_nNumOfImg=Integer.parseInt(param);
}
catch(Exception e)
{
m_nNumOfImg=1;
System.out.println("Can't convert the param's name to int.");
}
for(int i=0;i<m_nNumOfImg;i++)
{
m_sImgName[i]=getParameter("Image"+(i+1))+".jpg";
//用字符串数组m_sImgName分别保存三个大图及其规范命名:p
//pintu.jpg pintu1.jpg pintu2.jpg
System.out.println(m_sImgName[i]);
}
System.out.println(param);
MediaTracker mediaTracker=new MediaTracker(this);
//为这个拼图界面设置一个监视器
m_ImgAll=getImage(getDocumentBase(),"img/"+m_sImgName[0]);
//从装载总的大图片
mediaTracker.addImage(m_ImgAll,1);
//为向此媒体跟踪器正在跟踪的图像列表中添加一个图像,
//并分配一个表示号1 给这个图像
try
{
mediaTracker.waitForID(1);
//加载所跟踪的图像列表中的某一个标识号所对应的的一个图像
}
catch(Exception e)
{
System.out.println("图片装载出错");
}
if(mediaTracker.isErrorAny())System.out.println("图片装载出错");
for(int i=0;i<9;i++)
{
m_Image[i]=createImage(IMAGE_WIDTH,IMAGE_HEIGHT);
Graphics g=m_Image[i].getGraphics();
int nRow=i%3;
int nCol=i/3;
g.drawImage(m_ImgAll,
0,
0,
IMAGE_WIDTH,
IMAGE_HEIGHT,
nRow*IMAGE_WIDTH,
nCol*IMAGE_HEIGHT,
(nRow+1)*IMAGE_WIDTH,
(nCol+1)*IMAGE_HEIGHT,
this);
System.out.println("init "+i);
}
//将一个大图切割成九个小图
System.out.println("init over");
thTimer=new Thread(this);
//为线程分配内存空间
thTimer.start();
//开始线程
initData();
m_audioClip1=getAudioClip(getCodeBase(),"au/move.au");
m_audioClip2=getAudioClip(getCodeBase(),"au/notmove.au");
addMouseListener(this);
addKeyListener(this);
public void initData()
{
System.out.println("run initData");
int[] nHasDistrib=new int[9];
//为每个小图分配一个数字标识,用来判定该小图是否被随机编一个二维数组号
for(int i=0;i<9;i++)nHasDistrib[i]=0;
for(int j=0;j<3;j++)
{
for(int i=0;i<3;i++)
{
int nCount=j*3+i;
int nImgNo=-1;
do
{
nImgNo=(int)(Math.random()*9);
}while(nHasDistrib[nImgNo]==1);
//1代表已经分配了这张图片到二维数组中的随机位置
m_nImageNo[i][j]=nImgNo;
nHasDistrib[nImgNo]=1;
System.out.println("test..");
}
}
m_nImageNo[(int)(Math.random()*3)][(int)(Math.random()*3)]=NO_IMAGE;
nStep=0;
nTime=0;
//清空计时器
}
public void run()
{
while(Thread.currentThread()==thTimer)
{
try
{
thTimer.sleep(990);
String sTemp="你玩了"+nTime+"秒的时间,";
if(nTime>200)sTemp=sTemp+"时间用的很长了,你可要加油啦!";
else sTemp=sTemp+"别紧张,慢慢来。";
showStatus(sTemp);
if(!bWantStartNewGame)nTime++;
}
catch(Exception e)
{
}
}
}
public void paint(Graphics g)
{
g.setColor(Color.blue);
//将当前颜色变为蓝色
g.fillRect(0,0,DELTAX,IMAGE_HEIGHT*3);
//填充左边的提示信息区域
g.setFont(new Font("宋体",Font.PLAIN,15));
//设置字体
/*Font是一个字体类!PLAIN是它的一个静态常量!类似的还有BOLD,ITALIC
Font.PLAIN 是一个普通的系统默认的字体!
jMenuSystem.setFont(new java.awt.Font("华文新魏", Font.PLAIN, 20));
设置字体为 华文新魏 类型: 普通系统默认 大小为20
*/
g.setColor(Color.red);
//setColor函数对该函数调用的下文进行颜色设置
g.drawString("步数:"+nStep,5,20);
g.drawString("现有图片"+m_nNumOfImg+"张",5,60);
g.drawString("请按1-"+m_nNumOfImg+"键改变图片",5,100);
//在坐标(5,20)画出字串,来显示现在走了多少步。
g.setColor(Color.blue);
if(bOnShowAll)
{
int x=DELTAX;
int y=0;
g.drawImage(m_ImgAll,x,y,this);
return;
}
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
int x=i*IMAGE_WIDTH+DELTAX;
int y=j*IMAGE_HEIGHT;
if(m_nImageNo[i][j]==NO_IMAGE)
g.fill3DRect(x,y,IMAGE_WIDTH,IMAGE_HEIGHT,false);
else
{
g.drawImage(m_Image[m_nImageNo[i][j]],x,y,this);
g.drawRect(x,y,IMAGE_WIDTH,IMAGE_HEIGHT);
}
}
}
checkStatus();
if(bWantStartNewGame)
{
//如果游戏结束,玩家将拼图的顺序排对之后
nScore=1000-nStep*10-nTime;
g.setColor(Color.blue);
g.drawString("请按任意键重新开始",5,140);
g.setColor(Color.red);
g.setFont(new Font("宋体",Font.PLAIN,40));
g.drawString("你赢了"+nScore+"分",70+DELTAX,160);
g.drawString("祝贺你!",110+DELTAX,210);
}
}
}
public void checkStatus()
{
boolean bWin=true;
//定义成员,默认值为真
int nCorrectNum=0;
for(int j=0;j<3;j++)
{
for(int i=0;i<3;i++)
{
if(m_nImageNo[i][j]!=nCorrectNum&& m_nImageNo[i][j]!=NO_IMAGE)
bWin=false;
nCorrectNum++;
}
}
//比较拼图是否都放到了正确的位置上,如果,有一个没有放到正确位置上,则游戏就不能结束。
if(bWin)bWantStartNewGame=true;
}
2、鼠标事件处理
public void mouseClicked(MouseEvent e)
{
//Invoked when the mouse has been clicked on a component.
if(bOnShowAll)return;
if(bWantStartNewGame)
{
initData();
repaint();
bWantStartNewGame=false;
return;
}
int nX=e.getX()-DELTAX;
int nY=e.getY();
int nCol=nY/IMAGE_HEIGHT;
int nRow=nX/IMAGE_WIDTH;
System.out.println("col:"+nCol+" row:"+nRow);
int nDirection=directionCanMove(nCol,nRow);
if(nDirection!=DIRECTION_NONE)
{
move(nCol,nRow,nDirection);
nStep++;
m_audioClip1.play();
repaint();
}
else
{
m_audioClip2.play();
}
}
public void mouseEntered(MouseEvent e)
{
//Invoked when the mouse has been clicked on a component.
}
public void mouseExited(MouseEvent e)
{
//Invoked when the mouse has been clicked on a component.
}
public void mousePressed(MouseEvent e)
{
//Invoked when the mouse has been clicked on a component.
}
public void mouseReleased(MouseEvent e)
{
//Invoked when the mouse has been clicked on a component.
}
public int directionCanMove(int nCol,int nRow)
//检测那个方向没有拼图而可以向之移动
{
if((nCol-1)>=0)
if(m_nImageNo[nRow][nCol-1]==NO_IMAGE)
return DIRECTION_UP;
if((nCol+1)<=2)
if(m_nImageNo[nRow][nCol+1]==NO_IMAGE)
return DIRECTION_DOWN;
if((nRow-1)>=0)
if(m_nImageNo[nRow-1][nCol]==NO_IMAGE)
return DIRECTION_LEFT;
if((nRow+1)<=2)
if(m_nImageNo[nRow+1][nCol]==NO_IMAGE)
return DIRECTION_RIGHT;
return DIRECTION_NONE;
}
public void move(int nCol,int nRow,int nDirection)
{
switch(nDirection)
{
case DIRECTION_UP:
m_nImageNo[nRow][nCol-1]=m_nImageNo[nRow][nCol];
m_nImageNo[nRow][nCol]=NO_IMAGE;
break;
case DIRECTION_DOWN:
m_nImageNo[nRow][nCol+1]=m_nImageNo[nRow][nCol];
m_nImageNo[nRow][nCol]=NO_IMAGE;
break;
case DIRECTION_LEFT:
m_nImageNo[nRow-1][nCol]=m_nImageNo[nRow][nCol];
m_nImageNo[nRow][nCol]=NO_IMAGE;
break;
case DIRECTION_RIGHT:
m_nImageNo[nRow+1][nCol]=m_nImageNo[nRow][nCol];
m_nImageNo[nRow][nCol]=NO_IMAGE;
break;
}
3、键盘事件处理
public void keyPressed(KeyEvent e)
{
//Invoked when a key has been pressed.
if(bOnShowAll)
{
if(e.getKeyCode()==KeyEvent.VK_Y)
{
bOnShowAll=false;
repaint();
}
return;
}
System.out.println("press key"+e.getKeyCode()+" "
+e.getKeyText(e.getKeyCode()));
System.out.println(KeyEvent.VK_LEFT);
if(bWantStartNewGame)
{
initData();
bWantStartNewGame=false;
repaint();
return;
}
int nDirection=DIRECTION_NONE;
switch(e.getKeyCode())
{
case KeyEvent.VK_DOWN:
nDirection=DIRECTION_DOWN;
break;
case KeyEvent.VK_UP:
nDirection=DIRECTION_UP;
break;
case KeyEvent.VK_LEFT:
System.out.println("left111...");
nDirection=DIRECTION_LEFT;
break;
case KeyEvent.VK_RIGHT:
System.out.println("left...");
nDirection=DIRECTION_RIGHT;
break;
case KeyEvent.VK_F1:
//F1键按下,重新开始游戏
initData();
//init();
repaint();
return;
case KeyEvent.VK_1:
case KeyEvent.VK_2:
case KeyEvent.VK_3:
case KeyEvent.VK_4:
case KeyEvent.VK_5:
case KeyEvent.VK_6:
case KeyEvent.VK_7:
case KeyEvent.VK_8:
case KeyEvent.VK_9:
int nImgNo=e.getKeyCode()-KeyEvent.VK_1;
if(nImgNo<m_nNumOfImg)
{
System.out.println(nImgNo);
initImageAgain(nImgNo);
initData();
repaint();
}
return;
case KeyEvent.VK_Y:
if(bOnShowAll)
bOnShowAll=false;
else
bOnShowAll=true;
repaint();
return;
default:
return;
}
boolean bCanMove=move(nDirection);
if(bCanM
展开阅读全文