Java basic stage project - jigsaw puzzle game (including explanation and source code)

statement

This project is a stage project based on java. This project involves basic grammar, object-oriented knowledge, such as grammar foundation such as judgment, loop, array, string, collection, etc.; object-oriented such as encapsulation, inheritance, polymorphism, abstraction Classes, interfaces, inner classes, etc... are all involved. This project involves a lot of content, as a beginner, you can string together the previous knowledge very well. This project is a good choice for practicing and reviewing the previous basic knowledge

game show

insert image description hereinsert image description here

material acquisition

Note: Each picture in this material is divided into 15 parts, each picture is square, and the length and width are 105 pixels
Link: https://pan.baidu.com/s/16maOd105xKqrWZSd6IScig?pwd=1234
Extraction code: 1234

game window

For the game window, we mainly use the JFrame class provided by Java. This class can provide us with a window. We can set the size, position, and whether to display, etc. for this window. The following is the appearance of the interface. All the business behind
insert image description here
us The logic must be implemented in this window, the following is the implemented code:

JFrame jf = new JFrame();
jf.setSize(400, 400);
jf.setVisible(true);

JFrame is a class provided by Java, so we can directly use JFrame to create objects. The setSize() method in it is to set the size of the window, and the unit is pixel; what needs to be noted here is that it is not possible to execute after setting the size Appears, JFrame hides the interface window by default, we need to use the setVisible() method to display it, true is to display, otherwise false is to hide the period

In the game, we need three interfaces to display, namely: game interface, login interface, and registration interface

So we need to create three JFrame objects, here we need to think about a question: Do we create a new class file, then create three JFrame objects in the main method, and then write all the business logic in the main method? The obvious result is NO , Big NO, special NO, will more than a thousand lines of code be written in one main method by then, and there will be a BUG by then, and I don’t know where it is. So I suggest three categories, namely game interface, login interface, and registration interface. Then we create a new class and use the main method to execute our game. In the main method, create three window class objects for Call methods, such as setting the window size and so on. In this way, if we need to do business logic in that window, we can just go to the corresponding class to do it. The general idea is as follows:
This is the game program execution entry:

import ui.GameFrame;
import ui.LoginJFrame;
import ui.RegisterJFrame;

public class App {
    
    
    public static void main(String[] args) {
    
    
        //表示程序的启动入口
        new GameFrame();

        new LoginJFrame();

        new RegisterJFrame();
    }
}

The following is the GameFrame (game interface) class.
Here I use an empty parameter structure to set the window size and display interface, so that when we create a GameFrame object in the main method, we will call the GameFrame empty parameter structure to set the interface, so that We don't need to set it in the main method

package ui;
import javax.swing.*;

public class GameFrame extends JFrame {
    
    

    public GameFrame(){
    
    
        this.setSize(603, 680);
        this.setVisible(true);
    }
}

The following is the LoginFrame (login interface) class,
which is the same as the GameFrame (game interface) class

package ui;
import javax.swing.*;
public class LoginJFrame extends JFrame {
    
    

    public LoginJFrame(){
    
    
    
        this.setSize(488, 430);
        this.setVisible(true);
    }
}

The following is the RegisterFrame (registration interface) class, and
the idea is the same as that of the GameFrame (game interface) class

package ui;
import javax.swing.*;
public class RegisterJFrame extends JFrame {
    
    

    public RegisterJFrame(){
    
    
        this.setSize(488, 500);
        this.setVisible(true);
    }
}

After the general framework is built, we only need to build the corresponding business logic in the corresponding class. Almost all the business logic behind us is implemented in these three windows.

window settings

After we display the game window, we need to set the game window accordingly, so as to give us a better game experience and visual effects. Next, we need to set the following functions and codes for the game interface: 1. Game
Title
Game The title is the name of our game, generally written on the upper left of the game interface, the effect is as shown in the figure below The
insert image description here
title setting uses the method of JFrame, the code is as follows:

//设置界面的标题
this.setTitle("拼图游戏单机版 V1.0");

2. The function of sticking to the top of the main interface of the game
must be well understood by everyone, that is, when we open other software, sticking to the top allows us to still be displayed on the top layer when we click on other applications. Here we will use one in JFrame method

//设置界面置顶
//盖住其他所有软件
this.setAlwaysOnTop(true);

3. The center of the main interface of the game
The center of the game interface means that when we open the game, the interface always appears in the middle of our computer screen. The method is as follows:

//设置界面居中
this.setLocationRelativeTo(null);

Since this method needs to pass a component parameter, here we only need to fill in a null
4. Set the game shutdown mode
In the game shutdown mode, JFrame provides us with a shutdown method

//设置游戏的关闭模式
this.setDefaultCloseOperation(3);

This method can pass a parameter of type int. This method has four closing modes, corresponding to the numbers 0, 1, 2, and 3; the four closing modes can be viewed by entering the source code of this method. Here I only say that the number 3 corresponds to Shutdown mode: When we close one of the windows, the virtual machine will stop running. It can be understood that as long as I close one of the game windows, the other login windows and registration windows will be closed, and the virtual machine will stop running

Note: this represents the class where this is located. Since we have inherited the three window classes from JFrame, we can directly use this to call the parent class method

menu construction

A game is indispensable is the menu, we re-game, re-login and so on will be displayed in the menu, the following figure is the style of the game menu Before we create such a menu, we must first understand
insert image description here
Java to us Provided JMenuBar class, JMenu class and JMenuItem class, I will use a few pictures below to let you understand the relationship between these three types
insert image description here
insert image description here
After understanding these three types, we need to connect these three types and put them into GameFrame. The following is the implementation Steps:
1. First create JMenuBar
2. Then create JMenu
3. Then create JMenuItem
4. Put JMenuItem into JMenu
5. Put JMenu into JMenuBar
6. Finally add JMenuBar to the entire JFrame interface.

The following is the code implementation:

	//初始化菜单
    public void initJMenuBar(){
    
    
        //创建整个的菜单对象
        JMenuBar jMenuBar = new JMenuBar();

        //创建菜单上面的两个选项的对象(功能  关于我们)
        JMenu functionJMenu = new JMenu("功能");
        JMenu aboutJMenu = new JMenu("关于我们");

        //创建选项下面的条目对象
        JMenuItem replayItem = new JMenuItem("重新游戏");
        JMenuItem reLoginItem = new JMenuItem("重新登录");
        JMenuItem closeItem = new JMenuItem("关闭游戏");

        JMenuItem accountItem = new JMenuItem("公众号");

        //将每一个选项下的条目添加到选项当中
        functionJMenu.add(replayItem);
        functionJMenu.add(reLoginItem);
        functionJMenu.add(closeItem);

        aboutJMenu.add(accountItem);

        //将菜单里面的两个选项添加到菜单中
        jMenuBar.add(functionJMenu);
        jMenuBar.add(aboutJMenu);


        //给整个界面设置菜单
        this.setJMenuBar(jMenuBar);
    }

