【java】16宫格拼图游戏项目

     这个游戏虽然不是很难,但是从中能帮我巩固很多多东西,比如接口的实现、类的继承等这些java面向对象的特点知识我都在写这个项目的过程中有了更深的理解。

     这个游戏的机制就是监听到键盘中的上下左右方向键来对图块来进行移动,最后按顺序拼成一张完整的图片。在游戏开始的时候我还添加 了登录功能,输入正确账号密码以及验证码就可以进入游戏了。如果输入错误,也会有相应的弹窗反馈。

     在游戏界面中我添加了一个JMenubar,里面有着像重新开始、关闭游戏、重新登录、随机切换图片等功能,每一个功能我都添加了相应的事件。

    但是,可能是我比较懒的缘故,有些知识还没有完全理解,有些功能我没有写完,比如注册这个功能,我没能将注册后的User的账号密码一直保持在之前创建的Arraylist中。

    下面是这个项目的源码:

这个是游戏本体的源码

package GameUI;

import javax.swing.*;
import javax.swing.border.BevelBorder;
import javax.swing.border.Border;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
import GameUI.Loginframe;
public class Gameframe extends JFrame implements KeyListener, ActionListener {
    //一些成员变量
    int[][] arr1 = new int[4][4];
    //我获取到的空白格子在二维数组中的位置
    int x = 0;
    int y = 0;
   //用来判断游戏是否完成的按顺序排列的二维数组
    int[][] win = {
            {1, 2, 3, 4},
            {5, 6, 7, 8},
            {9, 10, 11, 12,},
            {13, 14, 15, 16}
    };
    //创建一个int类型的变量来记录我们移动的步数
    int step=0;
    //把那些功能的条目放到成员变量的位置中,方便其他方法调用
    JMenuItem restart = new JMenuItem("重新开始");
    JMenuItem end = new JMenuItem("结束游戏");
    JMenuItem resign =new JMenuItem("重新登录");
    JMenuItem aboutme = new JMenuItem("关于作者");
    JMenuItem sfunction = new JMenuItem("特别内容");
    JMenuItem random=new JMenuItem("随机");
    JMenuItem sss=new JMenuItem("特殊");
    //用来切换图片的整型
    int v=1;



    //界面的构造方法
    public Gameframe() {
        int v=1;
        jiemian();
        function();
        miximage();
        image(arr1,v);

        //让界面显示
        this.setVisible(true);

    }

    private void miximage() {
        int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
        Random r = new Random();
        for (int i = 0; i < arr.length; i++) {
            int temp = arr[i];
            int x = r.nextInt(16);
            arr[i] = arr[x];
            arr[x] = temp;
        }

        int n = 0;
        for (int i = 0; i < arr1.length; i++) {
            for (int i1 = 0; i1 < 4; i1++) {
                arr1[i][i1] = arr[n];
                //获取空白的位置
                if (arr[n] == 16) {
                    x = i;
                    y = i1;
                }
                n++;
            }
        }
        //遍历二维数组看一下是否打乱
        for (int i = 0; i < arr1.length; i++) {
            for (int i1 = 0; i1 < arr1[i].length; i1++) {
                System.out.printf("%4d", arr1[i][i1]);
            }
            System.out.println();
        }
        System.out.println(x + "," + y);
    }

