Roma
世界已黑白,此人已成仙。

年少轻狂,总以为天下事竭力有为。人事尽时,终感力不能及。

一.界面分析

这个界面可以把它分为3个部分,各自有各自的作用。这三个部分都叫做组件

 

 

 

第一部分叫做JFrame,它是由2个单词来组成的,第一个是前面的J也就是java的意思,后面Frame窗体或者界面的意思,我们写的所有的文字图片都是放在这个窗体里面的,比如像那个统计步数就是放在就是放在这个里面。

中间的这个部分叫做菜单,当我们点击动能的时候,它会弹出下拉框比如说更换图片,可以重新游戏更换一把,或者是重新登陆、关闭游戏。菜单的名字叫JMenuBar,J是Java,Menu菜单的意思,Bar条目的意思。就是说上面的一长条是菜单。

第三部分叫做JLabel,这个JLabel不是图片是一个管理容易,可以管理文字、图片。

左上角这里的步数是一个文字,在写代码的时候我们要先创建一个JLabel管理容器的对象,再把文字放进去,最后再把管理容器JLabel管理容器放进去就可以了。图片也是一样的,先创建一个JLabel管理容器对象,把图片放进去,再把JLabel容器放进去就可以了。JLabel可以理解为一个管理容器。它名字第一个是J是Java的意思,后面Label可以理解为区域容器。

 

  1. 创建界面

创建一个宽683px,高680px的游戏主界面

当我们创建一个JFrame的时候,它就会出现一个窗体。

接下来我们进入IDEA中创建项目,项目的名称为puzzle,创建model名为pullzegame的模块,找到src新建一个包和一个名为APP的类用来表示程序的启动入口,包名为com.puzzlegame.ui,创建1个类主界面GameJFrame在Java中有个类叫做JFrame,用来描述界面的,通过import javax.swing.*;语句将包导入。

让这个类继承JFrame类我们要去创建游戏的主界面,在App类中直接创建GameJFrame对象就可以打开这个界面,可以直接掉用。

 

创建了这个对象之后就表示这个界面有了,界面默认是隐藏的,我们后面需要调用setVisible()方法,参数为true,将界面显示出来。现在设置界面的大小,通过setSize()方法设置他的大小,setSize()方法有两个参数,第一个是宽,第二个是高,然后我们可以输入603,680.它们的单位是像素(px),然后调用setVisible()方法将界面显示出来。

setVisible()方法写在最后。这些设置的代码可以写在一个方法中,在构造方法中去调用这个方法,在创建对象的同时初始化这些信息。在GameJFrame类中创建一个initJFrame()方法,再在GameJFrame这个构造方法中去调用initJFrame()方法。

然后在GameJFrame类initJFrame()方法中设置主界面标题this.setTitle(“拼图游戏 v1.0”);

设置界面置顶this.setAlwaysOnTop(true);

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

设置关闭模式(关闭程序停止运行)this.setDefaultCloseOperation(3);

 

一.菜单制作

在Java中有一个类专门用来描述菜单的类叫JMenuBar,在菜单当中还有很多的选项,每一个选项都对应一个Jmenu类,在菜单当中有3个选项,在代码当中就要创建3个Jmenu的对象。

以功能选项为例,当点击功能选项时,会弹出下拉框,会有多个选项,每一个选项都是一个JmenuItem的对象,单击关于我们也是会弹出选项

 

 

 

  1. 先创建JMenuBar
  2. 再创建JMenu
  3. 再创建JMenuItem
  4. 把JMenuItem放到Jmenu里面
  5. 把JMenu放到JMenuBar里面
  6. 最后把JMenuBar放到JFrame当中

 

在GameJFrame类中创建initJMenuBar()方法用来初始化菜单。

创建整个菜单对象

JMenuBar jMenuBar=new JMenuBar();

创建菜单上面的三个选项的对象(功能、充值入口和关于我们)

JMenu functionJMenu=new JMenu("功能");
JMenu aboutJMenu=new JMenu("关于我们");

创建选项下面的条目对象

JMenuItem replayItem=new JMenuItem("重新游戏");

JMenuItem closeItem=new JMenuItem("关闭游戏");

JMenuItem congtactItem=new JMenuItem("联系我们");

 

现在整个菜单对象,3个选项的对象,条目的对象都是独立的,将他们组合在一起。将每一个条目添加到选项当中将重新游戏、重新登陆、关闭游戏放在功能里面。调用JMenu的add()方法将这3个条目添加到功能里面。