Here I construct the initialization menu as a method, and then call it directly in the empty parameter structure of the GameFrame to achieve the following effects:
insert image description here
You can also use your imagination to add other menus to the menu bar.
The following is the structure and code of my current GameFrame class

public class GameFrame extends JFrame {
    
    

    public GameFrame(){
    
    

        //初始化界面
        initJFrame();

        //初始化菜单
        initJMenuBar();

        //让界面显示出来,建议放到最后
        this.setVisible(true);
    }

    //初始化界面
    public void initJFrame(){
    
    
        //设置界面的宽高
        this.setSize(603, 680);

        //设置界面的标题
        this.setTitle("拼图游戏单机版 V1.0");

        //设置界面置顶
        //盖住其他所有软件
        this.setAlwaysOnTop(true);

        //设置界面居中
        this.setLocationRelativeTo(null);

        //设置游戏的关闭模式
        this.setDefaultCloseOperation(3);
    }


    //初始化菜单
    public void initJMenuBar(){
    
    
        //创建整个的菜单对象
        JMenuBar jMenuBar = new JMenuBar();

        //创建菜单上面的两个选项的对象(功能  关于我们)
        JMenu functionJMenu = new JMenu("功能");
        JMenu aboutJMenu = new JMenu("关于我们");

        //创建选项下面的条目对象
        JMenuItem replayItem = new JMenuItem("重新游戏");
        JMenuItem reLoginItem = new JMenuItem("重新登录");
        JMenuItem closeItem = new JMenuItem("关闭游戏");

        JMenuItem accountItem = new JMenuItem("公众号");

        //将每一个选项下的条目添加到选项当中
        functionJMenu.add(replayItem);
        functionJMenu.add(reLoginItem);
        functionJMenu.add(closeItem);

        aboutJMenu.add(accountItem);

        //将菜单里面的两个选项添加到菜单中
        jMenuBar.add(functionJMenu);
        jMenuBar.add(aboutJMenu);


        //给整个界面设置菜单
        this.setJMenuBar(jMenuBar);
    }
}

add pictures

After the window and menu are roughly built, we can now try to add pictures to the main window. Since the game window is in the GameFrame window, the subsequent business logic is also completed in the GameFrame class. Before adding pictures,
we Re-understand the game window The
insert image description here
game window here is actually divided into three parts
1. The title part
2. The menu part
3. The hidden container part
The hidden container part here already exists when we create the JFrame object, so We don't need to recreate the object, we can just use this.getContentPane() method to call it, and then use it to call the add() method to add pictures to it. If there is no special requirement, it will be placed in the positive In the center, if we want to place it in another location, we must turn off its default switch. To turn it off, we can use the following method

//取消默认的居中放置,只有取消了才会按照XY轴的形式添加组件
this.setLayout(null);

Since the hidden container is generated when the JFrame object is created, we can use this setLayout method in initFrame(), the initialization interface, and later we can place the image in the hidden container in the XY axis without default placed in the middle

After we cancel the default centering method of the hidden container, we can add pictures next

Adding pictures in JFrame is not simply putting the picture address directly into JFrame, but using ImageIcon and JLabel classes. The
following is the implementation step
1. We need to create an ImageIcon object first, which is equivalent to the picture we want to place. The parameter passed can be the image address
2. Create a JLabel class to store our ImageIcon object, which is our picture. This JLabel is a management container container that can store pictures and text, etc. 3. Use the
object created by the JLabel class to specify the picture The position, that is, the XY axis, here we will use the setBounds method of JLabel, the parameters we pass here are (x, y, width, height), that is, the XY axis and width and height of the image are set, and the XY axis here is not a right angle For the coordinate system, the origin is in the upper left corner of the JFrame window. The following figure can give you a better understanding
insert image description here
4. Finally, add the object created by JLabel to the hidden container of JFrame

Below we use the code to achieve the above function

    //初始化图片
    public void initImage(){
    
    

        //创建一个图片ImageIcon对象
        ImageIcon icon = new ImageIcon("D:\\Java Code\\puzzlegame\\image\\animal\\animal3\\1.jpg");
        //创建一个JLabel的对象(管理容器)
        JLabel jLabel = new JLabel(icon);
        //指定图片位置
        jLabel.setBounds(0, 0 , 105, 105);
        //把管理容器添加到界面中
        this.getContentPane().add(jLabel);
    }

Here I built a method in the GameFrame class, and then called it in the empty parameter construction of the GameFrame class

After writing in this way, the effect should be like this.
insert image description here
Because the parameters in the setBounds method we set are x = 0, y = 0; that is, they are placed at the origin. Here we need to pay attention to the coordinates corresponding to the upper left corner of the picture, and also That is, the coordinates of the picture are the coordinates corresponding to the upper left corner of the picture . Obviously, the result is correct.

When we know how to add pictures to JFrame, let's add other pictures

I know what you're thinking, stop!!!, you don't really want to write the above code a dozen times to add all the pictures, right? The answer is NO!!! If you really want to
try
it, it's not impossible, when When you add 3 pictures, look at the code at this time, do you find any rules? In order to make it easier for everyone to see, here is the code after I added three pictures

        //创建一个JLabel的对象(管理容器)放入ImageIcon对象
        JLabel jLabel1 = new JLabel(new ImageIcon("D:\\Java Code\\puzzlegame\\image\\animal\\animal3\\1.jpg"));
        //指定图片位置
        jLabel1.setBounds(0, 0, 105, 105);
        //把管理容器添加到界面中
        this.getContentPane().add(jLabel1);

        //创建一个JLabel的对象(管理容器)放入ImageIcon对象
        JLabel jLabel2 = new JLabel(new ImageIcon("D:\\Java Code\\puzzlegame\\image\\animal\\animal3\\2.jpg"));
        //指定图片位置
        jLabel2.setBounds(105, 0, 105, 105);
        //把管理容器添加到界面中
        this.getContentPane().add(jLabel2);

        //创建一个JLabel的对象(管理容器)放入ImageIcon对象
        JLabel jLabel3 = new JLabel(new ImageIcon("D:\\Java Code\\puzzlegame\\image\\animal\\animal3\\3.jpg"));
        //指定图片位置
        jLabel3.setBounds(210, 0, 105, 105);
        //把管理容器添加到界面中
        this.getContentPane().add(jLabel3);