    private void image(int arr1[][],int v) {
        this.getContentPane().removeAll();
        //显示步数
        JLabel Step=new JLabel("步数:"+step);
        Step.setBounds(0,0,60,40);
        this.getContentPane().add(Step);
        //每次调用绘制图片时,都要判断是否是完成了
        if (win()){
            ImageIcon win = new ImageIcon("images/win.png");
            JLabel Win = new JLabel(win);
            Win.setBounds(0,0,600,400);

            this.getContentPane().add(Win);
            this.getContentPane().repaint();
        }
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                //打乱的二维数组的不同索引对应的不同的图片序号,这样就可以将图片打乱了
                int n = arr1[i][j];
                //初始化图片
                ImageIcon image = new ImageIcon("images\\test"+v+"\\t" + n + ".jpg");
                //jlabel是一个管理的容器,将imageicon加进去才能对其进行操作
                JLabel j1 = new JLabel(image);
                //设置图片的位置
                j1.setBounds(155 * j + 100, 135 * i + 140, 155, 135);
                j1.setBorder(new BevelBorder(0));
                //将图片添加到窗口上
                this.getContentPane().add(j1);
                //刷新
                this.getContentPane().repaint();

            }

        }


    }

    private void function() {
        //界面中的功能
        JMenuBar bar = new JMenuBar();
        JMenu function = new JMenu("功能");
        JMenu about = new JMenu("关于");
        JMenu special = new JMenu("隐藏功能");
        JMenu change=new JMenu("更换图片");
        /*JMenuItem restart = new JMenuItem("重新开始");
        JMenuItem end = new JMenuItem("结束游戏");
        JMenuItem resign =new JMenuItem("重新登录");
        JMenuItem aboutme = new JMenuItem("关于作者");
        JMenuItem sfunction = new JMenuItem("特别内容");*/
        bar.add(function);
        bar.add(about);
        bar.add(special);
        function.add(restart);
        function.add(end);
        function.add(resign);
        function.add(change);
        about.add(aboutme);
        special.add(sfunction);
        function.add(change);
        change.add(random);
        change.add(sss);
       //给这些功能绑定事件
        restart.addActionListener(this);
        end.addActionListener(this);
        aboutme.addActionListener(this);
        sfunction.addActionListener(this);
        resign.addActionListener(this);
        sss.addActionListener(this);
        random.addActionListener(this);
        this.setJMenuBar(bar);
    }

    private void jiemian() {
        //界面的大小和标题
        this.setSize(850, 880);
        this.setTitle("Kinroy的拼图游戏 v1.0");
        //让界面一直在所有窗口的上方
        this.setAlwaysOnTop(true);
        //选择关闭方式
        this.setDefaultCloseOperation(3);
        //让界面出现在中央
        this.setLocationRelativeTo(null);
        //键盘监听,反馈我们的操作
        setLayout(null);
        this.addKeyListener(this);
    }


    @Override
    //
    public void keyTyped(KeyEvent e) {

    }

    @Override
    //按下键盘后
    public void keyPressed(KeyEvent e) {
        int o = e.getKeyCode();
        System.out.println(o);
        if (o == 82) {
            System.out.println("显示完整图片");
            this.getContentPane().removeAll();
            ImageIcon All = new ImageIcon("images/test"+v+"/All.jpg");
            JLabel all = new JLabel(All);
            all.setBounds(100, 140, 623, 543);
            this.getContentPane().add(all);
            this.getContentPane().repaint();

        }
    }

    @Override
    //松开键盘后
    public void keyReleased(KeyEvent e) {
        //如果完成了拼图,将无法对拼图进行任何控制操作
        if (win()){
            return;
        }
        //上键对应的编号是38,下为40,左为37,右为39
        int o = e.getKeyCode();
/*
        System.out.println(o);
*/
        switch (o) {
            case 38:
                System.out.println("向上移动");
                if (x == 3) {
                    return;
                }
                arr1[x][y] = arr1[x + 1][y];
                arr1[x + 1][y] = 16;
                x++;
                step++;
                image(arr1,v);
                break;
            case 40:
                System.out.println("向下移动");
                if (x == 0) {
                    return;
                }
                arr1[x][y] = arr1[x - 1][y];
                arr1[x - 1][y] = 16;
                step++;
                x--;
                image(arr1,v);
                break;
            case 37:
                System.out.println("向左移动");
                if (y == 3) {
                    return;
                }
                arr1[x][y] = arr1[x][y + 1];
                arr1[x][y + 1] = 16;
                y++;
                step++;
                image(arr1,v);
                break;
            case 39:
                System.out.println("向右移动");
                if (y == 0) {
                    return;
                }
                arr1[x][y] = arr1[x][y - 1];
                arr1[x][y - 1] = 16;
                y--;
                step++;
                image(arr1,v);
                break;
            case 82:
                image(arr1,v);
                break;
            case 87:
                System.out.println("一键通关");
                int[][] arr2 = new int[4][4];
                int v = 1;
                for (int i = 0; i < arr2.length; i++) {
                    for (int i1 = 0; i1 < arr2.length; i1++) {
                        arr2[i][i1] = v;
                        v++;
                    }
                }
                arr1=arr2;
                image(arr1,v);
                break;


                /* for (int j = 0; j < arr2.length; j++) {
                    for (int g = 0; g < arr2.length; g++) {
                        System.out.printf("%4d",arr2[j][g]);
                    }
                    System.out.println();
                }*/


        }

    }

    public boolean win() {

        for (int i = 0; i < arr1.length; i++) {
            for (int i1 = 0; i1 < arr1.length; i1++) {
                if (arr1[i][i1] != win[i][i1]) {
                    return false;
                }
            }
        }
        return true;

            /*if (b == 16) {
                this.getContentPane().removeAll();
                ImageIcon win = new ImageIcon("");
                JLabel Win = new JLabel(win);
                Win.setBounds(100, 140, 623, 543);
                this.getContentPane().add(Win);
                this.getContentPane().repaint();
            }*/


    }

    @Override
    public void actionPerformed(ActionEvent e) {
        Object x=e.getSource();
        if (x==restart){
            //重新开始游戏
            step=0;
            System.out.println("游戏重新开始");
            miximage();
            image(arr1,v);
            this.getContentPane().repaint();
        }
        else if (x==end){
           //结束游戏
            System.exit(0);
        }
        else if (x==resign){
            this.setVisible(false);
            new Loginframe();


        }
        else if (x==aboutme){
           //设置关于作者这个功能的弹窗
            JDialog jd=new JDialog();
            JLabel j2=new JLabel(new ImageIcon("images/me.jpg"));
            j2.setBounds(0,0,258,258);
            jd.getContentPane().add(j2);
            jd.setSize(344,344);
            jd.setAlwaysOnTop(true);
            jd.setLocationRelativeTo(null);
            //设置不关闭弹窗就无法进行下一步操作
            jd.setModal(true);
            jd.setVisible(true);
        }
        else if (x==random){
            System.out.println("开始随机出现图片进行拼图游戏");
           step=0;
            Random r=new Random();
            v=r.nextInt(4)+1;
            System.out.println(v);
            miximage();
            image(arr1,v);


        }



    }
}

