Java拼图游戏

总结:

1)添加事件处理要掌握;

2)强制类型转换时若转换的是一个表达式,要记得整体括号括起来转换;

3)静态成员变量的使用

4)实现了某个事件监听器接口时,要记得实现接口中的抽象方法

5)形如

java.lang.Object→

java.awt.Component→

java.awt.Container→

java.awt.Window→

java.awt.Frame→

javax.swing.JFrame

之类的继承关系,即能分清顶层容器,中间容器,原子组件。


MainApp.java

package com.remoa.picturepuzzle;

//启动器类,启动游戏
public class MainApp
{
public static void main(String[] args)
{
// 创建界面
PictureMainFrame frame = new PictureMainFrame();
// 显示界面
frame.setVisible(true);
}

}


PictureMainFrame.java

package com.remoa.picturepuzzle;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;

public class PictureMainFrame extends JFrame
{
private static final long serialVersionUID = 1L;
private String[] items = { "雾里看花", "小邓同学", "全家福", "邓丽君" };// 下拉项选择
private JRadioButton button1;// 显示数字提示按钮
private JRadioButton button2;// 清除数字提示按钮
private JButton button3; // 开始按钮
private PicturePuzzleArea picturePuzzle;// 拼图区
private PicturePreviewArea picturePreview;// 预览区
private JComboBox<String> box;// 下拉框
private JTextField name;// 预览区图片名称显示
public static JTextField step;// 预览区游戏步数显示

// 空参数构造方法
public PictureMainFrame()
{
super();
init();
addComponent();
addPreviewPicture();
addActionListener();// 添加事件监听器
}

private void addActionListener()
{
// 显示数字提示按钮的事件监听器
button1.addActionListener(new ActionListener()
{
// 点击按钮时会自动调用下面的方法
@Override
public void actionPerformed(ActionEvent e)
{
picturePuzzle.reloadPictureAddTips();
}
});

// 清除数字提示按钮的事件监听器
button2.addActionListener(new ActionListener()
{
// 点击按钮时会自动调用下面的方法
@Override
public void actionPerformed(ActionEvent e)
{
picturePuzzle.reloadPictureClearTips();
}
});

// 接收项事件的监听器
box.addItemListener(new ItemListener()
{
@Override
public void itemStateChanged(ItemEvent e)
{
// 获取到选择的图片的序号
int num = box.getSelectedIndex();
//更新选择的图片序号
PicturePuzzleArea.pictureNum = num + 1;
// 更新预览区
picturePreview.repaint();
// 更新拼图区
picturePuzzle.reloadPictureClearTips();
// 更新当前步数
PicturePuzzleArea.stepNum = 0;
step.setText("Current step: " + PicturePuzzleArea.stepNum);
// 更新图片名称
name.setText("Picture's name: " + box.getSelectedItem());
// 更新按钮区
button2.setSelected(true);
}
});

// 开始按钮的事件监听器
button3.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
// 步数清零
PicturePuzzleArea.stepNum = 0;
// 更新游戏状态区
step.setText("Current step: " + PicturePuzzleArea.stepNum);
// 小方格的随机打乱
picturePuzzle.start();
}
});
}

// 初始化界面
public void init()
{
// 设置窗口大小
this.setSize(1000, 640);// 窗口宽度为1000像素,高度为640像素
// 设置窗口标题
this.setTitle("Picture Puzzle");// 游戏标题为“拼图游戏”
// 设置窗口固定
this.setResizable(false);// 窗体不可由用户调整大小
// 设置窗口显示位置
this.setLocation(150, 40); // 运行时将组件移动到x = 150, y = 40的位置显示
// 设置窗口默认关闭操作
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

// 添加组件
public void addComponent()
{
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(1, 2));// 设置面板布局为网格布局1行2列
this.add(panel, BorderLayout.NORTH);// 设置面板位置在上方

// 创建左边按钮区面板
JPanel leftPanel = new JPanel();
panel.add(leftPanel, BorderLayout.WEST);
leftPanel.setBorder(new TitledBorder("Button Area"));
leftPanel.setBackground(Color.GREEN);// 设置左边按钮面板的背景颜色为绿色

// 设置按钮
button1 = new JRadioButton("Show Tips", false);
button2 = new JRadioButton("Clear Tips", true);// 默认选中
ButtonGroup buttonGroup = new ButtonGroup();
buttonGroup.add(button1);
buttonGroup.add(button2);
box = new JComboBox<String>(items);
button3 = new JButton("Start");
button1.setBackground(Color.CYAN);
button2.setBackground(Color.CYAN);
button3.setBackground(Color.CYAN);

// 创建右边按钮区面板
JPanel rightPanel = new JPanel();
panel.add(rightPanel, BorderLayout.EAST);
rightPanel.setBorder(new TitledBorder("Current State"));
rightPanel.setBackground(Color.GREEN);
rightPanel.setLayout(new GridLayout(1, 2));
name = new JTextField("Picture's name: 雾里看花");
step = new JTextField("Current step: 0");
name.setEditable(false);
step.setEditable(false);

// 将按钮添加到左右面板中
leftPanel.add(button1);
leftPanel.add(button2);
leftPanel.add(new JLabel("  Please choose a picture:"));
leftPanel.add(box);
leftPanel.add(button3);
rightPanel.add(name);
rightPanel.add(step);
}