For my convenience here, I directly put the created ImageIcon object into the parameters of creating the JLabel object

Here we need to carefully observe these three pieces of code and tell me if I have found any rules?
We can find that every time a picture is added, only the position of the picture and the address of the picture have changed, especially when the position of the picture changes, it still meets a rule , that is, the x-axis of each row of pictures is added 105 one by one, that is to say, the first x of the first row is 0, the second is 105, the third is 210... and so on, the nth of the first row Zhang’s x is 105 * (n - 1), and y is always 0; the second line, like the first line, is y becomes 105, and the third line’s y is 210...and so on, the first line The y of n rows is 105 * (n - 1);

With the above ideas, we should now think of loops, because we have four rows and four columns, we can loop four times with rows, and then loop four times with columns, so we can use loop nesting, an outer loop An inner loop to add pictures, the following is a code demonstration:

    public void initImage(){
    
    

        int number = 1;
        //外循环 --- 四行
        for (int i = 0; i < 4; i++) {
    
    
            //内循环 --- 一行的四张图片
            for (int j = 0; j < 4; j++) {
    
    
                //创建一个图片ImageIcon对象
                //创建一个JLabel的对象(管理容器)放入ImageIcon对象
                JLabel jLabel = new JLabel(new ImageIcon("D:\\Java Code\\puzzlegame\\image\\animal\\animal3\\" + number + ".jpg"));
                //指定图片位置
                jLabel.setBounds(105 * j, 105 * i, 105, 105);
                //把管理容器添加到界面中
                this.getContentPane().add(jLabel);

                //number自增表示图片变化
                number++;
            }
        }
    }

I wrote this function in the initImage() method in the GameFrame class, and then called it in the empty parameter construction

As you can see in the above code, the outer loop is used to represent the number of rows, and the inner loop is used to represent the number of columns. This nested loop roughly means that when I start the loop, i = 0 represents the first row, and then j represents the number of columns, j Gradually increasing means that the number of columns is gradually increasing. The x shown in the setBounds method is gradually increasing, and it is gradually increasing to 105, and y is exactly 0, which just meets our picture placement rule. After the first line of pictures is added, i automatically Increment means the second row, and then execute the inner loop, add 4 pictures in the second row, and then continue to loop until all the pictures in the picture are added

Some people will ask what the number means, here I want to remind again, for the convenience of adding the name of the picture, we try to set it in the following form
Note: Here I divide a picture into 15 parts and put it into the JFrame, You can’t put a whole picture
insert image description here
here. When we create the ImageIcon object and pass the address, we can use a number to gradually increase to represent all the pictures, and add all the pictures to the container so that we can
understand the meaning of the number, which is used as an address Value, add the corresponding picture to the container, when writing the number into the address, remember to write "+number+", don't write the number directly, so that we can get the following results. The last picture is missing because
insert image description here
I Divide a picture into 15 parts. When the loop executes to i = 3, j = 3, there is no corresponding picture, and a blank picture is displayed. Later, we need a blank position to move the picture

Shuffle the picture order

Now that we have figured out how to add pictures to JFrame, the next thing we have to do is to scramble the order of the pictures. After all, it is a jigsaw puzzle game, which itself is a picture that scrambles the order. Let us move and restore it. If we want to scramble the order of the
pictures , we used an int type number variable to continuously increase, and our pictures are put in one by one. Of course, our picture names must be set regularly. Since our pictures are added according to the value of number, and number The value is added from 1 to 16 in order, so if we break the number order, can we break the order of the pictures? Next, we will try

To disrupt the order of 1-16, the easiest way is to set a one-dimensional array with a length of 16, and then exchange the index to interrupt the order. The following is the code for implementation

		//创建一个一维数组
        int[] Arr = {
    
    0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};

        Random r = new Random();
        //遍历数组,将索引进行交换
        for (int i = 0; i < Arr.length; i++) {
    
    
            int index = r.nextInt(Arr.length);

            int temp = Arr[i];
            Arr[i] = Arr[index];
            Arr[index] = temp;
        }

        //遍历一维数组
        for (int i = 0; i < Arr.length; i++) {
    
    
            System.out.print(Arr[i] + " ");
        }

What needs to be noted here is why I don't press 1-16 for a one-dimensional array, but 0-15, because my picture name is only 1-15, and the extra 0, that is, when 0 is recognized, If it is not found in the material, it will be automatically empty, that is, a blank picture, which is the white frame when we move the picture

The final output result:
insert image description here
Obviously, the order is completely disrupted. After the order is disrupted, can it be directly put into the initialization image method? No, no, no, we need to make the image index more elegant , since the puzzle is displayed in 4 × 4, why doesn't our index also display in 4 × 4

4 × 4 index arrangement The first thing that comes to mind should be a two-dimensional array, so now we only need to convert the one-dimensional array into a two-dimensional array, we can use loop nesting to express, and gradually convert the one-dimensional array Add the elements inside, the following is the implemented code:

		//将一维数组添加到二维数组中
        int[][] newArr = new int[4][4];

        int index = 0;
        for (int i = 0; i < 4; i++) {
    
    
            for (int j = 0; j < 4; j++) {
    
    
                newArr[i][j] = Arr[index];
                index++;
            }
        }

        //遍历二维数组
        for (int i = 0; i < newArr.length; i++) {
    
    
            for (int j = 0; j < newArr[i].length; j++) {
    
    
                System.out.print(newArr[i][j] + " ");
            }
            System.out.println();
        }

The final output result (one-dimensional array and two-dimensional array)
insert image description here
finally we only need to substitute the data of this two-dimensional array into the method of initializing the image.
Note: the creation of the two-dimensional array is best written in the member position of the GameFrame class. Here I write it in the initialization data method for the convenience of display, because the two-dimensional array we need to use in the initialization image method, if written in the member position, we can use it directly, so this initialization data method is equivalent to giving Two-dimensional array assignment, the method of initializing the picture can directly use the data in the two-dimensional array

Here's how to use a two-dimensional array in the initialize image method to shuffle the order of the images

		//外循环 --- 四行
        for (int i = 0; i < 4; i++) {
    
    
            //内循环 --- 一行的四张图片
            for (int j = 0; j < 4; j++) {
    
    
                //获取加载当前图片的序号
                int num = newArr[i][j];

                //创建一个图片ImageIcon对象
                //创建一个JLabel的对象(管理容器)放入ImageIcon对象
                JLabel jLabel = new JLabel(new ImageIcon("D:\\Java Code\\puzzlegame\\image\\animal\\animal3\\" + num + ".jpg"));
                //指定图片位置
                jLabel.setBounds(105 * j, 105 * i, 105, 105);
                //把管理容器添加到界面中
                this.getContentPane().add(jLabel);

            }
        }