functionJMenu.add(replayItem);

functionJMenu.add(closeItem);

 

联系我们条目放入aboutJMenu中

aboutJMenu.add(contractItem);

将菜单里面的3个选项添加到菜单中,也就是把功能、关于我们、充值入口添加到JMenuBar中

jMenuBar.add(functionJMenu);
jMenuBar.add(aboutJMenu);

 

然后给整个界面设置菜单让他显示出来调用setJMenuBar()将jMenuBar放进去就可以了

this.setJMenuBar(jMenuBar);

 

三.添加并美化图片

图片是由15张小的图片组成,通过移动小图片的位置来组成一张完整的图片。

定义一个成员变量path用来表示图片的路径

String path=” pullzegame\\image\\animal\\animal3\\”;

初始化数据将数据打乱,在GameFJrame类中定义一个二维数组。在initData()中会用到这个二维数组,在下面加载图片的时候也要用到,所以把他定义为成员变量。

    int[][] data=new int[4][4];

 

在无参构造中定义一个名为initData()的方法打乱数据给二维数组赋值,把一个一维数组中的数据0-15打乱顺序,然后再按照4个一组的方式添加到二维数组中。

定义一个一维数组

int[] tempArr={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 < tempArr.length; i++) {

            //获取到随机索引

            int index=r.nextInt(tempArr.length);

            //拿着遍历到的每一个数据,跟随机索引进行交换

            int temp=tempArr[i];

            tempArr[i]=tempArr[index];

            tempArr[index]=temp;

        }

接下来4个一组将数据添加到二维数组当中,遍历二维数组,给里面的每一个数据赋值

        //遍历二维数组给里面的每一个数据赋值

        for (int i = 0; i < tempArr.length; i++) {

            if(tempArr[i]==0){

            x=i/4;

            y=i%4;

            }

            data[i/4][i%4]=tempArr[i];

        }     

根据打乱之后的结果去加载图片,图片所对应的类为ImageIcon,一张图片对应的就是一个ImageIcon对象。添加前需要给图片宽高的设置,先把图片放在一个JLabel的管理区域,JLabel可以管理图片文字。

创建ImageIcon对象并指定图片的位置,然后再把ImageIcon对象放入JLabel当中,再这个整体放入JFrame窗体当中,默认是居中。

在GameJFrame类中创建initImage()方法,创建双层循环,内层循序表示创建一排图片内层循环创建一个图片ImageIcon的对象,然后创建一个JLabel的对象用来管理图片大小,把图片放在管理容器里面,调用方法getContentPane()获取隐藏容器,在initFjrame()方法中调用setLayout(null)取消居中放置。再把容器放在放在界面当中。

外层循环把内层循环4次

for(int i=0;i<4;i++){

 

}

 

创建内层循环

for(int j=0;j<4;j++){

 

}

 

在内层循环中创建一个图片ImageIcon的对象

ImageIcon icon=new ImageIcon(

" path+data[i][j]+".jpg"

);

 

创建一个JLabel的对象

JLabel jLabel = new JLabel(icon);

 

调用setBounds()方法指定图片位置,该方法有四个参数,前两个参数x,y为图片的x轴和y轴,后面两个参数为图片的宽高单位像素。

jLabel.setBounds(105*j,105*i,105,105);

获取隐藏容器并把容器添加到界面中

   this.getContentPane().add(jLabel);

接下来初始化图片,在GameJFrame类无参构造方法GameJFrame()中调用initImage();方法。

 

美化图片

找到GameJFrame类中的initImage()方法,修改指定位置的图片将图片位置x轴向右偏移120,y轴向下偏移100。

jLabel.setBounds(105*j+120,105*i+100,105,105);

 

添加背景图片,创建一个ImageIcon的对象用来放图片,再把图片放到管理容器对象JLabel中

        ImageIcon bg=new ImageIcon(

"pullzegame\\image\\background.png"

);

        JLabel background=new JLabel(bg);

 

设置背景图片位置

    background.setBounds(76,6,508,560);

 

将背景图片添加到界面中

        this.getContentPane().add(background);

再给图片添加给边框

jLabel.setBorder(new BevelBorder(1));

 

四.移动图片

向上移动实际上就是把空白方块下方的图片上移