// 添加图片界面
public void addPreviewPicture()
{
JPanel panel2 = new JPanel();
panel2.setLayout(new GridLayout(1, 2));
picturePuzzle = new PicturePuzzleArea();
picturePuzzle.setBorder(new TitledBorder("Picture Puzzle's Area:"));
panel2.add(picturePuzzle, BorderLayout.WEST);
picturePreview = new PicturePreviewArea();
picturePreview.setBorder(new TitledBorder("Picture Preview's Area:"));
panel2.add(picturePreview, BorderLayout.EAST);
this.add(panel2, BorderLayout.CENTER);
}
}


PicturePreviewArea.java

package com.remoa.picturepuzzle;

import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JPanel;

public class PicturePreviewArea extends JPanel
{
private static final long serialVersionUID = 1L;

@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
String filename = "Picture\\" + PicturePuzzleArea.pictureNum + ".jpg";
ImageIcon icon = new ImageIcon(filename);
Image image = icon.getImage();
g.drawImage(image, 20, 20, 460, 520, this);
}
}


PicturePuzzleArea.java

package com.remoa.picturepuzzle;

import java.awt.Color;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class PicturePuzzleArea extends JPanel implements MouseListener
{
private static final long serialVersionUID = 1L;
// 静态成员变量
public static int pictureNum = 1;// 图片序号
public static int stepNum = 0; // 步数
// 非静态成员变量
private Cell[] cell;// 小方格
private boolean hasAddActionListener = false;// 是否为小方格添加了点击监听事件
private Rectangle nullCell;// 空方格

public PicturePuzzleArea()
{
this.setLayout(null);
cell = new Cell[16];
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
int num = i * 4 + j + 1;
ImageIcon icon = new ImageIcon("Picture\\" + pictureNum + "_0" + num + ".gif");
cell[num - 1] = new Cell(icon);
cell[num - 1].setLocation(j * 115 + 20, i * 130 + 20);// 确定小方格的位置
this.add(cell[num - 1]);// 将小方格添加到拼图区
}
}
this.remove(cell[15]);
nullCell = new Rectangle(345 + 20, 390 + 20, 115, 130);
}

public void reloadPictureAddTips()
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
int num = i * 4 + j;
ImageIcon icon = new ImageIcon("Picture\\" + pictureNum + "_0"
+ (num + 1) + ".gif");
cell[num].setIcon(icon);
cell[num].setText(Integer.toString(num + 1));
cell[num].setForeground(Color.RED);
cell[num].setHorizontalTextPosition(this.getX() / 2);
cell[num].setVerticalTextPosition(this.getY() / 2);
}
}
}

public void reloadPictureClearTips()
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
int num = i * 4 + j;
ImageIcon icon = new ImageIcon("Picture\\" + pictureNum + "_0"
+ (num + 1) + ".gif");
cell[num].setIcon(icon);
cell[num].setText(null);
}
}
}

// 点击start后打乱小方格
public void start()
{
// 鼠标点击监听
if (!hasAddActionListener)// 如果没有监听。则添加事件监听
{
for (int i = 0; i < 15; i++)
{
cell[i].addMouseListener(this);
}
hasAddActionListener = true;
}
// 小方格位置移动,判断第一个小方格距离左上角较近时,进行方格与空方格互换,如果第一个小方格在左上角
// 四个位置方格内,就不断进行循环,进行方格与空方格位置的互换
while (cell[0].getBounds().x <= 135 && cell[0].getBounds().y <= 150)
{
// 获取空方格的位置
int nullx = nullCell.getBounds().x;
int nully = nullCell.getBounds().y;
// 随机产生一个方向,使空方格随机与某个方向小方格进行互换
// 产生一个0到3之间的随机数,对应移动
int direction = (int) (Math.random() * 4);// 0\1\2\3
switch (direction)
{
case 0:// 空方格左移,左侧小方格右移
nullx -= 115;
cellMove(nullx, nully, "RIGHT");
break;
case 1:// 空方格右移,右侧小方格左移
nullx += 115;
cellMove(nullx, nully, "LEFT");
break;
case 2:// 空方格上移,上侧小方格下移
nully -= 130;
cellMove(nullx, nully, "DOWN");
break;
case 3:// 空方格下移,下侧小方格上移
nully += 130;
cellMove(nullx, nully, "UP");
break;
default:
break;
}
}
}

