
课程咨询: 400-996-5531 / 投诉建议: 400-111-8989
认真做教育 专心促就业
特征1:游戏的主窗口是由16个灰色的方块按照4x4的网格方式组成
特征2:游戏刚开始时,在这十六个方块之中,有两个带有数字的方块
特征3:这两个方块随机的出现在这十六个方块中的任意位置,方块上的数字为2或者4,不固定
特征4:所有带数字的方块都可以上下左右移动
特征5: 方块碰撞与合并算法
特征6:当16个方块都被数字方块充满且无法合并时,游戏结束
一、 开发步骤
2.1 创建游戏窗体
JFrame
介绍:JAVA面板,JAVA提供的GUI(用户图形界面编程)工具包,用于绘制界面软件窗口(相框)。
语法:a) 1、导包
2、 JFrame frame = new JFrame();
b) 1、导包
2、extends JFrame类,然后本类就可以当作JFrame类使用
常见方法:setSize(width,height); --设置窗体大小
SetVisible(true/false); --当参数设置为true设置窗口可见
SetLocationRelativeTo(null); --设置窗口初始位置,参数为NULL时居中,不填写参数时按照屏幕默认焦点定位
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); --设置程序的关闭方式,这里指当窗口关闭时程序结束
Jpanel
介绍:JAVA面板,JAVA提供的GUI(用户图形界面编程)工具包,用于绘制界面软件面板(照片纸)。
语法:a) 1、导包
2、 Jpanel panel= new Jpanel ();
b) 1、导包
2、extends Jpanel类,然后本类就可以当作Jpanel类使用
常用方法:略(在这里我们不怎么使用)
2.2 绘制4X4的方块墙
JButton
介绍:JAVA按钮,用于在界面上创建我们所需要使用的按钮,在这里我们将JButton作为我们游戏界面方块的载体使用。
Q:为什么使用JButton而不是其他的方法?
A:JDK中给我们提供了一个类叫做Layout,即布局的意思,这个类及其子类在结合JButton类使用的情况下为我们提供了GUI的布局,使我们可以更轻松的解决GUI的布局问题,如果不使用JButton也可以完成效果,但是需要我们一个一个的去考虑每一个方块的定位坐标,过于繁琐,而且不利于修改。例如:如果我们要将窗口由4X4变成5X5的话,只需要修改提供给Layout的插件即可,但是不使用JButton的话我们就要重新考虑所有方块的坐标。
JBurtton的布局方式
边界布局:BorderLayout,按钮按东西南北的顺序沿着窗口的边界布局,南北的按钮高度固定,东西的按钮宽度固定,留白的部分留给中间的窗口使用
使用方式,在add方法中直接作为参数声明即可
流布局:FlowLayout,顾名思义,象水流一样从前至后一次排列,默认居中,可以通过设置参数来改变对齐方式
使用方式,通过setLayout方法设置流布局
Q:流布局是否可以实现我们的方块墙?
A:可以实现,但是需要界定方块的大小,每次修改都要重新界定,相比网格布局更麻烦一些。
网格布局:GridLayout,根据我们提供的参数,呈网状分布的布局方式
使用方式,通过setLayout方法设置网格布局
回到项目中,下一步我们是要绘制出4X4的方块墙,要绘制出来4X4的效果我们需要在Game类中设置两个属性,row和col
接下来,我们已经知道这里的方块墙是一个个方块拼接而成的,在以往的学习过程中,我们都是用数组来接收多个一组属性的,那么这里的这一组方块我们能够用数组来接收吗?
我们先分析一下添加方块墙所需要具备的条件有哪些
1、 方块坐标
2、 方块本身
Point
JAVA提供给我们的一个新的工具类,表示 (x, y) 坐标空间中的位置的点,以整数精度来指定。
语法:Point(X,Y) --根据传入的X,Y的值来进行定位
Q:那老师,你这不还是需要确定坐标才可以定位吗?
A:当我们结合网格式布局使用Point时,该类可以根据你提供的序列,结合网格型布局自动定位方位,因此我们只需要给一个序列就可以,而不需要提供精确的坐标。
案例:略(待会我们到代码中可以证实)
到目前为止,我们第一个需要封装的内容就已经拿出来了,接下来我们需要封装第二个属性,也就是方块属性(Cube),这里JAVA并没有给我门提供方块这个类,所以我们需要自己封装。
建立Cube类
Cube类中需要用到哪些属性和方法?
1:数字 --int num
方法:设置数字 setText(int n)
2:方块 --JButton btn
获取方块 JButton getBtn(int index)
3:图片 --ImageIcon[] cubes
初始化图片 static{}
获取图片 ImageIcon getImg(int index)
4:是否使用 – boolean isAdded
构造方法 初始化Button num和isAdded
注:这里我们因为接下来的num是非连续性的,所以采用swith case来添加
扩展:其实我们这里可以用另外一种方法来实现,这里除了0以外的所有数字都是上一个的2倍
我们用二进制来查看
0 ->00000000
2 ->00000010
4 ->00000100
8 ->00001000
…
当数字不等于0时,每一次赋值都是将这个1向左移一位
所以我们可以通过位运算符来实现
<<左移
>>右移
>>>无符号右移
完成Cube类的设计后,我们开始将这两个属性封装
复习一下我们之前学过的知识,数组是接收一组同类数据的容器,既然数组只能封装同一类型的一组数据,但是这里我们有两个类型的数据,那么我们在这里应该用什么呢?
HashMap和泛型
首先,在这里 声明一下,HashMap和泛型跟之前的异常捕获一样,我们在一周以后会讲到,所以这里只是简要的介绍一下,HashMap是集合的一种,所谓集合,就是没有数据类型限制的一种数组。
名称可否存放多个元素可否存放多个类型
HashMapTrueTure
数组TrueFalse
举例,看到老师手腕上的珠子没
集合类似于超市的储物柜
而HashMap则类似于带锁的储物柜(蜂巢快递柜),它包含两个部分,第一个部分叫做Key,类似于钥匙,第二个部分叫做Value,类似于储物柜中的货物。
语法:HashMap<key,Value> map = new HashMap();
常用方法:put(key,Value);向集合中添加元素
获取方法,get方法,传入Key的参数
好,HashMap我们暂时介绍到这,想知道它更多的方法以及底层实现的话,一周以后会跟你们详细说明。
声明属性
注释paint方法
Q:既然注释掉了paint方法为何还要extends JPanel?
A:我们需要一张在我们的游戏中使用不到的图片为我们的背景去确定宽和高,这样做对比写死来说一来方便我们以后扩展游戏内容,比如设置窗口为5X5、6X6、扩展游戏功能等,另外则是为了以后可以添加背景图片,美化我们的游戏界面。
在构造方法中调用put方法提供元素并且添加到面板上
根据Key(Point)获取Value(Cubes)
2.3 创建数字方块
下一步,生成两个随机的带数字的方块,
gameStart方法 --游戏开局方法,我们在这里创建初始的两个数字方块
同时,如果未来我们想要添加游戏状态的话也可以在这里添加。
createCube方法
生成方块
1、给与方块一个随机的坐标,横纵坐标基于0~3之间
2、调用setText方法,设置方块内的数字
如何达成条件1?
画图:
我们假设我们在所有方块中随便找一个方块,找到该方块以后,
我们要判断该方块是否是数字方块,条件就是如果这个方块的num不为0
也就是说如果Cube的num值是0,那么它就不是数字方块,我们需要再去找下一个方块,一直到我们找到的方块是数字方块才能将这个方块创建出来
要素条件:
1、一直找->循环
2、先找到再判断->do while循环
3、随机->math.random
4、随机出来的结果只能在0,1,2,3之间->*100%宽高
5、画图:
x坐标由行决定,y坐标由列决定
2.4 方块的移动
业务描述:
当我们按下“上下左右”按键时,界面上的所有数字方块的上下左右移动
1、 当我们按下键盘上的对应按键时,程序需要给与反应
2、 方块的移动
a) 哪些方块可以移动?
i. 向上时:第一排以下所有方块
ii. 向下时:最后一排往上的所有方块
iii. 向左时:最右边一列往左的所有方块
iv. 向右时:最左边一列往右的所有方块
b) 方块移动的特点
i. 移动的本质是交换方块
ii. 每次移动都是一排一排的移动
iii. 当移动的方向上没有方块的时候,移动到底
iv. 当移动的路径上有方块的时候,移动到方块侧面
v. 每次方块移动完毕后,在空白位置生成新的方块
1. CreateCbue方法
vi. 当两个相撞的方块的数字相同时,方块合并,数字翻倍
1. setNum方法
a) 目标方块位置num*2
b) 原方块位置num为0
2. getBtn方法获取新的Cube图片
3. setIsAdded设置使用状态
a) 目标状态为true
b) 原方块位置为false
方块的直接移动
移动到下一个方块边缘
创建随机的新方块
方块的合并
方法设计
在方向平移时,哪些方块能动
方块的当前位置 now
方块的下一个位置 next
方块的移动方向 up down left right
这个位置是否存在数字方块 isAdded
根据一般来说方法只做一件事情的原则,我们做如下
获取方块当前位置和方块的下一个位置->方块的位移 ->swap方法
控制方块的移动方向 ->Move方法
控制哪些方块能够上下左右移动 ->down up left right方法
当我们按下键盘按键时,程序会给予反应 -> ?
键盘监听器
Keylistener 键盘监听,检测键盘被敲击的动作
使用:1、implements Keylistener接口
3、 addKeyListener方法,传入我们自定义的Keylistener
在JAVA中,keyListener和KeyEvent之间是有继承关系的,所以我们使用的时候只需要implements Keylistener接口便可以了
Keylistener接口为我们提供了两个类
--keyPressed 键盘被按下时调用该方法
--keyReleased 松开键盘时调用该方法
--keyTyped 键入某个按键时调用该方法
KeyEvent 键盘事件,当KeyListener监听到键盘被敲击的动作后,产生键盘敲击事件
常用属性:KeyEvent中与键盘一一对应的属性
常用方法:get/setKeyCode、get/setKeyChar、get/setKeyLocation
get/setKeyText等
案例练习
练习:将该类改为继承Jpanel,看看结果如何?
由于JPanel默认键盘事件焦点是关闭的,所以我们需要通过setFocusable(true)来开启
设计MyKeyListener类
Panel的焦点重置
Left, Right, Up, Down方法
移动方块:2048中有两种方块,所以我们需要考虑两种方块不同的移动逻辑
确定方块的移动方向
方块的当前位置和方块的下一个位置
方块是否碰撞
注:一般在开发过程中,我们讲究一个方法一般只做一件事
这里,我们已经分析了五件需要我们完成的功能,那么在这四个方法里我们优先完成
靠上层的一件事,即区分两种方块的移动方式
方块分两类:1、数字方块 ->数字方块的移动方式
2、墙方块 ->墙方块的移动方式
移动完毕后,再创建一个方块 ->createCube方法已经完成了
我们直接调用即可
Move方法
已知:在之前分析的功能中我们还需要做到以下几点
1、确定方块的移动方向
2、方块的当前位置和方块的下一个位置
3、方块是否碰撞
那么在这里我们只需要考虑如何制定方块不同方向的移动轨迹即可
其他的功能我们交由下层方法去执行
向上移动时,Y坐标不变,X坐标越来越小,X不小于0
向下移动时,Y坐标不变,X坐标越来越大,X不大于row-1(只能移动三次)
向左移动时,X坐标不变,Y坐标越来越小,Y不小于0
向右移动时,X坐标不变,Y坐标越来越大,Y不大于col-1(只能移动三次)
单向交换移动
在move方法中我们已经设定好方向的移动轨迹
而且我们现在也已经通过getCube方法获取了方块的当前位置和方块的下一个移动位置,那么现在我们只需要知道当前方块所移动的目标位置的方块是数字方块还是墙壁方块即可:
若为墙壁方块,则数字方块与这个墙壁方块互换位置
若为数字方块,则判断能否合并,可以合并的话在目标位置的方块晋升为更高级的数字方块
若不能合并,则位置不变
【免责声明】本文部分系转载,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及作品内容、版权和其它问题,请在30日内与联系我们,我们会予以更改或删除相关文章,以保证您的权益!