java 2048游戏设计初体验

来源:互联网 发布:淘宝客推广平台有哪些 编辑:程序博客网 时间:2024/06/05 05:48
package my2048;import java.awt.*;import java.awt.event.KeyAdapter;import java.awt.event.KeyEvent;import java.awt.event.MouseAdapter;import java.awt.event.MouseEvent;import javax.swing.*;public class My2048 extends JFrame {Block[] block;// 用于储存16个数据JPanel panel;boolean up, down, left, right;// 判断每个方向上是否还能移动boolean numFlag;// 用于判断是否还能加入新的数字boolean iswin; // 用于判断是否winpublic My2048() {setTitle("2048");setSize(400, 400);setLocationRelativeTo(null);// 设定窗口起始位置setResizable(false);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);getContentPane().setLayout(new GridLayout(4, 4, 5, 5));// 设定布局方式为GridLayout型panel = (JPanel) getContentPane();block = new Block[16];// 初始化参数iswin = false;numFlag = true;up = true;down = true;left = true;right = true;// 设置初始化界面addBlock();for (int i = 0; i < 2; i++)appearBlock();panel.setFocusable(true);panel.addKeyListener(new KeyAdapter() {public void keyPressed(KeyEvent e) {if (iswin) {return;}switch (e.getKeyCode()) {case KeyEvent.VK_UP:if (up) {upBlock();}judgeAppear();appearBlock();win();over();if (numFlag == false) {up = false;} else {up = true;down = true;left = true;right = true;}break;case KeyEvent.VK_DOWN:if (down) {downBlock();}judgeAppear();appearBlock();win();over();if (numFlag == false) {down = false;} else {up = true;down = true;left = true;right = true;}break;case KeyEvent.VK_LEFT:if (left) {leftBlock();}judgeAppear();appearBlock();win();over();if (numFlag == false) {left = false;} else {up = true;down = true;left = true;right = true;}break;case KeyEvent.VK_RIGHT:if (right) {rightBlock();}judgeAppear();appearBlock();win();over();if (numFlag == false) {right = false;} else {up = true;down = true;left = true;right = true;}break;}}});setVisible(true);// 设为可视}public static void main(String args[]) // 程序入口点{JFrame.setDefaultLookAndFeelDecorated(true);// 设定Frame的缺省外观new My2048();}/** * 往panel里加入block */private 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]);}}/** * 随机生成一个2或者4 */public void appearBlock() {while (numFlag) {int index = (int) (Math.random() * 16);// 取一个0到15的随机整数,这个数作为随机加入盘中的2或4的位置if (block[index].getValue() == 0)// 如果block[index]的值为空时,加入一个2或4{if (Math.random() < 0.5) {block[index].setValue(2);} else {block[index].setValue(4);}break;// 跳出while}}}/** * 统计block数组中是否含有值为0的元素,若没有,则numFlag变为false */public void judgeAppear() {int sum = 0;for (int i = 0; i < 16; i++) {if (block[i].getValue() != 0) {sum++;}}if (sum == 16)numFlag = false;}/** * 返回第一个不为空的block[i]的索引位置 * @param i 起始索引 * @param j 累加数值 * @param a 最小边界 * @param b 最大边界 * @return 没有返回 -1 */public int Find(int i, int j, int a, int b) {while (i < b && i >= a) {if (block[i].getValue() != 0) {return i;}i = i + j;}return -1;}/** * 向上移动 *  *  第一重循环    0 1 2 3 *   *  第二重循环    4  8  12  *      5  9  13 *  6  10 14 *  7  11 15 */public void upBlock() {int i = 0, j = 0;int t = 0;int valueJ = 0;int valueI = 0;int index = 0;for (i = 0; i < 4; i++) {index = i;for (j = i + 4; j < 16; j += 4) {valueJ = 0;valueI = 0;if (block[index].getValue() == 0) {//查找竖直方向上第一个不为空的方块索引,并将他置于顶部t = Find(index, 4, 0, 16);if (t != -1) {block[index].setValue(block[t].getValue());block[t].setValue(0);} else {break;}}valueI = block[index].getValue();if (block[j].getValue() == 0) {//查找竖直方向上第二个不为空的方块索引,并将他置于第二层t = Find(j, 4, 0, 16);if (t != -1) {block[j].setValue(block[t].getValue());block[t].setValue(0);} else {break;}}valueJ = block[j].getValue();//如果两个方块数值不为0且相等,则合并if (valueI == valueJ && valueI != 0 && valueJ != 0) {block[index].setValue(valueI + valueJ);block[j].setValue(0);numFlag = true;}index = j;}}}/** * 向下移动 *  *  第一重循环  12 13 14 15 *   *  第二重循环    8  4  0 *      9  5  1 *  10 6  2 *  11 7  3 */public void downBlock() {int i = 0, j = 0;int t = 0;int valueJ = 0;int valueI = 0;int index = 0;for (i = 12; i < 16; i++) {index = i;for (j = i - 4; j >= 0; j -= 4) {valueJ = 0;valueI = 0;if (block[index].getValue() == 0) {t = Find(index, -4, 0, 16);if (t != -1) {block[index].setValue(block[t].getValue());block[t].setValue(0);} else {break;}}valueI = block[index].getValue();if (block[j].getValue() == 0) {t = Find(j, -4, 0, 16);if (t != -1) {block[j].setValue(block[t].getValue());block[t].setValue(0);} else {break;}}valueJ = block[j].getValue();if (valueI == valueJ && valueI != 0 && valueJ != 0) {block[index].setValue(valueI + valueJ);block[j].setValue(0);numFlag = true;}index = j;}}}/** * 向左移动 *  *  第一重循环  0 4 8 12 *   *  第二重循环    1  2  3 *      5  6  7 *  9  10 11 *  13 14 15 */public void leftBlock() {int i = 0, j = 0;int t = 0;int valueJ = 0;int valueI = 0;int index = 0;for (i = 0; i < 16; i += 4) {index = i;for (j = i + 1; j < i + 4; j++) {valueJ = 0;valueI = 0;if (block[index].getValue() == 0) {t = Find(index, 1, i, i + 4);if (t != -1) {block[index].setValue(block[t].getValue());block[t].setValue(0);} else {break;}}valueI = block[index].getValue();if (block[j].getValue() == 0) {t = Find(j, 1, i, i + 4);if (t != -1) {block[j].setValue(block[t].getValue());block[t].setValue(0);} else {break;}}valueJ = block[j].getValue();if (valueI == valueJ && valueI != 0 && valueJ != 0) {block[index].setValue(valueI + valueJ);block[j].setValue(0);numFlag = true;}index = j;}}}/** * 向右移动 *  *  第一重循环  3 7 11 15 *   *  第二重循环   2  1  0 *      6  5  4 *  10 9  8 *  14 13 12 */public void rightBlock() {int i = 0, j = 0;int t = 0;int valueJ = 0;int valueI = 0;int index = 0;for (i = 3; i < 16; i += 4) {index = i;for (j = i - 1; j > i - 4; j--) {valueJ = 0;valueI = 0;if (block[index].getValue() == 0) {t = Find(index, -1, i - 3, i + 1);if (t != -1) {block[index].setValue(block[t].getValue());block[t].setValue(0);} else {break;}}valueI = block[index].getValue();if (block[j].getValue() == 0) {t = Find(j, -1, i - 3, i + 1);if (t != -1) {block[j].setValue(block[t].getValue());block[t].setValue(0);} else {break;}}valueJ = block[j].getValue();if (valueI == valueJ && valueI != 0 && valueJ != 0) {block[index].setValue(valueI + valueJ);block[j].setValue(0);numFlag = true;}index = j;}}}public void over() {if (numFlag == false && up == false && down == false && left == false&& right == false) // 当不能添加元素,并且不可移动就输了.{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");JOptionPane.showMessageDialog(null, "你输了!");block[15].addMouseListener(new MouseAdapter() {public void mousePressed(MouseEvent e) {reStart();}});}}public void win() {for (int i = 0; i < block.length; i++) {if (block[i].getText().equals("2048")) {iswin = true;block[0].setText("Y");block[1].setText("O");block[2].setText("U");block[13].setText("W");block[14].setText("I");block[15].setText("N");JOptionPane.showMessageDialog(null, "你赢了!");block[15].addMouseListener(new MouseAdapter() {public void mousePressed(MouseEvent e) {reStart();}});}}}public void reStart() {iswin = false;numFlag = true;up = true;down = true;left = true;right = true;for (int i = 0; i < 16; i++)block[i].setValue(0);for (int i = 0; i < 2; i++)appearBlock();}}

package my2048;import javax.swing.*;import java.awt.*;public class Block extends JLabel {private int value;public Block() {value = 0;// 初始化值为0setFont(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("");// 如果值为0则不显示setColor();}public void setColor() // 根据值的不同设定不同的背景颜色、label字体{switch (value) {case 0:setBackground(Color.gray);break;case 2:setBackground(new Color(238, 228, 218));break;case 4:setBackground(new Color(238, 224, 198));break;case 8:setBackground(new Color(243, 177, 116));break;case 16:setBackground(new Color(243, 177, 116));break;case 32:setBackground(new Color(248, 149, 90));break;case 64:setBackground(new Color(249, 94, 50));break;case 128:setBackground(new Color(239, 207, 108));break;case 256:setBackground(new Color(239, 207, 99));break;case 512:setBackground(new Color(239, 203, 82));break;case 1024:setBackground(new Color(239, 199, 57));break;case 2048:setBackground(new Color(239, 195, 41));break;case 4096:setBackground(new Color(255, 60, 57));break;}}}
初次学习制作游戏,没有经验,所以借鉴了一位前辈的代码,如有冒犯,请望见谅。而在学习的过程中,由于本人数学不是很好,加之源码中有的地方注释解释的不够清晰,所以对于源码中的移动,合并算法设计着实理解了好久,有感于此,遂决定将此次理解的过程以注释的方式进行了批注,并在自己理解的过程中着手对算法一些难以理解的地方进行了调优,使之更便于理解,并亲测好久,没有发现太大问题,故分享出来,望大家能多多指出一些修改意见!而且对于这个游戏的结束算法,总感觉判断的不够智能,还望各位大神如有更好的建议,能够告知,在下不胜感激!