在整个游戏界面中,按上下左右才回去移动图片,所以给整个游戏界面添加一个键盘监听事件让GameJFrame这个类去实现KeyListener接口,在initJframe()方法中给整个界面添加键盘监听事件。

        this.addKeyListener(this);

游戏界面当中,要上下左右移动都和这个0有关系,不管怎么移动都要知道0的位置。

定义一个成员变量x和y用来表示图片0的位置

    int x=0;

int y=0;

 

统计0所在的位置,这个数据在initData()中,在添加二维数据时可以做个判断,如果tempArr[i]==0,就把0位置的坐标赋给x,y,否则就把当前数据添加到二维数组当中

 

现在找到keyReleased()方法对上下左右进行判断,调用getKeyCode()得到code值,上(38)下(40)左(37)右(39)

int code = e.getKeyCode();

针对于这四种情况就要写四个判断

    //对上下左右进行判断修改图片位置

        //左移

    if(code==37){

        if(y==3){

            return;

        }

        data[x][y]=data[x][y+1];

        data[x][y+1]=0;

        y++;

        initImage();

    }//上移

    else if(code==38){

        if(x==3){

            //表示空白图片已经时最下方了,它的下方没有图片再能移动

            return;

        }

        //把空白图片下方的数字往上移动

        //x,y表示空白图片,(x+1,y)表示空白下方的数字

        //空白图片下方的数字赋值给空白图片

        data[x][y]=data[x+1][y];

        data[x+1][y]=0;

        //数据发生改变之后0空白位置也因该发生改变

        x++;

        //调用方法按照最新的数字加载图片

        initImage();

    }//右移

    else if(code==39){

        if(y==0){

            return;

        }

        data[x][y]=data[x][y-1];

        data[x][y-1]=0;

        y--;

        initImage();

    }//下移

    else if(code==40){

        if(x==0){

            return;

        }

        data[x][y]=data[x-1][y];

        data[x-1][y]=0;

        x--;

        initImage();

    }

 