// 方格移动,三个参数分别为空方格x坐标,空方格y坐标,小方格要移动的方向
public void cellMove(int x, int y, String direction)
{
for (int i = 0; i < 15; i++)
{
if (cell[i].getBounds().x == x && cell[i].getBounds().y == y)
{
// 当前方格移动
cell[i].move(direction);
// 空方格移动
nullCell.setLocation(x, y);
break;
}
}
}

@Override
public void mouseClicked(MouseEvent e)
{

}

@Override
public void mousePressed(MouseEvent e)
{
// 获取点击的是哪个小方格
Cell button = (Cell) e.getSource();
// 获取当前小方格的x,y坐标
int clickX = button.getBounds().x;
int clickY = button.getBounds().y;
// 获取空方格的x,y坐标
int nullX = nullCell.getBounds().x;
int nullY = nullCell.getBounds().y;
// 对比,进行位置交换
if (clickX == nullX && clickY == nullY - 130)
{
button.move("Down");
}
else if (clickX == nullX && clickY == nullY + 130)
{
button.move("UP");
}
else if (clickX == nullX + 115 && clickY == nullY)
{
button.move("LEFT");
}
else if (clickX == nullX - 115 && clickY == nullY)
{
button.move("RIGHT");
}
else
{
return;
}
// 更新空方格位置
nullCell.setLocation(clickX, clickY);
// 拼图区重新绘制
this.repaint();
// 步数更新
stepNum++;
PictureMainFrame.step.setText("Current step: " + stepNum);
// 判断游戏结束条件
if (this.isFinish())
{
JOptionPane.showMessageDialog(this, "Well done!!!\nStep use: "
+ stepNum);
for (int i = 0; i < 15; i++)
{
cell[i].removeMouseListener(this);
}
hasAddActionListener = false;
}
}

// 判断当前游戏是否完成,根据坐标判断
private boolean isFinish()
{
for (int i = 0; i < 15; i++)
{
int x = cell[i].getBounds().x;
int y = cell[i].getBounds().y;
if (((x - 20) / 115 + (y - 20) / 130 * 4) != i)
{
return false;
}
}
return true;
}

@Override
public void mouseReleased(MouseEvent e)
{

}

@Override
public void mouseEntered(MouseEvent e)
{

}

@Override
public void mouseExited(MouseEvent e)
{


}
}


Cell .java

package com.remoa.picturepuzzle;

import javax.swing.Icon;
import javax.swing.JButton;

public class Cell extends JButton
{
private static final long serialVersionUID = 1L;

public Cell(Icon icon)
{
super(icon);
this.setSize(115, 130);
}

public Cell(String text, Icon icon)
{
super(text, icon);
this.setSize(115, 130);
this.setHorizontalTextPosition(CENTER);
this.setVerticalTextPosition(CENTER);
}

// 当前方格的移动
public void move(String direction)
{
switch (direction)
{
case "UP":
this.setLocation(this.getBounds().x, this.getBounds().y - 130);
break;
case "DOWN":
this.setLocation(this.getBounds().x, this.getBounds().y + 130);
break;
case "RIGHT":
this.setLocation(this.getBounds().x + 115, this.getBounds().y);
break;
case "LEFT":
this.setLocation(this.getBounds().x - 115, this.getBounds().y);
break;
default:
break;
}
}
}


Graphics 类是所有图形上下文的抽象基类,允许应用程序在组件(已经在各种设备上实现)以及闭屏图像上进行绘制。 

 因为较久没用Java了,所以有些生疏,查了下jdk帮助文档,稍微总结了一下。

1void setLocation(int x, int y):将组件移动到新位置。

来自Container的方法

2)void setResizable(boolean resizable):设置此窗体是否可由用户调整大小

来自Frame的方法

3)void setTitle(String title):将此窗体的标题设置为指定字符串

来自Frame的方法

4)void setVisible(boolean b):根据参数b的值显示或隐藏此Window

来自Window的方法

5)void setSize(int width, int height):调整组件的大小,使其宽度为width,高度为height

来自Window的方法

6)GridLayout(int rows, int colomns):创建具有指定行数和列数的网格布局。

来自GridLayout的构造方法

7)TitledBorder(Border border, String title):创建具有指定边框和标题的TitledBorder实例。

来自TitledBorder的构造方法

8)void setBorder(Border border):设置此组件的边框。

来自JComponent的方法

9)void setHorizontalTextPosition(int textPosition):设置文本相对于图标的水平位置。

来自AbstractButton的方法

10)abstract boolean(Image image, int x, int y, int width, int height, ImageObserver observer):绘制指定图像中已缩放到适合指定矩形内部的图像。

来自Graphics的方法 


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值