下面是登录功能的源码:

package GameUI;

import javax.swing.*;
import CodeText.code;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseListener;
import Function.function;

public class Loginframe extends JFrame implements ActionListener {
    //一些成员变量
    JButton sign=new JButton();
    JButton create=new JButton();
    JTextField id=new JTextField();
    JPasswordField pw=new JPasswordField();
    JTextField ct=new JTextField();
    JButton change=new JButton();
    JLabel code=new JLabel();
    //用来存验证码的字符串
    String c="";


    public Loginframe(){
        jiemian();

        view();



        //让窗口显示出来
        this.setVisible(true);
    }

    private void jiemian() {
        this.setSize(400,500);
        this.setTitle("登录");
        //让界面一直在所有窗口的上方
        this.setAlwaysOnTop(true);
        //选择关闭方式
        this.setDefaultCloseOperation(3);
        //让界面出现在中央
        this.setLocationRelativeTo(null);
        this.setAlwaysOnTop(true);
        this.setLayout(null);


    }
    public void view(){
       //添加用户名的输入框
        /*JTextField id=new JTextField();*/
        id.setBounds(120,165,200,30);
        this.getContentPane().add(id);
        //添加密码的输入框
        /*JPasswordField pw=new JPasswordField();*/
        pw.setBounds(120,215,200,30);
        this.getContentPane().add(pw);
        //添加验证码输入框
        /*JTextField ct=new JTextField();*/
        ct.setBounds(120,265,100,30);
        this.getContentPane().add(ct);
        //添加验证码

         c= CodeText.code.getcode();
        code.setText(c);
        code.setBounds(250,210,100,150);
        this.getContentPane().add(code);

        change.setBounds(290,270,70,30);
        change.setText("更换验证码");
        this.getContentPane().add(change);
        //给更换验证码按钮添加事件
        change.addActionListener(this);
        //添加登录按钮
        /*JButton sign=new JButton();*/
        sign.setBounds(90,320,80,40);
        sign.setText("登录");
        this.getContentPane().add(sign);

        //给登录按钮添加事件
        sign.addActionListener(this);
        //添加注册按钮
        /*JButton create=new JButton();*/
        create.setBounds(220,320,80,40);
        create.setText("注册");
        this.getContentPane().add(create);



        //显示加载登录的背景:
        JLabel bg=new JLabel(new ImageIcon("images/backgroud/BG-final.jpg"));
        bg.setBounds(0,0,400,500);
        this.getContentPane().add(bg);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        Object a=e.getSource();
        if (a==sign){
            System.out.println("点击了登录");
            if (ct.getText().equals(c)){
                if (function.check(id.getText(),pw.getText())){
                    new Gameframe();
                    this.setVisible(false);
                }
            }
            else {
                JDialog wrong =new JDialog();
                JLabel j2=new JLabel();
                j2.setText("你输入的验证码错误");
                j2.setBounds(0,0,100,100);
                wrong.getContentPane().add(j2);
                wrong.setSize(200,100);
                wrong.setAlwaysOnTop(true);
                wrong.setLocationRelativeTo(null);
                //设置不关闭弹窗就无法进行下一步操作
                wrong.setModal(true);
                wrong.setVisible(true);
                //验证码刷新
                c=CodeText.code.getcode();
            }

        }
        else if (a==change){
            System.out.println("点击了更换验证码");
            String c1=CodeText.code.getcode();
            System.out.println(c1);
            c=c1;
            code.setText(c);
            this.getContentPane().repaint();

        }
    }
}

