在这里写记录一次拼图游戏的实验,很可惜存在bug,但是也学到一定的知识,有能力的话还请高人解疑。
以下是代码
首先有一个自动切割图片的类,使用时修改目标路径即可
package test;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
public class Test {
private static void splitImage() throws IOException {
String source = "e:/img/1.jpg";
File file = new File(source); // 读入要分解的图片
FileInputStream fis = new FileInputStream(file); // 运用文件字节输入流
BufferedImage image = ImageIO.read(fis);
int rows = 3; // 分解行成 3 块
int cols = 3; // 分解列成 3 列
int littleimgs = rows * cols; // 总共分解成 rows * cols 张小图
// 计算每个小图的宽度和高度
int width = image.getWidth() / cols;
int height = image.getHeight() / rows;
int count = 0;
BufferedImage imgs[] = new BufferedImage[littleimgs];
for (int x = 0; x < rows; x++) {
for (int y = 0; y < cols; y++) {
//设置小图的大小和类型
imgs[count] = new BufferedImage(width, height, image.getType());
//写入图像内容
Graphics2D gr = imgs[count++].createGraphics();
gr.drawImage(image, 0, 0,
width, height,
width * y, height * x,
width * y + width,
height * x + height, null);
gr.dispose();
}
}
// 输出小图
for (int i = 0; i < imgs.length; i++) {
// 分解图片输出位置
ImageIO.write(imgs[i], "jpg", new File("e:/img/1_" + i + ".jpg"));
}
System.out.println("完成分割!");
}
public static void main(String[] args) {
try {
splitImage();
}catch (IOException e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
接下来是拼图的主类
package text11_7;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.TitledBorder;
public class MedleyGame extends JFrame{
private static final long serialVersionUID = 1L;
private int row = 3; // 拼图行数
private int col = 3; // 拼图列数
private int ImgWidth; // 事例图片宽度
private int ImgHeight; // 事例图片高度
private int width; // 小拼图宽度
private int height; // 小拼图高度
private JPanel centerPanel; // 拼图按钮面板
private JButton emptyButton; // 空白按钮对象
public static void main(String[] args) {
try {
MedleyGame frame = new MedleyGame(); // 创建本类的对象
frame.setVisible(true); // 设置窗体可见
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
public MedleyGame() {
super(); // 继承JFrame
setTitle("拼图游戏"); // 窗体标题
setBounds(100, 100, 620, 690); // 设置窗体的显示位置及大小
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 设置关闭窗体是退出程序
final JPanel toPanel = new JPanel(); // 创建面板对象
toPanel.setBorder(new TitledBorder(null, "",
TitledBorder.DEFAULT_JUSTIFICATION,
TitledBorder.DEFAULT_JUSTIFICATION, null, null)); // 为面板添加边框
toPanel.setLayout(new BorderLayout()); // 设置面板采用边界布局
getContentPane().add(toPanel, BorderLayout.NORTH); // 将面板添加到窗体顶部
final JLabel modelLabel = new JLabel(); // 创建显示参考图片的标签对象
modelLabel.setIcon(new ImageIcon("e:/img/1.jpg")); // 设置标签显示的参考图片
toPanel.add(modelLabel, BorderLayout.WEST); // 将标签添加到面板的左侧
final JButton startButton = new JButton(); // 创建"下一局"标签对象
startButton.setText("开始游戏"); // 设置按钮的标签文本
startButton.addActionListener(new StartButtonAction()); // 为按钮添加监听器
toPanel.add(startButton, BorderLayout.CENTER); // 将按钮添加到面板中间
final JButton loadButton = new JButton(); // 创建"下一局"标签对象
loadButton.setText("上传图片"); // 设置按钮的标签文本
loadButton.addActionListener(new LoadButtonAction()); // 为按钮添加监听器
toPanel.add(loadButton, BorderLayout.EAST); // 将按钮添加到面板中间
centerPanel = new JPanel(); // 创建拼图按钮面板对象
centerPanel.setBorder(new TitledBorder(null, "",
TitledBorder.DEFAULT_JUSTIFICATION,
TitledBorder.DEFAULT_POSITION, null, null)); // 为面板添加边框
centerPanel.setLayout(new GridLayout(0, 3)); // 设置拼图按钮面板采用5列的网格布局
getContentPane().add(centerPanel, BorderLayout.CENTER); // 将面板添加到窗体的中间
BufferedImage t = null;
try {
t = ImageIO.read(new File("e:/img/1.jpg")); // 读取文件
ImgWidth = t.getWidth(); // 获取图像宽高
ImgHeight = t.getHeight();
width = ImgWidth/col; // 设置每张小图片宽高
height = ImgHeight/row;
}catch(Exception e){
System.out.println(e);
}
String[][] Img = getSource(); // 获得网格图片的随机摆放顺序
for(int i = 0; i < row; i++) { // 遍历行
for(int j = 0; j < col; j++) { // 遍历列
final JButton button = new JButton(); // 创建拼图按钮对象
button.setName(i + "" + j); // 设置按钮名称
button.setIcon(new ImageIcon(Img[i][j])); // 为按钮设置图片
if(Img[i][j].equals("e:/img/0.jpg")); // 判断是否为空白按钮
emptyButton = button;
button.addActionListener(new ImgButtonAction()); // 为拼图按钮添加监听器
centerPanel.add(button); // 将按钮添加到拼图按钮面板中
}
}
}
private String[][] getSource() {
String[][] Img = new String[row][col]; // 网格图片的正确摆放顺序
for(int i = 0; i < row; i++) {
for(int j = 0; j < col; j++) {
int num = i * col + j;
Img[i][j] = "e:/img/1_" + num + ".jpg";
}
}
return Img;
}
private String[][] reorder() { // 用来获取网格图片的随机摆放顺序
String[][] Img = getSource(); // 网格图片的正确摆放顺序
String[][] RandomImg = new String[row][col]; // 网格图片的随机摆放顺序
for(int i = 0; i < row; i++) {
for(int j = 0; j < col; j++) {
while(RandomImg[i][j] == null) {
int r = (int)(Math.random() * row); // 取随机行
int c = (int)(Math.random() * col); // 取随机列
if(Img[r][c] != null) { // 正确摆放顺序的指定网格不为空
RandomImg[i][j] = Img[r][c];
Img[r][c] = null;
}
}
}
}
return RandomImg;
}
public void check() {
Component[] components = this.getContentPane().getComponents();
for(int i = 0; i < components.length; i++) {
System.out.println(components[i]);
System.out.println(components[i].getClass());
if("javax.swing.JPanel".equals(components[i].getClass().getName())) {
// JButton t = (JButton) components[i];
System.out.println(i+"=");
}
}
this.centerPanel.getComponents();
}
class ImgButtonAction implements ActionListener { // 拼图按钮监听器
public void actionPerformed(ActionEvent e) {
// if(check()) {
// } else {
System.out.println(e);
String emptyName = emptyButton.getName(); // 获取空白按钮的名称
char emptyRow = emptyName.charAt(0); // 获取空白按钮所在的行
char emptyCol = emptyName.charAt(1); // 获取空白按钮所在的列
// System.out.println(emptyName);
JButton clickButton = (JButton) e.getSource(); // 获取被单击按钮对象
String clickName = clickButton.getName(); // 获取被单击按钮的名称
char clickRow = clickName.charAt(0); // 获取被单击按钮所在行
char clickCol = clickName.charAt(1); // 获取被单击按钮所在列
// System.out.println(clickName);
// 判断被单击按钮与空白按钮是否相邻
if(Math.abs(clickRow - emptyRow) + Math.abs(clickCol - emptyCol) == 1) {
// 将被单击按钮的图片移动到空白按钮上
emptyButton.setIcon(clickButton.getIcon());
// 设置被单击的按钮显示空白图片
clickButton.setIcon(new ImageIcon("e:/img/0.jpg"));
emptyButton = clickButton; // 将被单击的按钮设置为空白按钮
// }
}
}
}
class StartButtonAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
String[][] Img = reorder();
int index = 0;
for(int i = 0; i < row; i++) {
for(int j = 0; j < col; j++) {
JButton button = (JButton) centerPanel.getComponent(index++);
button.setIcon(new ImageIcon(Img[i][j]));
if(Img[i][j].equals("e:/img/0.jpg"));
emptyButton = button;
}
}
}
}
class LoadButtonAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
JFileChooser fileChooser = new JFileChooser("e:\\");
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int returnVal = fileChooser.showOpenDialog(fileChooser);
if(returnVal == JFileChooser.APPROVE_OPTION) {
String filePath = fileChooser.getSelectedFile().getAbsolutePath();
System.out.println(filePath);
}
}
}
}
结果截图
点击开始游戏即可,我这段代码有两处bug还没解决,一个就是不能判断拼图结束,还有一个不知道怎么实现点击图片来获取本地图片,进行切割,然后用自己想要的图片来做拼图。。。