java 2048游戏设计初体验

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; // 用于判断是否win

	public 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;// 初始化值为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);
		else
			setText("");// 如果值为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;
		}
	}
}
初次学习制作游戏,没有经验,所以借鉴了一位前辈的代码,如有冒犯,请望见谅。而在学习的过程中,由于本人数学不是很好,加之源码中有的地方注释解释的不够清晰,所以对于源码中的移动,合并算法设计着实理解了好久,有感于此,遂决定将此次理解的过程以注释的方式进行了批注,并在自己理解的过程中着手对算法一些难以理解的地方进行了调优,使之更便于理解,并亲测好久,没有发现太大问题,故分享出来,望大家能多多指出一些修改意见!而且对于这个游戏的结束算法,总感觉判断的不够智能,还望各位大神如有更好的建议,能够告知,在下不胜感激!
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值