生成验证码的工具类的源码:

package CodeText;

import java.util.Random;

public class code {

    static char[]arr1=new char[62];
    public static void make(){
        int n=48;
        for (int i = 0; i < 10; i++) {
            arr1[i]=(char)n;
          n++;
        }
        int n1=65;
        for (int i = 10; i < 36; i++) {
            arr1[i]=(char) n1;
            n1++;
        }
        int n2=97;
        for (int i = 36; i < 62; i++) {
            arr1[i]=(char) n2;
            n2++;
        }

    }
    public static String getcode(){
       make();
        Random r=new Random();
        String code="";
        for (int i = 0; i < 4; i++) {
            int n=r.nextInt(62);
            code=code+arr1[n];
        }
        return code;
    }

}

实现登录界面中的各种功能的源码:

package Function;

import java.util.ArrayList;
import GameUI.Gameframe;

import javax.swing.*;

public class function extends JFrame {
    static ArrayList<User>al=new ArrayList<>();
    //在存储用户的列表中添加用户
    public static void add(User u1){
        al.add(u1);
    }
    public static boolean check(String id,String password){
        for (int i = 0; i < al.size(); i++) {
            if (al.get(i).getId().equals(id)){
                if (al.get(i).getPasswrod().equals(password)){
                    return true;
                }
            }
            JDialog wrong =new JDialog();
            JLabel j1=new JLabel();
            j1.setText("你输入的账号或密码错误");
            j1.setBounds(0,0,100,100);
            wrong.getContentPane().add(j1);
            wrong.setSize(200,100);
            wrong.setAlwaysOnTop(true);
            wrong.setLocationRelativeTo(null);
            //设置不关闭弹窗就无法进行下一步操作
            wrong.setModal(true);
            wrong.setVisible(true);
        }
        return false;
    }
}

最后是定义用户的JavaBean类的源码:

package Function;

public class User {
    private String id;
    private String passwrod;

    public User() {
    }

    public User(String id, String passwrod) {
        this.id = id;
        this.passwrod = passwrod;
    }

    /**
     * 获取
     * @return id
     */
    public String getId() {
        return id;
    }

    /**
     * 设置
     * @param id
     */
    public void setId(String id) {
        this.id = id;
    }

    /**
     * 获取
     * @return passwrod
     */
    public String getPasswrod() {
        return passwrod;
    }

    /**
     * 设置
     * @param passwrod
     */
    public void setPasswrod(String passwrod) {
        this.passwrod = passwrod;
    }

    public String toString() {
        return "User{id = " + id + ", passwrod = " + passwrod + "}";
    }
}

以及程序的入口:

import javax.swing.*;

import Function.User;
import GameUI.Gameframe;
import GameUI.Loginframe;
import CodeText.code;
import Function.function;
public class test  {
    public static void main(String[] args) {
        /*new Gameframe();*/
        //用来测试用的账号
        User u=new User("kinroy06","123456");
        function.add(u);
        //初始化游戏
        new Loginframe();


    }



}

代码中有些地方我没有整理,或许直接看上去会很乱,但是那些用来测试的代码我都注释掉了,所有可以忽略一下吧哈哈哈。

大体结构如上,然后我只添加了4张图片,如果你想添加更多也是可以的。

下面给大家看一下运行的界面吧:

 

 

完成这个小小项目还是可以收获到很多东西的哈哈哈哈。 

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一支猫咔qly

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值