We used number to call the image address before, but now we call it with the disturbed value in the two-dimensional array. It happens that there is a loop nest here, so we can directly use num to get the value of the two-dimensional array. That's why I had to convert the one-dimensional array into a two-dimensional array earlier.
The final result is like this.
insert image description here
The result is indeed in line with our expectations, and it is completely disrupted compared with the previous picture of the husky.

Beautify the interface

After we mess up the order of the pictures, we can start to beautify the interface. Our main beautification of the game interface is to add a game background image, add a side span to the image, and move the image and the background image to the middle and lower positions (multiple First try, the middle and lower position is the best)
1. Move the position of the picture

//指定图片位置
jLabel.setBounds(105 * j + 83, 105 * i + 134, 105, 105);

The above is the code in the nested loop when adding a picture, that is, to adjust the position of the picture. You can debug the best-looking position by yourself. I chose to move 83 pixels to the right as a whole, that is, x+83; and then move down as a whole 134 pixels, that is, the position of y+134 is the best

2. Add game background image
Adding the game background image is still the method of adding pictures, but there is one very important point: the
picture added first is at the top, and the picture added later is at the bottom , which may be contrary to other languages, so please pay attention here , so the code to add a background image should be written after the cycle of adding images, and within the initImage() method, the following is the code implementation:

//添加背景图片
//创建ImageIcon对象
ImageIcon bg = new ImageIcon("image\\background.png");
//创建JLabel容器对象
JLabel backgound = new JLabel(bg);
backgound.setBounds(40,40,508,560);
//把背景图片添加到界面当中
this.getContentPane().add(backgound);

The background image has been tried, and it looks best when placed at x = 40, y = 40

3. Adding picture borders
Adding picture borders does not require us to find the borders and add them in. JLabel is to store pictures, and the text container provides us with the setBorder() method. We can use it directly. The following code is written in adding
pictures within the nested loop of

JLabel jLabel = new JLabel(new ImageIcon("image\\animal\\animal3\\" + num + ".jpg"));
//指定图片位置
jLabel.setBounds(105 * j + 83, 105 * i + 134, 105, 105);
//给图片添加边框
//0:让图片凸起来
//1:让图片凹下去
jLabel.setBorder(new BevelBorder(1));
//把管理容器添加到界面中
this.getContentPane().add(jLabel);

The setBorder() method can pass a BevelBorder object. There are two options for the parameters inside, one is 0, the other is 1, 0 is to add a border that makes the picture convex, and 1 is to add a border that makes the picture concave. You can try it yourself, I personally think it looks better if it is concave

After completing the above beautification code, the result is that the picture below
insert image description here
looks much better than before

event listener

A simple understanding of event monitoring is that java recognizes that you have made various operations on the mouse and keyboard to respond, just like in this game, we press the ↑ key, and the picture below the blank will move up, like this, and Java recognizes that you have pressed the ↑ key and then moves up the blank picture below, which is called event monitoring.
Regarding event monitoring, java gives us three interfaces, which can be used directly, namely ActionListener (action monitoring), MouseListener (mouse monitoring ), KeyListener (keyboard monitoring), in which action monitoring is a simplified version of the other two, which can only recognize the left mouse button click and space keyboard, mouse monitoring can recognize click, press and hold, release, draw in, and draw Out, the keyboard monitor can recognize the pressing and holding, typing, and releasing. You can check the information on this aspect. I won’t go into details here. Here we only use the release of the keyboard monitor.

Now let's start to practice.
Since the event listener is an interface, we directly call the interface in the GameFrame class

public class GameFrame extends JFrame implements KeyListener

After calling the interface, all methods of the interface must be rewritten. There are three methods in total:

    @Override
    public void keyTyped(KeyEvent e) {
    
    

    }

    @Override
    public void keyPressed(KeyEvent e) {
    
    
        
    }

    @Override
    public void keyReleased(KeyEvent e) {
    
    
        
    }

Here we mainly use the keyReleased method, that is, release, that is, it will be recognized only after I press and release, and it will not be recognized if I hold it down
. How do we move pictures?
When we add pictures, we add pictures according to the index. Then we move the pictures according to the index. As long as we give the data after the movement to the initialization picture method, it can be realized. Move the picture, so the logic we roughly implement is
1. Get the position of the blank picture.
The following is the code to add the one-dimensional array to the two-dimensional array in the initialization data method. Here we mainly judge that when the index is 0, it is blank. When the picture is taken, its index is obtained. I set an x ​​and y in the member position to record the blank picture position (since the keyboard monitor override method also uses x and y), here x and y y is actually the i and j of the two-dimensional array we set up before, if you list it as a 4 × 4 table, it is actually rows and columns

        //将一维数组添加到二维数组
        int index = 0;
        for (int i = 0; i < 4; i++) {
    
    
            for (int j = 0; j < 4; j++) {
    
    
                if(Arr[index] == 0){
    
    
                    x = i;
                    y = j;
                }else{
    
    
                    newArr[i][j] = Arr[index];
                }
                index++;
            }
        }

2. Realize the movement logic in the keyReleased method.
The principle of image movement is actually to exchange the blank image with the surrounding images. We know the position of the blank image before. Now we mainly realize the exchange
here. int code = e.getKeyCode(); The interface provides a method for identifying keys. It will name almost all the keys on the keyboard. The name is an int type number, so we can directly judge the code later, and then perform the corresponding exchange. The exchange is the exchange of indexes, for example Move down, that is, the blank picture is exchanged with the above picture, move the blank picture up, the x of the blank picture remains unchanged, the y of the blank picture will be - 1, the picture to be exchanged is moved down, that is, the x of the picture to be exchanged No change, y needs to be + 1; the position of the swapped picture is swapped with the blank picture, so just set its index to 0. Finally, don’t forget that after the blank picture is moved, its position also changes, for example, to Moving down means that the blank picture moves up, so x-- , x and y should always indicate the position of the blank picture

    @Override
    public void keyReleased(KeyEvent e) {
    
    
        //对上,下,左,右进行判断
        //左:37, 右:39, 上:38, 下:40
        int code = e.getKeyCode();
        
        if(code == 37){
    
    
            System.out.println("向左移动");
            if(y == 3){
    
    
                return;
            }

            newArr[x][y] = newArr[x][y + 1];
            newArr[x][y + 1] = 0;
            y++;
            //调用方法按最新的方法加载图片
            initImage();


        }else if(code == 38){
    
    
            System.out.println("向上移动");
            if(x == 3){
    
    
                //表示方块已经已经在最下方了,他的下面没有图片再能移动了
                return;
            }

            //把空白方块下方的数字赋值给空白方块
            newArr[x][y] = newArr[x + 1][y];
            newArr[x + 1][y] = 0;
            x++;
            //调用方法按最新的方法加载图片
            initImage();


        }else if(code == 39){
    
    
            System.out.println("向右移动");

            if(y == 0){
    
    
                return;
            }

            newArr[x][y] = newArr[x][y - 1];
            newArr[x][y - 1] = 0;
            y--;
            //调用方法按最新的方法加载图片
            initImage();


        }else if(code == 40){
    
    
            System.out.println("向下移动");
            if(x == 0){
    
    
                return;
            }

            newArr[x][y] = newArr[x - 1][y];
            newArr[x - 1][y] = 0;
            x--;
            //调用方法按最新的方法加载图片
            initImage();
        }
    }

