JAVA实现拼图游戏

  • Post author:
  • Post category:java


一,设计思路

在这里插入图片描述

二,具体实现

1.设计cell类

package 拼图小游戏;
import javax.swing.*;
import java.awt.*;
public class Cell extends JButton{
    private  int bw ;
    private  int bh ;
    private int place;

    public Cell(Icon icon, int place, int imagewidth, int imagehight)
    {
        this.bw=imagewidth;
        this.bh=imagehight;
        this.setSize(bw,bh);//按钮大小
        this.setIcon(icon);//图标
        this.place = place;//位置
    }
    public void move(Direction dir)
    {
        Rectangle rec = this.getBounds();
        switch (dir)
        {
            case UP:
                this.setLocation(rec.x,rec.y-bh);
                break;
            case DOWN:
                this.setLocation(rec.x,rec.y+bh);
                break;
            case LEFT:
                this.setLocation(rec.x-bw,rec.y);
                break;
            case RIGHT:
                this.setLocation(rec.x+bw,rec.y);
                break;
        }
    }
    public int getX()
    {
        return this.getBounds().x;
    }
    public int getY()
    {
        return this.getBounds().y;
    }
    public int getPlace()
    {
        return place;
    }


}

2.设计Direction类

package 拼图小游戏;

public enum Direction
{
    UP,DOWN,LEFT,RIGHT
}

3.设计GamePanel类

在此类中的outoforder( )函数需要一些数学知识,保证在打乱图片后能够还原。

1、逆序的定义:

逆序是一个与排列相关的概念。

由自然数1,2…,n组成的不重复的每一种有确定次序的排列,称为一个n级排列(简称为排列);或者一般的,n个互不同元素排成一列称为“一个n级排列”。例如,1234和4312都是4级排列,而24315是一个5级排列。

在一个n级排列中,如果一对数的前后位置与大小顺序相反,即前面的数大 于后面的数,那么它们就称为一个“逆序”。

一个排列中逆序的总数就称为这个排列的逆序数。

逆序数为偶数的排列称为偶排列;逆序数为奇数的排列称为奇排列。

如2431中,21,43,41,31是逆序,逆序数是4,为偶排列。

(图形块看做矩阵每一个的元素)图形A与图形B等价<<==>>图形A的排列的逆序数加上0元素行号和列号的奇偶性等于图形B的排列的逆序数加上0元素行号和列号的奇偶性。(同为奇数或者同为偶数都可以还原图片)(0号元素就是空白格)

package 拼图小游戏;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Random;

public class GamePanel extends JPanel implements MouseListener {
    private int row=3 ;
    private int col=3;
    private Cell[] cells = new Cell[row * col];
    private Cell cellblank = null;
    int Imagew;
    int Imageh;

    public GamePanel() {
        super();
        setLayout(null);
        init();
    }

