软件工程第二次作业

来源:互联网 发布:java split 效率 编辑:程序博客网 时间:2024/05/18 02:25

软件工程第二次作业

2048游戏

 

一、题目内容

题目内容:2048游戏

要求:实现2048游戏

实现方式:windows界面,主要利用Swing技术和事件处理机制编程。

做法:

1、利用Swing技术绘制2048界面。

2、定义Block类,设置数据块的背景颜色及数字的字体,还有不同数据块的颜色。

3、分别编写用户向上、向下、向右、向左滑动式的函数及其中的算法。

4、利用事件处理机制编写用户对键盘操作(上、下、左、右)时2048对应的实现。

二、背景及相关技术

(一)相关背景

2048是比较流行的一款数字游戏。原版2048首先在github上发布,原作者是Gabriele Cirulli。它是基于《1024》和《小3传奇》的玩法开发而成的新型数字游戏。

随后2048便出现各种版本,走各大平台。由Ketchapp公司移植到IOS的版本最为火热,现在约有1000万下载,其名字跟原版一模一样。衍生版中最出名的是《2048六边形》版本,先后在全球81个国家中的board game中排进了前200。安卓版非常火爆的有《挑战2048》,其2.0.0版以后还加入了双人对战。其次比较特别的有2048中国朝代版。更有2048自定义版,可以自己定义文字和图片。《2048~》是IOS中流行的一款。

(二)相关技术

利用Swing技术和事件监听机制来实现2048游戏的编程,用到的数据结构包括数组,类等,用户向上、向下、向左、向右滑动时的算法包括:数组元素赋值,数组元素之间的值相加,以及if条件语句和for循环语句。

三、概要设计

(一)2048游戏实现步骤

1.新建项目javatestà新建包my2048à新建类My2048主类和Block类。

引入程序中可能会用到的包(java.awt.*; java.awt.event.* ; javax.swing.*;)

My2048主类需要继承JFrame类并且实现KeyListener接口以及接口的所有方法。Block类:这个类的主要功能是设置2048界面中值为0的数据块的背景颜色,数字的字体,以及值不为0的数字块的背景颜色。主要用到setBackground()方法和 if---else if--。。。。---else语句。

2.在主类中声明需要的Swing组件以及变量。创建主类的构造函数,在构造函数中定义已经声明的组件和变量,设置窗口的标题、大小、位置和程序关闭操作。

3.给窗口加一个监听器,并把显示窗口的函数值设为true。

4.定义成员方法addBlock,用for语句初始化每个block[i],设置图标和文本的水平对齐方式,设置控件不透明。

5.定义成员方法appearBlock,用while语句实现系统随机给出的数字方块2或者4,while语句判断是否还能继续生成随机数字,其中要用到取随机数的方法Math.random()。在while语句中用双层if条件语句设置在数字块block[index]为空(即其值为0时)时,当Math.random()<0.5时, block[index]=2,否则block[index]=4。

6.定义成员方法judgeAppear,记录2048界面中已经出现的数字块的个数,当个数等于16时,停止随机生成数字。

7. 定义成员方法upBlock,即用户向上滑动时程序对应的操作。用双层for语句循环和if条件语句实现数字块的上移和垂直方向上的相邻数字块上移相加。

8.分别用类似upBlock()的定义方法定义downBlock(),rightBlock()和leftBlock()方法,实现用户向下,向右,向左滑动时程序对应的操作。

9.定义成员方法over(),当数字块在各个方向上都不能移动时在2048界面中出现CAMEOVER。

10.定义成员方法win(),当用户在这16个数字块中凑出2048时在界面中出现YOUWIN。

11.实现接口KeyListener的keyPressed(KeyEvent e)方法,用switch-----case语句分别实现用户对键盘的上、下、左、右触发时程序对应的操作。

对于KeyListener接口的其他方法要在程序中定义,可以没有方法体。

12.在主函数实例化My2048。

(二)逻辑图

 

 

四、系统实现

(一)My2048类