3. The display and refresh of the effect after moving.
After we complete the above code, we will find that it will not move after execution. Is it wrong? Actually, it is not. As I said before, we called the initImage method after modifying the index , the effect after the move at this time will be placed on the main interface again, but it will be covered by the first initialization picture, that is, the picture added first is on the top , and the picture added later is on the bottom . Don't forget , so we need to implement a clearing of the content of the previous main interface in front of the initImage method, so that the content after moving will be displayed every time we move

//清空原本已经出现的所有图片
//清空以后才会出现移动后的图片,不然被覆盖在下面了
this.getContentPane().removeAll();

The above code should be written in initImage(), and it should be written at the front,
and then it is refreshed, which can be written at the bottom of the initImage() method

//刷新界面
this.getContentPane().repaint();

4. BUG repair
After all the above codes are written, the game can actually be played. However, during the game, we found that when the blank picture is at the top, we press the ↓ key, and the program will throw an exception, although it can be played normally. , but it’s still a little uncomfortable. What’s the matter?
In fact, we didn’t consider the position of the blank picture when we moved the picture. If it’s in the boundary, if we insist on letting it move outside the boundary, it will definitely not be able to move. At this time, an exception will be thrown, and it is actually very easy to fix. It is only used in the four key judgment statements in the keyReleased method to judge whether x and y are on the boundary. If it is, do not execute the mobile code, and just exit , the implementation code is in 2. Implement the movement logic in the keyReleased method

view full image

When we play games, sometimes we don’t know what the complete picture of the game is and don’t know how to move the puzzle, so we need to realize the function of pressing the shortcut key to display the complete picture. Let’s take pressing the A key as an example, when When we press the A button and hold on, the complete picture of the current puzzle will appear on the main interface of the game, and the interface we are playing will be displayed again when we send it away. The following is the general idea:
1. Since keyboard monitoring
is displayed by pressing the A key, we must use keyboard monitoring. When we implemented the logic of moving the keyboard, we have rewritten all the methods of keyboard monitoring, so we can directly Use the rewriting method
2.
Press the A button and hold it to display the complete picture, and release it to return to the game interface. Here we need to write the code in the keyPressed() and keyReleased() methods , when we press it, the content in the keyPressed() method will be executed, and when we release it, the content in the keyReleased() method will be executed
3. Clear the interface and display the picture
. When it is pressed, all the pictures of our game will be clear, and the complete picture will be displayed in the main interface. When we release it, we can directly call the initImage() method to display our previous game content

The following is the code implementation

    @Override
    public void keyPressed(KeyEvent e) {
    
    
        int code = e.getKeyCode();
        if(code == 65){
    
    
            //把界面中的所有图片全部清除
            this.getContentPane().removeAll();
            //加载第一张完整的图片
            JLabel all = new JLabel(new ImageIcon("image\\animal\\animal3\\all.jpg"));
            all.setBounds(83, 134, 420, 420);
            this.getContentPane().add(all);

            //添加背景图片
            JLabel background = new JLabel(new ImageIcon("image\\background.png"));
            background.setBounds(40,40,508,560);
            //把背景图片添加到界面当中
            this.getContentPane().add(background);

            //刷新界面
            this.getContentPane().repaint();
        }
    }

The above paragraph is to recognize when we press the A key, clear all the code of the picture, and refresh