然后再initImage(()方法中清空已经出现的图片,不然界面不会发生变化还是之前的图片,再第一行调用removeAll()方法

this.getContentPane().removeAll();

 

最后调用repaint()方法刷新界面

        this.getContentPane().repaint();

 

一.查看完整图片、作弊码、判断胜利、按键提示

1.查看完整图片

游戏再刚开始启动时,图片时随机打乱的,在玩游戏过程中要查看完整图片。可以给游戏设置一个快捷键,通过这个快捷键查看完整图片。当按住这个键不松时就会显示完整图片。松开时显示打乱图片。在整个窗体上玩游戏时,按键时触发效果,给整个窗体绑定一个键盘监听事件。在之前写上下左右时,已经绑定了键盘监听事件,所有这一步不用写了。当键盘按住不松时,会一直掉用KeyPressed()方法,在方法当中可以先用e去调用getKeyCode()方法获取code值

int code=e.getKeyCode();

获取code值之后再定义一个victory()方法,调用victory()方法用来判断是否胜利,如果胜利停止此方法直接return。

        if(victory()){

            return;

        }

再做一个if判断,如果code值时65说明按的这个键时a,按a的时候把界面中所有图片删除,调用removeAll()方法。删完之后加载第一张完整图片,加载背景图片。创建一个JLabel对象,把完整图片路径仍进去。再给它设置位置宽高,调用setBounds()方法。

把图片加载到整个界面当中,再把背景图片加载到界面当中,刷新界面。

if(code==65){

        //把界面中所有图片全部删除

        this.getContentPane().removeAll();

        //架子第一张完整的图片

        JLabel all=new JLabel(new ImageIcon(path+"

all.jpg"));

        all.setBounds(120,100,420,420);

        this.getContentPane().add(all);

        //加载背景图片

        ImageIcon bg=new ImageIcon("pullzegame\\image\\background.png");

        JLabel background=new JLabel(bg);

        //设置背景图片位置

        background.setBounds(76,6,508,560);

        //将背景图片添加到界面中

        this.getContentPane().add(background);

        //刷新界面

        this.getContentPane().repaint();

 

    }

 

释放鼠标时要把图片变回之前的样子。在keyReleased()方法当中还要再添加判断,code如果等于65就说明松开,再调用initImage()方法加载图片。

 

  1. 作弊码

当按下w键时直接变成效果图,在整个界面添加键盘监听事件,但是已经添加过了不需要重复添加,找到对应的方法keyReleased()。添加一个if判断如果code值为87也就是w,new一个二维数组,直接把二维数组data里面的数据变成最后效果。最后调用initImage()重新加载图片。

  else if(code==87){

        data= new int[][]{

                {1,2,3,4},

                {5,6,7,8},

                {9,10,11,12},

                {13,14,15,0}

        };

        initImage();

    }

 

3.判断胜利

界面当中显示界面的图标,判断二维数组中的数字是否按照顺序进行排列,如果时就显示胜利。先定义一个正确的二维数组win,在加载图片之前,先判断二维数组中的数字跟win中的数组是否相同。如果相同展示正确图标,不相同不展示图标。

定义二维数组

    int[][] win={

            {1,2,3,4},

            {5,6,7,8},

            {9,10,11,12},

            {13,14,15,0}

};

再定义一个返回值为布尔类型的方法,判断data中的数据与win中的数据是否相同。

public boolean victory(){

        for (int i = 0; i < data.length; i++) {

            for (int j = 0; j < data[i].length; j++) {

                //只要有一个数据不一样就false

                if(data[i][j]!=win[i][j]){

                return false;

                }

            }

        }

        //比较完返回true

        return true;

    }

在initImage()方法当中去调用victory()方法对它的结果进行判断如果返回true就返回胜利的图标

游戏胜利之后,按上下左右就没有反应了,只能重新开始。

在keyReleased()方法当中判断游戏是否胜利如果胜利直接return

 

4.按键提示

在initImage()方法当中new一个JLabel对象并设置提示文字和位置

JLabel helpInfo = new JLabel("

小提示:w一键通关,a键查看全部,↑上↓下←左→右");

        helpInfo.setBounds(3,5,600,20);

        this.getContentPane().add(helpInfo);

 

 

 

六、菜单功能(计步功能、重新开始、关闭游戏、关于我们、)

1.计步功能

定义一个成员变量用来统计已经玩了多少步,每次按上下左右的时候计步器自增一次

Int step=0;

 

定义完成之后将它加载到界面当中,在initImage()方法中new一个JLabel对象并添加到界面当中

JLabel stepCount=new JLabel("步数"+step);

        stepCount.setBounds(50,30,100,20);

        this.getContentPane().add(stepCount);

当按上下左右键时,step变量加加,找到keyReleased()方法。在if中自增一次;

 

2.重新开始

点击重新游戏图片重新打乱并重新加载,给重新游戏按钮绑定ActionListener点击事件,重新打乱二维数组中的数字,加载图片,计步器清零。

找到GameJFrame类让他实现ActionListener,重新里面的方法。绑定菜单里面的重新开始条目,添加一个监听事件

replayItem.addActionListener(this);

在actionPerFormed()方法中调用getSource()方法获取被点击条目的对象

Object obj=e.getSource();

用这个对象去比较,为了方便使用,将创建条目对象代码放到方法外使它成为成员变量。再用if判断点击的是谁从而执行相应的条目

 

   //计步器清零

            step=0;

           // 再次打乱二维数组中的数据

            initData();

 

            // 重新加载图片

            initImage();

 

 

3.关闭游戏

给关闭游戏绑定事件,结束虚拟机,关闭所有

closeItem.addActionListener(this);

关闭当前的游戏界面,在actioinPerformed()方法判断closeItem中写入调用setVisible()方法

4.关于我们

绑定监听事件

在关于我们中点击联系我们会弹出弹框,弹框可以用JDialog来做,图片交给ImageIcon来管理,把ImageIcon放到JDialog中。

 创建一个弹框对象

            JDialog jDialog=new JDialog();

 

          创建一个管理容器的对象JLabel

            JLabel jLabel=new JLabel(new ImageIcon("

pullze\\pullzegame\\image\\ji.jpeg"));

 

设置位置

jLabel.setBounds(0,0,720,729);

           

把图片添加到弹框当中

           jDialog.getContentPane().add(jLabel);

            给弹框设置大小

            jDialog.setSize(750,750);

            让弹框置顶

            jDialog.setAlwaysOnTop(true);

            让它剧中

            jDialog.setLocationRelativeTo(null);

            弹框不关闭无法操作下面界面

            jDialog.setModal(true);

            让弹框显示出来

            jDialog.setVisible(true);

 做完了。。。。ovo

 

posted on 2022-07-31 17:51  罗|马  阅读(1884)  评论(0编辑  收藏  举报

Live2D