这个类的功能是利用Swing技术绘制2048图形界面,实例化每个随机生成的数据块,利用事件监听机制分别实现用户上移,下移,左移,右移时对应的2048界面的操作,游戏运行时出现2048或者不能移动时,利用对某些数据块赋值,实现游戏结束时可能会出现的结果(GAMEOVER或YOU WIN)。大致完成2048游戏的主要功能。

 
package my2048;import java.awt.*;import java.awt.event.KeyEvent;import java.awt.event.KeyListener;import java.awt.event.MouseAdapter;import java.awt.event.MouseEvent;import javax.swing.*;@SuppressWarnings("serial")public class My2048 extends JFrame implements KeyListener {Block[] block;JPanel panel;boolean numFlag;int moveFlag;public My2048() {numFlag = true;moveFlag = 0;block = new Block[16];setTitle("2048");setSize(400, 400);setLocation(500, 200);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);panel = (JPanel) getContentPane();panel.setLayout(new GridLayout(4, 4, 5, 5));addBlock();for (int i = 0; i < 2; i++)appearBlock();this.addKeyListener(this);this.setVisible(true);}public void addBlock() {for (int i = 0; i < 16; i++) {block[i] = new Block();block[i].setHorizontalAlignment(JLabel.CENTER);// 不透明block[i].setOpaque(true);panel.add(block[i]);}}public void appearBlock() {while(numFlag) {int index = (int) (Math.random() * 16);if (block[index].getValue() == 0) {if (Math.random() < 0.5)block[index].setValue(2);elseblock[index].setValue(4);break;}}}public void judgeAppear() {int sum = 0;for (int i = 0; i < 16; i++) {if (block[i].getValue() != 0)sum++;}if (sum == 16)numFlag = false;}public void upBlock() {for (int i = 12; i < 16; i++) {int index = i;for (int j = i - 4; j >= i - 12; j -= 4) {int valueI = block[index].getValue(), valueJ = block[j].getValue();if (valueJ == 0) {block[index].setValue(0);block[j].setValue(valueI);} else {if (valueI == valueJ) {block[index].setValue(0);block[j].setValue(valueI + valueJ);if (valueI + valueJ == 4096)win();numFlag = true;moveFlag = 0;} else if (numFlag == false)moveFlag += 1;}index = j;}}}public void downBlock() {for (int i = 0; i < 4; i++) {int index = i;for (int j = i + 4; j <= i + 12; j += 4) {int valueI = block[index].getValue(), valueJ = block[j].getValue();if (valueJ == 0) {block[index].setValue(0);block[j].setValue(valueI);} else {if (valueI == valueJ) {block[index].setValue(0);block[j].setValue(valueI + valueJ);if (valueI + valueJ == 4096)win();numFlag = true;moveFlag = 0;} else if (numFlag == false)moveFlag += 1;}index = j;}}}public void rightBlock() {for (int i = 0; i <= 12; i += 4) {int index = i;for (int j = i + 1; j <= i + 3; j++) {int valueI = block[index].getValue(), valueJ = block[j].getValue();if (valueJ == 0) {block[index].setValue(0);block[j].setValue(valueI);} else {if (valueI == valueJ) {block[index].setValue(0);block[j].setValue(valueI + valueJ);if (valueI + valueJ == 4096)win();numFlag = true;moveFlag = 0;} else if (numFlag == false)moveFlag += 1;}index = j;}}}public void leftBlock() {for (int i = 3; i <= 15; i += 4) {int index = i;for (int j = i - 1; j >= i - 3; j--) {int valueI = block[index].getValue(), valueJ = block[j].getValue();if (valueJ == 0) {block[index].setValue(0);block[j].setValue(valueI);} else {if (valueI == valueJ) {block[index].setValue(0);block[j].setValue(valueI + valueJ);if (valueI + valueJ == 4096)win();numFlag = true;moveFlag = 0;} else if (numFlag == false)moveFlag += 1;}index = j;}}}@Overridepublic void keyPressed(KeyEvent e) {switch (e.getKeyCode()) {case KeyEvent.VK_UP:upBlock();judgeAppear();appearBlock();over();break;case KeyEvent.VK_DOWN:downBlock();judgeAppear();appearBlock();over();break;case KeyEvent.VK_LEFT:leftBlock();judgeAppear();appearBlock();over();break;case KeyEvent.VK_RIGHT:rightBlock();judgeAppear();appearBlock();over();break;}}public void over() {if (!numFlag && moveFlag >= 36) {block[4].setText("G");block[5].setText("A");block[6].setText("M");block[7].setText("E");block[8].setText("O");block[9].setText("V");block[10].setText("E");block[11].setText("R");block[11].addMouseListener(new MouseAdapter() {@Overridepublic void mousePressed(MouseEvent e) {reStart();}});}}    public void win() {block[0].setText("Y");block[1].setText("O");block[2].setText("U");block[13].setText("W");block[14].setText("I");block[15].setText("N");block[15].addMouseListener(new MouseAdapter() {@Overridepublic void mousePressed(MouseEvent e) {reStart();}});}    public void reStart(){    numFlag=true;moveFlag=0;for(int i=0;i<16;i++)block[i].setValue(0);    for (int i = 0; i < 2; i++)appearBlock();    }@Overridepublic void keyTyped(KeyEvent e) {}@Overridepublic void keyReleased(KeyEvent e) {}public static void main(String args[]) {try {UIManager.setLookAndFeel("org.jvnet.substance.skin.SubstanceRavenGraphiteLookAndFeel");} catch (ClassNotFoundException | InstantiationException| IllegalAccessException | UnsupportedLookAndFeelException e) {e.printStackTrace();}JFrame.setDefaultLookAndFeelDecorated(true);new My2048();}}

 

(二)Block类

    这个类的主要功能是设置2048界面中值为0的数据块的背景颜色,数字的字体,以及值不为0的数字块的背景颜色。主要用到setBackground()方法和if—else if。。。else条件语句。

package my2048;import javax.swing.*;import java.awt.*;@SuppressWarnings("serial")public class Block extends JLabel {private int value;public Block() {value = 0;setFont(new Font("font", Font.PLAIN, 40));setBackground(Color.gray);}public int getValue() {return value;}public void setValue(int value) {this.value = value;String text = String.valueOf(value);if (value != 0)setText(text);elsesetText("");setColor();}public void setColor() {if (this.value == 0)setBackground(Color.gray);else if (this.value == 2)setBackground(new Color(238, 228, 218));else if (this.value == 4)setBackground(new Color(238, 224, 198));else if (this.value == 8)setBackground(new Color(243, 177, 116));else if (this.value == 16)setBackground(new Color(243, 177, 116));else if (this.value == 32)setBackground(new Color(248, 149, 90));else if (this.value == 64)setBackground(new Color(249, 94, 50));else if (this.value == 128)setBackground(new Color(239, 207, 108));else if (this.value == 256)setBackground(new Color(239, 207, 99));else if (this.value == 512)setBackground(new Color(239, 203, 82));else if (this.value == 1024)setBackground(new Color(239, 199, 57));else if (this.value == 2048)setBackground(new Color(239, 195, 41));else if (this.value == 4096)setBackground(new Color(255, 60, 57));}}


五、结果测试

(一)运行环境

运行环境:windows7。

开发工具:Eclipse

(二)运行结果



 

六、性能分析

性能测试工具 :JDK自带的 Visualvm插件

(一)CPU


(二)堆


(三)类


(四)线程


    七、心得体会

    经过对程序反复调试以及不断完善,基本能实现2048游戏的功能,例如,用户每次可以选择上、下、左、右其中一个方向去滑动,每滑动一次,大部分的数字方块都会往滑动的方向靠拢,同时在空白的地方随机出现一个数字方块,相同数字的方块在靠拢、相撞时会相加。随机出现的数字方块不是2就是4,当用户凑出2048是就胜利,并且会出现YOU WIN 字样,当各个方向都不能滑动时,游戏失败,界面会出现GAMEOVER字样。2048的界面,一开始整体16个方格有14个都是灰色的(即是说有14个空的数据块),当用户滑动出现数字之后就会改变颜色。程序的不足之处是,每滑动一次,并不是所有的数字方块都会往滑动的方向靠拢。这点以后在程序中的上下左右滑动方法中加以改进。

    通过对该游戏的设计,我对Java程序设计知识有了更进一步的认识;并且通过上机实践提高了我的动手能力。加深了我对Swing技术的理解,以及对事件监听机制的掌握。

 

 

0 0