开发工具:eclipse,jdk1.8
- 概述
拼图游戏是广受欢迎的一种智力游戏,它的变化多端,难度不一,让人百玩不厌。拼图游戏是把一张图片分成多个小块,根据难度一般有9块(3×3)、16块(4×4)、25块(5×5)等,然后随机打乱图块的顺序,重新把拼图还原成原来的样子。这次我做的这个拼图小游戏就是一个简单的3×3小拼图,可以实现一般的拼图功能,并且可以选择不同的图片。操作也是非常简单,鼠标点击“开始游戏”进行游戏,然后用鼠标点击拼图块完成拼图就可以了。
- 程序分析。
该游戏程序由MyMainFrame、MyCanvas、Cell三部分组成,其中Cell类是继承的按钮类,并加上相应图片形成拼图方格, MyCanvas类是一个面板,加载Cell类的对象(方格),是这三个类中的核心,并且定义了接收鼠标事件以及开始游戏的方法,MyMainFrame类是主程序,初始化了面板,并在面板上添加了按钮。
- 程序设计,
3.1程序目标
-
- 将原始图片分割成大小相同的9个小方格,每个小方格加载相应的图片;
- 通过鼠标点击小方格来进行移动;
- 用户界面具有标题,并且在上方面板上添加“开始游戏”、“查看图片”、“选择图片”按钮;
- 原始图片至少有5张以上,进行游戏时可以选择任意一张;
- 用户界面美观、简洁、友好,符合日常软件的使用规范;
- 当完成拼图是会弹出消息框显示“恭喜你完成拼图”。
-
? ? ①Cell模块
首先Cell类继承了JButton类,然后构造了宽100,高100的方格,this.setSize(100,100)就是设定方格大小的语句。然后还定义了方格移动的方法,当参数direction为“UP”时,方格向上移动,用this.setLocation()实现;当参数direction为“DOWN”时,方格向下移动;当参数direction为“LEFT”时,方格向左移动;当参数direction为“RIHGT”时,方格向右移动。
主要方法代码如下:
Cell(Icon icon){构造方格
super(icon);//调用父类构造函数
this.setSize(100,100);//每块方格拼图设置为宽100,高100
}
Move方法用来进行方格的移动:
public void move(String direction,int sleep){//方格的移动
if(direction=="UP"){//上移
this.setLocation(this.getBounds().x,this.getBounds().y-100);
}else if(direction=="DOWN"){//下移
this.setLocation(this.getBounds().x,this.getBounds().y+100);
}else if(direction=="LEFT"){//左移
this.setLocation(this.getBounds().x-100,this.getBounds().y);
}else{//右移
this.setLocation(this.getBounds().x+100,this.getBounds().y);
}
}
②MyCanvas模块
MyCanvas类首先继承JPanel类,并实现MouseListener接口。MyCanvas类构造了一个宽400,高400的容器,用this.setSize(400,400)实现。接着构造了一个宽100,高100的空方格区域放在第三行每三列,然后为9个方格加载图片,并初使化坐标,形成三行三列,最后还要移除最后一个方格。模块还定义了一个方法isFinish来判断拼图是否拼合成功,成功返回true,否则返回false。 模块定义了Start方法来开始游戏,使方格随机排序。还定义了方格的鼠标事件mousePressed(MouseEvent arg0)来进行点击方格跟空方格的交换。当完成拼图时,用JOptionPane.showMessageDialog(this,"恭喜你完成拼图!")弹出消息框显示“恭喜你完成拼图!”
主要方法代码如下:
MyCanvas方法用来初始化方格并给方格加载图片:
public MyCanvas() {初始化方格,并给每个方格加载图片
this.setLayout(null);//设置此容器的布局管理器
this.setSize(400,400);
cellNull=new Rectangle(200,200,100,100);//空方格区域在第三行每三列,宽100,高100
cell=new Cell[9];
Icon icon;
for (int i = 0; i < 3; i++) {//为9个方格加载图片,并初使化坐标,形成三行三列
for(int j=0;j<3;j++){
icon=new ImageIcon("pictrue/pic_"+pictureID+"_"+(i*3+j+1)+".jpg");
cell[i*3+j]=new Cell(icon);
cell[i*3+j].setLocation(j*100,i*100);//初始化方格坐标
this.add(cell[i*3+j]);//添加方格
}
}
this.remove(cell[8]);//移除最后一个多余的方格
}
isFinish方法用来判断拼图是否拼合成功:
public boolean isFinish(){//判断拼图是否拼合成功
for(int i=0;i<8;i++){
int x=cell[i].getBounds().x;
int y=cell[i].getBounds().y;
if(y/100*3+x/100!=i)//依次判断每个方格是否在最初的位置
return false;
}
return true;
}
Start方法用来打乱方格顺序,进行随机排序
public void Start(){//对方格进行重新排列,打乱顺序
while(cell[0].getBounds().x<=100&&cell[0].getBounds().y<=100){//当第一个方格距左上角较近时
int x=cellNull.getBounds().x;
int y=cellNull.getBounds().y;
int direction=(int)(Math.random()*4);//产生0-4,对应空方格的上下左右移动
if(direction==0){//LEFT空方格左移动,与左侧方格互换位置,左侧方格右移动
x-=100;
if(test(x,y)){
for(int j=0;j<8;j++){
if((cell[j].getBounds().x==x)&&(cell[j].getBounds().y==y)){//依次寻找空方格左侧的方格
cell[j].move("RIGHT",100);//左侧方格右移动
cellNull.setLocation(x,y);//空方格左移动
break;//找到后跳出for循环
}
}
}
}else if(direction==1){//RIGHT
x+=100;
if(test(x,y)){
for(int j=0;j<8;j++){
if((cell[j].getBounds().x==x)&&(cell[j].getBounds().y==y)){
cell[j].move("LEFT",100);
cellNull.setLocation(x,y);
break;
}
}
}
}else if(direction==2){//UP
y-=100;
if(test(x,y)){
for(int j=0;j<8;j++){
if((cell[j].getBounds().x==x)&&(cell[j].getBounds().y==y)){
cell[j].move("DOWN",100);
cellNull.setLocation(x,y);
break;
}
}
}
}else{//DOWN
y+=100;
if(test(x,y)){
for(int j=0;j<8;j++){
if((cell[j].getBounds().x==x)&&(cell[j].getBounds().y==y)){
cell[j].move("UP",100);
cellNull.setLocation(x,y);
break;
}
}
}
}
}
if(!hasAddActionListener)//如果尚未添加动作事件,则添加
for(int i=0;i<8;i++)//为第个方格添加动作事件,这样单击按钮就能移动了
cell[i].addMouseListener(this);
hasAddActionListener=true;
}
mousePressed方法用来进行点击方格跟空方格的交换:
public void mousePressed(MouseEvent arg0) {//方格的鼠标事件
Cell button=(Cell)arg0.getSource();//确定点击的方格
int x1=button.getBounds().x;//得到所单击方格的坐标
int y1=button.getBounds().y;
int x2=cellNull.getBounds().x;//得到空方格的坐标
int y2=cellNull.getBounds().y;
if(x1==x2&&y1-y2==100)//进行比较,如果满足条件则进行交换
button.move("UP",100);
else if(x1==x2&&y1-y2==-100)
button.move("DOWN",100);
else if(x1-x2==100&y1==y2)
button.move("LEFT",100);
else if(x1-x2==-100&&y1==y2)
button.move("RIGHT",100);
else
return;//不满足就不进行任何处理
cellNull.setLocation(x1,y1);//空方格移动到点击的方格坐标
this.repaint();//重绘此组件
if(this.isFinish()){//进行是否完成的判断
JOptionPane.showMessageDialog(this,"恭喜你完成拼图!");//调出 消息对话框
for(int i=0;i<8;i++)
cell[i].removeMouseListener(this);//如果已完成,撤消鼠标事件,鼠标单击方格不在起作用
hasAddActionListener=false;
}
}
③MyMainFrame模块
MyMainFrame类先继承了JFrame类并实现ActionListener接口。用MyMainFrame方法初始化面板,在上方面板上添加了“开始游戏”、“查看图片”、“选择图片”三个按钮,并在主面板上坐标(0,0)位置加载了宽300高300的图片,用label.setBounds(0,0,300,300); panelPreview.add(label)实现。用语句panelNorth.setBackground(Color.gray)将上方面板设置成灰色,用语句this.setTitle("拼图小游戏")设置界面窗口标题为拼图小游戏。this.setResizable(false)语句设置窗体为不可以由用户调整大小。再用actionPerformed(ActionEvent arg0)方法对三个按钮事件进行处理。当点击“开始游戏”的按钮,就执行Start方法即初始化游戏;当点击“查看图片”按钮,主面板显示图片,并把“显示图片”按钮改成“返回游戏”按钮,当再次点击“返回游戏”按钮时,就会回到游戏并且“返回游戏”按钮也会变回“查看图片”按钮;当点击“选择图片”按钮时,就会弹出选择方框,方框里有6张图片可以选择,分别是小猫、小猪、云彩、QQ、动漫、花朵。
主要方法代码如下:
actionPerformed 方法是对“开始游戏”、“查看图片”、“选择图片”三个按钮进行相对应的功能设置:
public void actionPerformed(ActionEvent arg0) {//对三个按钮事件的处理
// TODO 自动生成方法存根
Button button=(Button)arg0.getSource();
if(button==start){
myCanvas.Start();
}else if(button==preview){
if(button.getLabel()=="查看图片"){
container.remove(myCanvas);
container.add(panelPreview);
panelPreview.updateUI();//利用当前外观的值重置UI属性
container.repaint();
button.setLabel("返回游戏");
}else{
container.remove(panelPreview);
container.add(myCanvas);
container.repaint();
button.setLabel("查看图片");
}
}else if(button==set){//修改所选图片
Choice pic = new Choice();
pic.add("小猫");
pic.add("小猪");
pic.add("云彩");
pic.add("QQ");
pic.add("动漫");
pic.add("花朵");
int i=JOptionPane.showConfirmDialog(this, pic, "选择图片", JOptionPane.OK_CANCEL_OPTION);
if(i==JOptionPane.YES_OPTION){//当选择YES时
MyCanvas.pictureID=pic.getSelectedIndex()+1;//把选择的图片索引号返回给pictureID
myCanvas.reLoadPictrue();//重新加载图片
Icon icon=new ImageIcon("pictrue/pic_"+MyCanvas.pictureID+".jpg");
JLabel label=new JLabel(icon);
label.setBounds(0,0,300,300);
panelPreview.removeAll();
panelPreview.add(label);
panelPreview.repaint();
}
}
|