JavaJavaSE算法之2048
Posted 笔触狂放
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaJavaSE算法之2048相关的知识,希望对你有一定的参考价值。
Java历经几十年IT届不倒,这个编程语言肯定是存在它的过人之处,计算机中任何软件最核心的东西就是算法。
这里分享一个以前风靡一时的网页小游戏《2048》的JavaUI版
界面效果如下:
通过按键盘的↑↓←→键移动数字,相邻的数字相同时,会进行合并。
右滑合并两个8,变成16再合并16变成32,效果如下
同时会进行统计当前得分,当游戏结束后,会自动记录当前得分,成为最高分。
接下来上代码:
package com.xf.game2048;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SpringLayout;
import javax.swing.SwingConstants;
public class Game2048 {
private int fwidth = 504;
private int fheight = 570;
private JFrame frame = null;
private JTextField sorceText = null;
private JTextField maxText = null;
private JLabel[][] card = new JLabel[4][4];
// 用来保存当前所有空的小卡片的下标
private List<Point> points = new ArrayList<>();
public Game2048() {
// 创建窗口
frame = new JFrame("2048");
frame.setSize(fwidth, fheight);
// 禁止窗口放大
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
center();
// 创建主面板
JPanel panel = new JPanel();
panel.setBackground(new Color(194, 184, 169));
frame.setContentPane(panel);
// 分数面板
JPanel srocePanel = new JPanel();
// 设置面板的高宽
srocePanel.setPreferredSize(new Dimension(480, 40));
// 添加边缘布局
SpringLayout layout = new SpringLayout();
// 设置面板的背景颜色为天蓝色
srocePanel.setBackground(new Color(159, 193, 230));
// 将边缘布局添加至面板
srocePanel.setLayout(layout);
panel.add(srocePanel);
JLabel maxlable = new JLabel("最高分:");
maxlable.setSize(50, 30);
maxlable.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 14));
srocePanel.add(maxlable);
layout.putConstraint(SpringLayout.NORTH, maxlable, 10, SpringLayout.NORTH, srocePanel);
layout.putConstraint(SpringLayout.WEST, maxlable, 10, SpringLayout.WEST, srocePanel);
maxText = new JTextField(5);
maxText.setText("0");
maxText.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 14));
maxText.setEditable(false);
srocePanel.add(maxText);
layout.putConstraint(SpringLayout.WEST, maxText, 5, SpringLayout.EAST, maxlable);
layout.putConstraint(SpringLayout.NORTH, maxText, -2, SpringLayout.NORTH, maxlable);
JLabel sorceLable = new JLabel("得分:");
sorceLable.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 14));
sorceLable.setSize(50, 30);
srocePanel.add(sorceLable);
layout.putConstraint(SpringLayout.NORTH, sorceLable, 0, SpringLayout.NORTH, maxlable);
layout.putConstraint(SpringLayout.WEST, sorceLable, 150, SpringLayout.EAST, maxText);
sorceText = new JTextField(5);
sorceText.setText("0");
sorceText.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 14));
sorceText.setEditable(false);
srocePanel.add(sorceText);
layout.putConstraint(SpringLayout.NORTH, sorceText, 0, SpringLayout.NORTH, maxText);
layout.putConstraint(SpringLayout.WEST, sorceText, 5, SpringLayout.EAST, sorceLable);
GridBagLayout layout2 = new GridBagLayout();
JPanel gamePanel = new JPanel();
gamePanel.setLayout(layout2);
gamePanel.setPreferredSize(new Dimension(480, 480));
gamePanel.setBackground(new Color(194, 184, 169));
panel.add(gamePanel);
GridBagConstraints constraints = new GridBagConstraints();
constraints.weightx = 4;
constraints.weighty = 4;
constraints.fill = GridBagConstraints.NONE;
constraints.anchor = GridBagConstraints.CENTER;
for (int i = 0; i < card.length; i++) {
for (int j = 0; j < card[i].length; j++) {
card[i][j] = new JLabel("", JLabel.CENTER);
card[i][j].setFont(new Font(Font.SANS_SERIF, Font.BOLD, 30));
card[i][j].setHorizontalAlignment(SwingConstants.CENTER);
card[i][j].setPreferredSize(new Dimension(110, 110));
card[i][j].setOpaque(true);// 隐藏背景
card[i][j].setBackground(new Color(204, 192, 178));
addJlable(constraints, card[i][j], gamePanel, i, j, 1, 1);
}
}
maxText.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
switch (key) {
// 向上滑
case KeyEvent.VK_W:
case KeyEvent.VK_UP:
up();
break;
// 向下滑
case KeyEvent.VK_S:
case KeyEvent.VK_DOWN:
down();
break;
// 向左滑
case KeyEvent.VK_A:
case KeyEvent.VK_LEFT:
left();
break;
// 向右滑
case KeyEvent.VK_D:
case KeyEvent.VK_RIGHT:
right();
break;
}
}
});
frame.setVisible(true);
startGame();
}
// 向左滑动
public void left() {
// 用于判断是否要添加随机卡片
boolean isadd = false;
// 用于控制行数循环
for (int y = 0; y < card.length; y++) {
for (int x = 0; x < card[y].length; x++) {
for (int x1 = x + 1; x1 < card.length; x1++) {
if (getNum(card[x1][y]) > 0) {
// 不合并,只是往指定的方向挪动
if (getNum(card[x][y]) <= 0) {
card[x][y].setText(card[x1][y].getText());
card[x1][y].setText("");
isadd = true;
x--;
break;
} else if (getNum(card[x][y]) == getNum(card[x1][y])) {
int s = x1 - x;
switch (s) {
case 1:
card[x][y].setText(getNum(card[x1][y]) * 2 + "");
card[x1][y].setText("");
isadd = true;
getSorce(getNum(card[x][y]));
break;
case 2:
if (getNum(card[x + 1][y]) == 0) {
card[x][y].setText(getNum(card[x1][y]) * 2 + "");
card[x1][y].setText("");
isadd = true;
getSorce(getNum(card[x][y]));
}
break;
case 3:
if (getNum(card[x + 1][y]) == 0 && getNum(card[x + 2][y]) == 0) {
card[x][y].setText(getNum(card[x1][y]) * 2 + "");
card[x1][y].setText("");
isadd = true;
getSorce(getNum(card[x][y]));
}
break;
}
}
}
}
}
}
check_stop();
if (isadd) {
createCard();
}
}
public void right() {
boolean isadd = false;
for (int y = 0; y < card.length; y++) {
for (int x = 3; x >= 0; x--) {
for (int x1 = x - 1; x1 >= 0; x1--) {
if (getNum(card[x1][y]) > 0) {
// 不合并,只是往指定的方向挪动
if (getNum(card[x][y]) <= 0) {
card[x][y].setText(card[x1][y].getText());
card[x1][y].setText("");
isadd = true;
x++;
break;
} else if (getNum(card[x][y]) == getNum(card[x1][y])) {
int s = Math.abs(x1 - x);
switch (s) {
case 1:
card[x][y].setText(getNum(card[x1][y]) * 2 + "");
card[x1][y].setText("");
isadd = true;
getSorce(getNum(card[x][y]));
break;
case 2:
if (getNum(card[x - 1][y]) == 0) {
card[x][y].setText(getNum(card[x1][y]) * 2 + "");
card[x1][y].setText("");
isadd = true;
getSorce(getNum(card[x][y]));
}
break;
case 3:
if (getNum(card[x - 1][y]) == 0 && getNum(card[x - 2][y]) == 0) {
card[x][y].setText(getNum(card[x1][y]) * 2 + "");
card[x1][y].setText("");
isadd = true;
getSorce(getNum(card[x][y]));
}
break;
}
}
}
}
}
}
check_stop();
if (isadd) {
createCard();
}
}
public void up() {
boolean isadd = false;
for (int x = 0; x < card.length; x++) {
for (int y = 0; y < card.length; y++) {
for (int y1 = y + 1; y1 < card.length; y1++) {
if (getNum(card[x][y1]) > 0) {
// 不合并,只是往指定的方向挪动
if (getNum(card[x][y]) <= 0) {
card[x][y].setText(card[x][y1].getText());
card[x][y1].setText("");
isadd = true;
y--;
break;
} else if (getNum(card[x][y]) == getNum(card[x][y1])) {
int s = y1 - y;
switch (s) {
case 1:
card[x][y].setText(getNum(card[x][y1]) * 2 + "");
card[x][y1].setText("");
isadd = true;
getSorce(getNum(card[x][y]));
break;
case 2:
if (getNum(card[x][y + 1]) == 0) {
card[x][y].setText(getNum(card[x][y1]) * 2 + "");
card[x][y1].setText("");
isadd = true;
getSorce(getNum(card[x][y]));
}
break;
case 3:
if (getNum(card[x][y + 1]) == 0 && getNum(card[x][y + 2]) == 0) {
card[x][y].setText(getNum(card[x][y1]) * 2 + "");
card[x][y1].setText("");
isadd = true;
getSorce(getNum(card[x][y]));
}
break;
}
}
}
}
}
}
check_stop();
if (isadd) {
createCard();
}
}
public void down() {
boolean isadd = false;
for (int x = 0; x < card.length; x++) {
for (int y = 3; y >= 0; y--) {
for (int y1 = y - 1; y1 >= 0; y1--) {
if (getNum(card[x][y1]) > 0) {
// 不合并,只是往指定的方向挪动
if (getNum(card[x][y]) <= 0) {
card[x][y].setText(card[x][y1].getText());
card[x][y1].setText("");
isadd = true;
y++;
break;
} else if (getNum(card[x][y]) == getNum(card[x][y1])) {
int s = Math.abs(y1 - y);
switch (s) {
case 1:
card[x][y].setText(getNum(card[x][y1]) * 2 + "");
card[x][y1].setText("");
isadd = true;
getSorce(getNum(card[x][y]));
break;
case 2:
if (getNum(card[x][y - 1]) == 0) {
card[x][y].setText(getNum(card[x][y1]) * 2 + "");
card[x][y1].setText("");
isadd = true;
getSorce(getNum(card[x][y]));
}
break;
case 3:
if (getNum(card[x][y - 1]) == 0 && getNum(card[x][y - 2]) == 0) {
card[x][y].setText(getNum(card[x][y1]) * 2 + "");
card[x][y1].setText("");
isadd = true;
getSorce(getNum(card[x][y]));
}
break;
}
}
}
}
}
}
check_stop();
if (isadd) {
createCard();
}
}
public void check_stop() {
boolean isStop = true;
for (int y = 0; y < card.length; y++) {
for (int x = 0; x < card.length; x++) {
if (getNum(card[x][y]) <= 0 || x > 0 && getNum(card[x][y]) == getNum(card[x - 1][y])
|| x < 3 && getNum(card[x][y]) == getNum(card[x + 1][y])
|| y > 0 && getNum(card[x][y]) == getNum(card[x][y - 1])
|| y < 3 && getNum(card[x][y]) == getNum(card[x][y + 1])) {
isStop = false;
}
}
}
if (isStop) {
JDialog dialog = new JDialog(frame, "提示信息");
dialog.setSize(200, 120);
JLabel label = new JLabel("游戏结束,是否再来一局!!!");
JButton ok = new JButton("再战一次");
JButton cancel = new JButton("取消");
JPanel panel = new JPanel();
FlowLayout layout = new FlowLayout();
layout.setAlignment(FlowLayout.CENTER);
panel.setLayout(layout);
panel.add(ok);
panel.add(cancel);
dialog.add(label, "Center");
dialog.add(panel, "South");
Toolkit kit = Toolkit.getDefaultToolkit();
Dimension dim = kit.getScreenSize();
int x = (dim.width - 300) / 2;
int y = (dim.height - 200) / 2;
dialog.setLocation(x, y);
dialog.setVisible(true);
ok.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
startGame();
dialog.setVisible(false);
// 判断当前所得分数是否高于最高分,如果高于最高分,就替换,得分清零
getMaxSorce();
sorceText.setText("0");
}
});
cancel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// 判断当前所得分数是否高于最高分,如果高于最高分,就替换
getMaxSorce();
System.exit(0);
}
});
}
}
public void getMaxSorce() {
String max = maxText.getText();
String sroce = sorceText.getText();
if (Integer.parseInt(max) < Integer.parseInt(sroce)) {
maxText.setText(sroce);
sorceText.setText("");
}
sroceOutPut(maxText.getText());
}
public void sroceINput() {
File file = new File("D:\\\\", "max.txt");
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
byte[] b = new byte[1024];
int has = -1;
try {
StringBuilder builder = new StringBuilder();
FileInputStream fis = new FileInputStream(file);
while ((has = fis.read(b)) != -1) {
String num = new String(b, 0, has);
builder.append(num);
}
if (builder.toString() != null && !builder.toString().equals("")) {
maxText.setText(builder.toString());
} else {
maxText.setText("0");
}
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public void sroceOutPut(String MaxSroce) {
File file = new File("D:\\\\", "max.txt");
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
FileOutputStream fos = new FileOutputStream(file);
fos.write(MaxSroce.getBytes());
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 开始玩游戏
*/
public void startGame() {
sroceINput();
// 清空所有卡片
for (int i = 0; i < card.length; i++) {
for (int j = 0; j < card[i].length; j++) {
card[i][j].setText("");
}
}
// 随机产生两个小卡片
createCard();
createCard();
}
public void getSorce(int sorce) {
String str = sorceText.getText();
int sum = Integer.parseInt(str) + sorce;
sorceText.setText(sum + "");
}
/**
* 将小卡片上的文字转换成数字,如果为空的卡片,则返回为0
*
* @param label
* @return
*/
public int getNum(JLabel label) {
return label.getText() != null && !label.getText().equals("") ? Integer.parseInt(label.getText()) : 0;
}
/**
* 创建小卡片
*/
public void createCard() {
points.clear();
// 循环遍历16个小卡片,找出所有空的小卡片,将下标存入point的集合
for (int y = 0; y < card.length; y++) {
for (int x = 0; x < card[y].length; x++) {
if (getNum(card[x][y]) == 0) {
points.add(new Point(x, y));
}
}
}
Point point = points.remove((int) (Math.random() * points.size()));
card[point.x][point.y].setText(Math.random() < 0.1 ? "4" : "2");
for (int y = 0; y < card.length; y++) {
for (int x = 0; x < card[y].length; x++) {
setColor(x, y, getNum(card[x][y]));
}
}
}
/**
* 根据小卡片上的数字更改背景颜色
*
* @param x
* @param y
* @param num
*/
public void setColor(int x, int y, int num) {
switch (num) {
case 0:
card[x][y].setBackground(new Color(204, 192, 178));
break;
case 2:
card[x][y].setBackground(new Color(238, 228, 218));
break;
case 4:
card[x][y].setBackground(new Color(236, 224, 200));
break;
case 8:
card[x][y].setBackground(new Color(242, 177, 121));
break;
case 16:
card[x][y].setBackground(new Color(245, 149, 99));
break;
case 32:
card[x][y].setBackground(new Color(248,124,98));
break;
case 64:
card[x][y].setBackground(new Color(247, 94, 62));
break;
case 128:
card[x][y].setBackground(new Color(240, 208, 107));
break;
case 256:
card[x][y].setBackground(new Color(241, 200, 108));
break;
case 512:
card[x][y].setBackground(new Color(237, 201, 79));
break;
case 1024:
card[x][y].setBackground(new Color(239, 197, 63));
break;
case 2048:
card[x][y].setBackground(new Color(238, 194, 46));
break;
}
}
public void addJlable(GridBagConstraints constraints, JLabel label, JPanel gamePanel, int gridx, int gridy,
int gridwidth, int gridheight) {
constraints.gridx = gridx;
constraints.gridy = gridy;
constraints.gridwidth = gridwidth;
constraints.gridheight = gridheight;
gamePanel.add(label, constraints);
}
/**
* 用于设置窗口中央显示
*/
public void center() {
Toolkit kit = Toolkit.getDefaultToolkit();
Dimension dim = kit.getScreenSize();
int x = (dim.width - fwidth) / 2;
int y = (dim.height - fheight) / 2;
frame.setLocation(x, y);
}
public static void main(String[] args) {
new Game2048();
}
}
当游戏结束后,会弹出对话框,告诉玩家是否再玩一次,或者直接退出。
如果想和好友进行对战,能力强的朋友可以尝试一样改为服务端项目,使用Socket进行实时更新。
在此分享到这里,感谢大家的关注和阅读!
以上是关于JavaJavaSE算法之2048的主要内容,如果未能解决你的问题,请参考以下文章