一.界面分析
这个界面可以把它分为3个部分,各自有各自的作用。这三个部分都叫做组件
第一部分叫做JFrame,它是由2个单词来组成的,第一个是前面的J也就是java的意思,后面Frame窗体或者界面的意思,我们写的所有的文字图片都是放在这个窗体里面的,比如像那个统计步数就是放在就是放在这个里面。
中间的这个部分叫做菜单,当我们点击动能的时候,它会弹出下拉框比如说更换图片,可以重新游戏更换一把,或者是重新登陆、关闭游戏。菜单的名字叫JMenuBar,J是Java,Menu菜单的意思,Bar条目的意思。就是说上面的一长条是菜单。
第三部分叫做JLabel,这个JLabel不是图片是一个管理容易,可以管理文字、图片。
左上角这里的步数是一个文字,在写代码的时候我们要先创建一个JLabel管理容器的对象,再把文字放进去,最后再把管理容器JLabel管理容器放进去就可以了。图片也是一样的,先创建一个JLabel管理容器对象,把图片放进去,再把JLabel容器放进去就可以了。JLabel可以理解为一个管理容器。它名字第一个是J是Java的意思,后面Label可以理解为区域容器。
- 创建界面
创建一个宽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的对象,单击关于我们也是会弹出选项
- 先创建JMenuBar
- 再创建JMenu
- 再创建JMenuItem
- 把JMenuItem放到Jmenu里面
- 把JMenu放到JMenuBar里面
- 最后把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(
);
创建一个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()方法加载图片。
- 作弊码
当按下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