    public void init() {
        int num;
        int w = 0;
        int h = 0;
        BufferedImage src = null;
        BufferedImage splitpic = null;
        ImageIcon icon = null;

        try {
            src = ImageIO.read(new File("D:\\jdk1.8.0_131\\bin\\girl.jpg"));
            //图片路径
            Imagew = src.getWidth();
            Imageh = src.getHeight();

            w = Imagew / col;
            h = Imageh / row;
          //分割后每一小块的长和宽
        } catch (IOException e) {
            e.printStackTrace();
        }
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                num = i * col + j;
                if (num < row * col - 1) {
                    splitpic = src.getSubimage(w * j, h * i, w, h);
                    //getSubimage(1,2,3,4),1,2号确定开始分割的坐标.3,4确定分割图片的宽度和高度
                    icon = new ImageIcon(splitpic);//图像转化为图标
                } else {
                    icon = new ImageIcon("D:\\jdk1.8.0_131\\bin\\blank.png");
                }
                cells[num] = new Cell(icon, num, w, h);//添加图标到每一个button上面
                cells[num].setLocation(w * j, h * i);
            }
        }
           //初始化空白格
        cellblank = cells[row * col - 1];
        for (int i = 0; i < cells.length; i++) {
            this.add(cells[i]);//将每一个按钮添加到当前面板上
            if (i != cells.length - 1) {
                cells[i].addMouseListener(this);//空白格不添加监听
            }
        }
    }

    //打乱图片的顺序
    public void outoforder() {
    //定义两个数组存储产生的随机数,也就是任意两个将要交换的图片的编号
        int index1[] = new int[row * col];
        int index2[] = new int[row * col];
        
     while (true)//利用死循环得到两组满足还原图片的交换序列,存储在index1[]和index2[]中
     {
        Random random = new Random();
        int a[] = new int[col*row];
        //将图片映射到数组a[]中,图片的随机交换,也就是数组的随机交换,(便于算出逆序数)
        int num1 = 0, num2 = 0;
        num1 = (row * col - 1) + (cells[row * col - 1].getX() / (Imagew / col) + cells[row * col - 1].getY() / (Imageh / row));
        //图片没打乱之前算出奇偶性num1
        System.out.println(num1);
        for (int i = 0; i < cells.length; i++) {
            a[i] = i;
        }
        for (int i = 0; i < cells.length; i++) {
            System.out.print(a[i] + " ");
        }
        System.out.println();

        for (int i = 0; i < row * col; i++) {
            index1[i] = random.nextInt(cells.length);
            index2[i] = random.nextInt(cells.length);
            int temp;
            temp = a[index1[i]];
            a[index1[i]] = a[index2[i]];
            a[index2[i]] = temp;
        }//数组进行打乱
        for (int i = 0; i < row * col; i++) {
            System.out.print("index1:" + index1[i] + " ");
        }
        System.out.println();
        for (int i = 0; i < row * col; i++) {
            System.out.print("index2:" + index2[i] + " ");
        }
        for (int i = 0; i < cells.length; i++) {
            if (a[i] == row * col - 1) {
                a[i] = -1;
                num2 = i % col + i / col;
                break;
            }//找到打乱后的空白格的行列,相加
        }
        System.out.println();
        for (int i = 0; i < cells.length; i++) {
            System.out.print(a[i] + " ");
        }
        for (int i = 0; i < cells.length; i++) {
            for (int j = i + 1; j < cells.length; j++) {
                if (a[i] > a[j]) num2++;//算出打乱后的逆序数
            }
        }
        System.out.println();
        System.out.println(num2);
        if ((num1 + num2) % 2 == 0) {
            break;
            //判断是否同为奇or偶
        }
    }
    //同为奇or偶后,将图片位置进行交换,利用上述的两个数组即可打乱且能还原,(这里cell[]之间也要交换)
        for (int i = 0; i < row*col; i++) {
            int x = cells[index1[i]].getX();
            int y = cells[index1[i]].getY();
            int x1 = cells[index2[i]].getX();
            int y1 = cells[index2[i]].getY();
            cells[index1[i]].setLocation(x1, y1);
            cells[index2[i]].setLocation(x, y);

            Cell celltemp;
            celltemp = cells[index1[i]];
            cells[index1[i]] = cells[index2[i]];
            cells[index2[i]] = celltemp;
        }
    }
   //判断拼图成功
    public boolean iswin() {
        for (int i = 0; i < cells.length; i++) {
            int x = cells[i].getX();
            int y = cells[i].getY();
            if ((y / (Imageh / row) * col + x / (Imagew / col)) != cells[i].getPlace())
                return false;
        }
        return true;
    }


    public void mouseClicked(MouseEvent e) {
        Cell cell = (Cell) e.getSource();
        int x = cellblank.getX();
        int y = cellblank.getY();

        if ((x - cell.getX() == Imagew / col) && y == cell.getY()) {
            cell.move(Direction.RIGHT);
            cellblank.move(Direction.LEFT);
        } else if ((x - cell.getX() == -Imagew / col) && y == cell.getY()) {
            cell.move(Direction.LEFT);
            cellblank.move(Direction.RIGHT);
        } else if (cell.getX() == x && (cell.getY() - y == Imageh / row)) {
            cell.move(Direction.UP);
            cellblank.move(Direction.DOWN);
        } else if (cell.getX() == x && (cell.getY() - y == -Imageh / row)) {
            cell.move(Direction.DOWN);
            cellblank.move(Direction.UP);
        }
        if (iswin()) {
            int i = JOptionPane.showConfirmDialog(this, "success,again?", "拼图成功", JOptionPane.YES_NO_OPTION);
            if (i == JOptionPane.YES_OPTION) {
                outoforder();
            }
        }
    }

    @Override
    public void mousePressed(MouseEvent e) {

    }

    @Override
    public void mouseReleased(MouseEvent e) {

    }

    @Override
    public void mouseEntered(MouseEvent e) {

    }

    @Override
    public void mouseExited(MouseEvent e) {

    }


}

4.设计MainJFrame类

package 拼图小游戏;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class MainJFrame extends JFrame{
    public MainJFrame()
    {
        super();
        getContentPane().setLayout(new BorderLayout());
        setTitle("拼图游戏");
        setBounds(300,300,320,400);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
         JPanel panel  = new JPanel();
        getContentPane().add(panel,BorderLayout.NORTH);
        GamePanel gamepanel = new GamePanel();
        getContentPane().add(gamepanel, BorderLayout.CENTER);
         JButton button  =new JButton();
         JButton button1  = new JButton();
        panel.add(button);
        panel.add(button1);
        button.setText("开始");
        button1.setText("结束");
        button.addActionListener(new ActionListener() {
            public void actionPerformed( ActionEvent e) {
                gamepanel.outoforder();
            }
        });
        button1.addActionListener(new ActionListener() {
            public void actionPerformed( ActionEvent e) {
               setVisible(false);
               MainJFrame m1 = new MainJFrame();
               m1.setVisible(true);
            }
        });
    }
    public static void main(String[] args) {
            new MainJFrame();
    }
}

结果截图:

在这里插入图片描述

在这里插入图片描述

参考博客:

https://jiankunking.blog.csdn.net/article/details/18081823

https://blog.csdn.net/angry_youth/article/details/71404651



版权声明:本文为weixin_43563049原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。