else if(code == 65){
    
    
      initImage();

The above paragraph is the else if() in the keyReleased() method, because the judgment was added when the button was judged to move the picture, so now it is enough to write else if() directly behind, and then directly call the initImage() method, This method will clear all previous content and redisplay the game image and background image

Image path optimization

We can find that the pictures we use are fixed, the paths are fixed, and will not change. Changing pictures also requires rewriting all the paths in the class, which is very troublesome. Let’s optimize it now, so that it will be more convenient when we change it in the future. Convenient, what I want is to add a string-type path variable to the member position of the class, and then call path directly in the method that needs to use the path later. When modifying later, just modify the path directly. The following is the
code accomplish

String path = "image\\animal\\animal3\\";

Then just change it to path where you need the path

JLabel jLabel = new JLabel(new ImageIcon(path + num + ".jpg"));
JLabel all = new JLabel(new ImageIcon(path + "all.jpg"));

In this way, if you want to modify the picture in the future, you can directly modify the path

cheat code

Everyone knows the cheat codes here, so I won’t go into details, here are the codes directly

else if(code == 87){
    
    
            //作弊码
            //重写给二维数组赋值,初始化二维数组
            newArr = new int[][]{
    
    
                    {
    
    1,2,3,4},
                    {
    
    5,6,7,8},
                    {
    
    9,10,11,12},
                    {
    
    13,14,15,0},
            };
            //调用上面的二维数组进行初始化图片,直接通关
            initImage();
        }

Still use else if() in the keyReleased() method, here I set the W key (corresponding to 87), we directly initialize the two-dimensional array, that is, set the two-dimensional array according to the order of customs clearance, and then directly call initImage() The method can display the appearance after customs clearance, as shown in the figure below
insert image description here

judge victory

Judging victory is actually very similar to cheat codes. It is to identify whether your current two-dimensional array data is the same as the data of the complete picture, that is, it is the same as the two-dimensional array of cheat codes. If it is the same, the victory icon will be displayed. If it is not the same, continue to 1
. Define a correct two-dimensional array win and set it at the member position, because we need to use this data in multiple methods

//定义一个二维数组,存储正确的数据
    int[][] win = {
    
    
            {
    
    1,2,3,4},
            {
    
    5,6,7,8},
            {
    
    9,10,11,12},
            {
    
    13,14,15,0}
    };

2. Before loading the picture, first judge whether the numbers in the two-dimensional array are the same as those in the win array, because the functions of loading pictures and displaying the game interface are all in the initImage() method. If we want to continue the game, we must continue to display In the game interface, it is necessary to first identify whether there is a victory

if(victory()){
    
    
            //显示胜利的图标
            JLabel winJLabel = new JLabel(new ImageIcon("D:\\Java Code\\puzzlegame\\image\\win.png"));
            winJLabel.setBounds(203, 283, 197, 73);
            this.getContentPane().add(winJLabel);
        }

3. If you win, the correct icon will be displayed directly, otherwise the incorrect icon will be displayed. If there is no victory, the code in the initImage() method will continue to be executed to display the game puzzle
4. BUG repair. When we wrote it all, we found that when we win, the correct icon is displayed, but the picture can still move, I think when I succeed, the game can't move, unless we quit or play the next round.
This requires us to judge in the keyReleased() method. If we win, we will exit the method directly. After exiting, it means that the code we used to judge the key cannot be executed, that is, the picture will not move again.

//判断游戏是否胜利,如果胜利,此方法需要直接结束,不能再执行下面的移动代码了
        if(victory()){
    
    
            //结束方法
            return;
        }

The above code should be written at the top of the keyReleased() method, because below this method is the code for judging the up, down, left, and right keys. After winning, these keys cannot be used, so we must judge on them. End the method directly, do not execute the following judgment button, if there is no victory, it will continue to execute the following judgment until it wins

Statistical steps

In order to increase the fun of the game, we can add a counter next to the game to display the number of steps, and add one every time we move, so that we can compare who has the lowest number of steps. It is still a very interesting logic of counting
steps The implementation is relatively simple. We can define a counter variable at the member position, and then add the counter variable to self-increment when judging the movement key in the keyReleased() method of keyboard monitoring, and finally display the counter content in the initImage() method. OK, the following is the code implementation:

//定义变量用来统计步数
int step = 0;

Define calculator variable at member position

//添加计数器到主界面中
JLabel stepCount = new JLabel("步数:" + step);
stepCount.setBounds(50, 30, 100, 20);
this.getContentPane().add(stepCount);

In the initImage() method, the function of displaying the counter is realized.
Finally, add step++ at the bottom of the code for judging the up, down, left, and right keys to realize each step. The upper left corner of the game interface displays the number of moving steps, as shown in the figure below
insert image description here

Menu Bar

re-game

To restart the game, you need to click Replay in the menu bar, and the order of the pictures will be disturbed again. Since it is to
click the data in the menu bar to restart, then we need to add monitoring events to the data in these menus. The easiest way is to give them With ActionListener, there are only mouse clicks and keyboard spaces, so we need to bind event listeners to these items in the initJMenuBar() method.
Before calling ActionListener, we need to call the ActionListene interface

public class GameFrame extends JFrame implements KeyListener, ActionListener

Then add events to the entry

//给条目绑定事件
replayItem.addActionListener(this);
reLoginItem.addActionListener(this);
closeItem.addActionListener(this);
accountItem.addActionListener(this);

Note that before we rewrite the ActionListener interface method, we need to move the previously defined item object, namely JMenuItem, to the member position, because we need to call the item object in the ActionListener interface rewrite method. The following is the content of the ActionListener interface rewrite
method
here Judging the code executed when we click the replayItem of the entry object of the re-game

    @Override
    public void actionPerformed(ActionEvent e) {
    
    
        //获取当前被点击的条目对象
        Object obj = e.getSource();
        //判断
        if(obj == replayItem){
    
    
            System.out.println("重新游戏");

            //计数器清零
            step = 0;
            //再次打乱二维数组中的数据
            initData();
            //重新加载图片
            initImage();

It should be noted here that the counter reset must be placed above the initialization data and the initialization picture, because the counter step will be used in the initialization picture, if it is not cleared above, the counter will continue to use the counter data of the previous game

re-register

To re-login, we can click Re-login in the menu bar. Since we have added event monitoring for re-login, we only need to judge in the method rewritten by the ActionListener interface. The following is the code implementation

else if(obj == reLoginItem){
    
    
            System.out.println("重新登录");
            //关闭当前的游戏界面
            this.setVisible(false);
            //打开登录界面
            new LoginJFrame();

close the game

Closing the game is very simple. In the rewrite method, judge whether to click to close the game. If you click, just exit the virtual machine.

else if(obj == closeItem){
    
    
            System.out.println("关闭游戏");
            System.exit(0);

about Us

About us, we can display our QR code, that is, when the player clicks About Us, a bullet box will pop up to display our QR code picture. The bullet box is a new interface, and it needs to be resized and centered , top, whether to display, etc., are similar in nature to JFrame. The following is the code implementation

else if(obj == accountItem){
    
    
            System.out.println("公众号");

            //创建一个弹框对象
            JDialog jDialog = new JDialog();
            //创建一个管理图片的容器对象JLabel
            JLabel jLabel = new JLabel(new ImageIcon("image\\about.png"));
            //设置位置和宽高
            jLabel.setBounds(0,0,258,258);
            //把图片添加到弹框当中
            jDialog.getContentPane().add(jLabel);
            //给弹框设置大小
            jDialog.setSize(344, 344);
            //让弹框置顶
            jDialog.setAlwaysOnTop(true);
            //让弹框居中
            jDialog.setLocationRelativeTo(null);
            //弹框不关闭则无法操作下面的界面
            jDialog.setModal(true);
            //让弹框显示出来
            jDialog.setVisible(true);

        }

The following is the rendering
insert image description here

game optimization

We have finished writing the general content of the game. In order to increase the fun of the game, we can add a few more pictures and classify the pictures. Players can choose pictures, such as pictures of beauties, animals, and sports. There are good materials in the materials I gave Several, this effect is relatively simple after we realize the previous initialization picture, we can add a few more options to the re-game menu, such as beauty, animal, sports, etc., and then click the corresponding option to randomly select the corresponding Play the game with the picture, the number of steps is reset to 0, and the picture is random

The general process of realization:
1. Redefine a JMenu called re-game, then add JMenuItem of picture type to JMenu (re-game), and finally add JMenu to JMenu (function) to realize the multi-level menu 2.
Give Add action monitoring events to the picture type, judge the clicked button, and implement corresponding operations on the corresponding button. For example, if I click on a beauty, I will randomly select a picture from the beauty picture, initialize the data, initialize the picture, and refresh. At this time, we The previously defined path variable is used, as long as the value of the path is modified in the judgment, that is, the image address, the image type can be selected. 3. Before
initializing the data and initializing the image, define the step as 0, so that the number of steps is cleared to 0

Summarize

I didn’t write the login interface and registration interface here. If you are interested, you can study it yourself. There are more codes. You can try to write it yourself. You can also add interesting gameplay to make the game more diverse.

the code

package ui;

import javax.swing.*;
import javax.swing.border.BevelBorder;
import javax.xml.crypto.Data;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;

public class GameFrame extends JFrame implements KeyListener, ActionListener {
    
    
    //JFrame 界面,窗体
    //子类也可以表示界面和窗体
    //那么以后GameFrame就表示游戏的主界面
    //以后跟游戏相关的所有逻辑都写在这个类中

    Random r = new Random();

    //创建选项下面的条目对象
    JMenuItem girlItem = new JMenuItem("美女");
    JMenuItem animalItem = new JMenuItem("动物");
    JMenuItem sportItem = new JMenuItem("运动");
    JMenuItem reLoginItem = new JMenuItem("重新登录");
    JMenuItem closeItem = new JMenuItem("关闭游戏");

    JMenuItem accountItem = new JMenuItem("公众号");


    //定义变量用来统计步数
    int step = 0;

    //定义一个二维数组,存储正确的数据
    int[][] win = {
    
    
            {
    
    1,2,3,4},
            {
    
    5,6,7,8},
            {
    
    9,10,11,12},
            {
    
    13,14,15,0}
    };


    String path = "image\\animal\\animal3\\";

    //记录空白方块在数组中的位置
    int x = 0;
    int y = 0;

    //创建一个二维数组供初始化数据方法添加数据,和供初始化图片方法使用
    int[][] newArr = new int[4][4];


    public GameFrame(){
    
    

        //初始化界面
        initJFrame();

        //初始化菜单
        initJMenuBar();

        //初始化数据(打乱图片顺序的数据)
        initData();

        //初始化图片
        initImage();

        //让界面显示出来,建议放到最后
        this.setVisible(true);
    }

    //初始化界面
    private void initJFrame(){
    
    
        //设置界面的宽高
        this.setSize(603, 680);

        //设置界面的标题
        this.setTitle("拼图游戏单机版 V1.0");

        //设置界面置顶
        //盖住其他所有软件
        this.setAlwaysOnTop(true);

        //设置界面居中
        this.setLocationRelativeTo(null);

        //设置游戏的关闭模式
        this.setDefaultCloseOperation(3);

        //取消默认的居中放置,只有取消了才会按照XY轴的形式添加组件
        this.setLayout(null);

        //给整个界面添加键盘监听事件
        this.addKeyListener(this);
    }


    //初始化菜单
    private void initJMenuBar(){
    
    
        //创建整个的菜单对象
        JMenuBar jMenuBar = new JMenuBar();

        //创建菜单上面的两个选项的对象(功能  关于我们)
        JMenu functionJMenu = new JMenu("功能");
        JMenu aboutJMenu = new JMenu("关于我们");
        JMenu replayJMenu = new JMenu("重新游戏");


        //将图片类型添加到重新游戏菜单中
        replayJMenu.add(girlItem);
        replayJMenu.add(animalItem);
        replayJMenu.add(sportItem);

        //将每一个选项下的条目添加到选项当中
        functionJMenu.add(replayJMenu);
        functionJMenu.add(reLoginItem);
        functionJMenu.add(closeItem);

        aboutJMenu.add(accountItem);

        //给条目绑定事件
        reLoginItem.addActionListener(this);
        closeItem.addActionListener(this);
        accountItem.addActionListener(this);
        girlItem.addActionListener(this);
        animalItem.addActionListener(this);
        sportItem.addActionListener(this);

        //将菜单里面的两个选项添加到菜单中
        jMenuBar.add(functionJMenu);
        jMenuBar.add(aboutJMenu);


        //给整个界面设置菜单
        this.setJMenuBar(jMenuBar);
    }


    //初始化图片
    //添加图片的时候,需要按照二维数组中管理的数据添加图片
    private void initImage(){
    
    

        //清空原本已经出现的所有图片
        //清空以后才会出现移动后的图片,不然被覆盖在下面了
        this.getContentPane().removeAll();


        if(victory()){
    
    
            //显示胜利的图标
            JLabel winJLabel = new JLabel(new ImageIcon("D:\\Java Code\\puzzlegame\\image\\win.png"));
            winJLabel.setBounds(203, 283, 197, 73);
            this.getContentPane().add(winJLabel);
        }

        //添加计数器到主界面中
        JLabel stepCount = new JLabel("步数:" + step);
        stepCount.setBounds(50, 30, 100, 20);
        this.getContentPane().add(stepCount);


        //添加背景图片
        //先加载的图片在上方,后加载的图片在下方

        //外循环 --- 四行
        for (int i = 0; i < 4; i++) {
    
    
            //内循环 --- 一行的四张图片
            for (int j = 0; j < 4; j++) {
    
    
                //获取加载当前图片的序号
                int num = newArr[i][j];

                //创建一个图片ImageIcon对象
                //创建一个JLabel的对象(管理容器)放入ImageIcon对象
                JLabel jLabel = new JLabel(new ImageIcon(path + num + ".jpg"));
                //指定图片位置
                jLabel.setBounds(105 * j + 83, 105 * i + 134, 105, 105);
                //给图片添加边框
                //0:让图片凸起来
                //1:让图片凹下去
                jLabel.setBorder(new BevelBorder(1));
                //把管理容器添加到界面中
                this.getContentPane().add(jLabel);

            }
        }

        //添加背景图片
        //创建ImageIcon对象
        ImageIcon bg = new ImageIcon("image\\background.png");
        //创建JLabel容器对象
        JLabel backgound = new JLabel(bg);
        backgound.setBounds(40,40,508,560);
        //把背景图片添加到界面当中
        this.getContentPane().add(backgound);


        //刷新界面
        this.getContentPane().repaint();
    }



    //初始化数据
    private void initData(){
    
    
        //打乱一个数组里数字的顺序,并构成二维数组

        int[] Arr = {
    
    0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};

        Random r = new Random();
        //遍历数组进行交换
        for (int i = 0; i < Arr.length; i++) {
    
    
            int index = r.nextInt(Arr.length);

            int temp = Arr[i];
            Arr[i] = Arr[index];
            Arr[index] = temp;
        }


        //将一维数组添加到二维数组
        int index = 0;
        for (int i = 0; i < 4; i++) {
    
    
            for (int j = 0; j < 4; j++) {
    
    
                if(Arr[index] == 0){
    
    
                    x = i;
                    y = j;
                }

                newArr[i][j] = Arr[index];

                index++;
            }
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {
    
    

    }

    @Override
    public void keyPressed(KeyEvent e) {
    
    
        int code = e.getKeyCode();
        if(code == 65){
    
    
            //把界面中的所有图片全部清除
            this.getContentPane().removeAll();
            //加载第一张完整的图片
            JLabel all = new JLabel(new ImageIcon(path + "all.jpg"));
            all.setBounds(83, 134, 420, 420);
            this.getContentPane().add(all);

            //添加背景图片
            JLabel background = new JLabel(new ImageIcon("image\\background.png"));
            background.setBounds(40,40,508,560);
            //把背景图片添加到界面当中
            this.getContentPane().add(background);

            //刷新界面
            this.getContentPane().repaint();
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
    
    
        //判断游戏是否胜利,如果胜利,此方法需要直接结束,不能再执行下面的移动代码了
        if(victory()){
    
    
            //结束方法
            return;
        }


        //对上,下,左,右进行判断
        //左:37, 右:39, 上:38, 下:40
        int code = e.getKeyCode();
        if(code == 37){
    
    
            System.out.println("向左移动");
            if(y == 3){
    
    
                return;
            }

            newArr[x][y] = newArr[x][y + 1];
            newArr[x][y + 1] = 0;
            y++;
            //每移动一次,计数器自增一次
            step++;
            //调用方法按最新的方法加载图片
            initImage();


        }else if(code == 38){
    
    
            System.out.println("向上移动");
            if(x == 3){
    
    
                //表示方块已经已经在最下方了,他的下面没有图片再能移动了
                return;
            }

            //逻辑:
            //把空白方块下方的数字往上移动
            //x , y 表示空白方块
            //x+1 , y表示空白下方的方块

            //把空白方块下方的数字赋值给空白方块
            newArr[x][y] = newArr[x + 1][y];
            newArr[x + 1][y] = 0;
            x++;
            //每移动一次,计数器自增一次
            step++;
            //调用方法按最新的方法加载图片
            initImage();

        }else if(code == 39){
    
    
            System.out.println("向右移动");

            if(y == 0){
    
    
                return;
            }

            newArr[x][y] = newArr[x][y - 1];
            newArr[x][y - 1] = 0;
            y--;
            //每移动一次,计数器自增一次
            step++;
            //调用方法按最新的方法加载图片
            initImage();

        }else if(code == 40){
    
    
            System.out.println("向下移动");
            if(x == 0){
    
    
                return;
            }

            //逻辑
            //把空白方块往下移
            newArr[x][y] = newArr[x - 1][y];
            newArr[x - 1][y] = 0;
            x--;
            //每移动一次,计数器自增一次
            step++;
            //调用方法按最新的方法加载图片
            initImage();
        }else if(code == 65){
    
    
            initImage();
        }else if(code == 87){
    
    
            //作弊码
            //重写给二维数组赋值,初始化二维数组
            newArr = new int[][]{
    
    
                    {
    
    1,2,3,4},
                    {
    
    5,6,7,8},
                    {
    
    9,10,11,12},
                    {
    
    13,14,15,0},
            };
            //调用上面的二维数组进行初始化图片,直接通关
            x = 3;
            y = 3;
            initImage();
        }
    }


    //判断data数组中的数据是否跟win数组中相同
    //如果全部相同,返回true,否则返回false
    public boolean victory(){
    
    
        for (int i = 0; i < newArr.length; i++) {
    
    
            for (int j = 0; j < newArr[i].length; j++) {
    
    
                if(newArr[i][j] != win[i][j]){
    
    
                    //只要有一个数据不一样则返回false
                    return false;
                }
            }
        }
        //循环结束表示数组遍历比较完毕,完全一样则返回true
        return true;
    };

    @Override
    public void actionPerformed(ActionEvent e) {
    
    
        //获取当前被点击的条目对象
        Object obj = e.getSource();
        //判断
        if(obj == reLoginItem){
    
    
            System.out.println("重新登录");
            //关闭当前的游戏界面
            this.setVisible(false);
            //打开登录界面
            new LoginJFrame();
        }else if(obj == closeItem){
    
    
            System.out.println("关闭游戏");
            System.exit(0);
        }else if(obj == accountItem){
    
    
            System.out.println("公众号");

            //创建一个弹框对象
            JDialog jDialog = new JDialog();
            //创建一个管理图片的容器对象JLabel
            JLabel jLabel = new JLabel(new ImageIcon("image\\about.png"));
            //设置位置和宽高
            jLabel.setBounds(0,0,258,258);
            //把图片添加到弹框当中
            jDialog.getContentPane().add(jLabel);
            //给弹框设置大小
            jDialog.setSize(344, 344);
            //让弹框置顶
            jDialog.setAlwaysOnTop(true);
            //让弹框居中
            jDialog.setLocationRelativeTo(null);
            //弹框不关闭则无法操作下面的界面
            jDialog.setModal(true);
            //让弹框显示出来
            jDialog.setVisible(true);
        }else if(obj == girlItem){
    
    
            System.out.println("美女图片");
            //随机获取图片
            int num = r.nextInt(1, 14);
            path =  "image\\girl\\girl"+ num + "\\";

            //初始化步数
            step = 0;
            //初始化数据
            initData();
            //初始化图片
            initImage();
            //刷新
            this.repaint();

        }else if(obj == animalItem){
    
    
            System.out.println("动物图片");
            int num = r.nextInt(1, 9);
            path =  "image\\animal\\animal"+ num + "\\";
            //初始化步数
            step = 0;
            //初始化数据
            initData();
            //初始化图片
            initImage();
            //刷新
            this.repaint();

        }else if(obj == sportItem){
    
    
            System.out.println("运动图片");
            int num = r.nextInt(1, 11);
            path =  "image\\sport\\sport"+ num + "\\";
            //初始化步数
            step = 0;
            //初始化数据
            initData();
            //初始化图片
            initImage();
            //刷新
            this.repaint();
        }
    }
}

The following is the main program

import ui.GameFrame;
import ui.LoginJFrame;
import ui.RegisterJFrame;

public class App {
    
    
    public static void main(String[] args) {
    
    

        //表示程序的启动入口

        //如果我们想要开启一个界面,就创建谁的对象就可以了
        new GameFrame();

        //new LoginJFrame();

        //new RegisterJFrame();

        //
    }
}

Guess you like

Origin blog.csdn.net/m0_64041302/article/details/128689399