Java实现2048小游戏,我竟然一盘都没赢,你们说我到底行不行?

Posted 编程界明世隐

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java实现2048小游戏,我竟然一盘都没赢,你们说我到底行不行?相关的知识,希望对你有一定的参考价值。

作者简介

作者名:编程界明世隐
简介:CSDN博客专家,从事软件开发多年,精通Java、javascript,博主也是从零开始一步步把学习成长、深知学习和积累的重要性,喜欢跟广大ADC一起打野升级,欢迎您关注,期待与您一起学习、成长、起飞!

系列目录

1. Java俄罗斯方块
2. Java五子棋小游戏
3. 老Java程序员花一天时间写了个飞机大战
4. Java植物大战僵尸
5. 老Java程序员花2天写了个连连看
6. Java消消乐(天天爱消除)
7. Java贪吃蛇小游戏
8. Java扫雷小游戏
9. Java坦克大战
10. Java迷宫小游戏

Java 2048小游戏

引言:

前几天偶尔看到了这个数字游戏,感觉还蛮有意思,就玩了一下,竟然赢不了,怎么玩都是输,真是邪门了,这不作为程序员员,我玩不赢我就自己写一个,行不行?我自己写的,我想赢就赢,条件我自己设定,就是玩!!

效果图

实现思路

  1. 绘制窗口。
  2. 创建菜单。
  3. 创建所有空白卡片。
  4. 随机创建一个卡片(2或者4)。
  5. 键盘事件监听(上、下、左、右键监听)。
  6. 根据键盘的方向,处理数字的移动合并。
  7. 加入成功、失败判定。
  8. 处理其他收尾工作。

代码实现

创建窗口

首先创建一个游戏窗体类GameFrame,继承至JFrame,用来显示在屏幕上(window的对象),每个游戏都有一个窗口,设置好窗口标题、尺寸、布局等就可以。

package main;

import java.awt.Color;
import javax.swing.JFrame;
/**
 *窗体类
 */
public class GameFrame extends JFrame {
	//构造方法
	public GameFrame(){
		setTitle("2048");//设置标题
		setSize(370, 420);//设置窗体大小
		getContentPane().setBackground(new Color(66,136,83));//加上背景
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭后进程退出
		setLocationRelativeTo(null);//居中
		setResizable(false);//不允许变大
	}
}

创建面板容器GamePanel继承至JPanel

package main;

import javax.swing.JFrame;
import javax.swing.JPanel;

/*
 * 画布类
 */
public class GamePanel extends JPanel{
	private JFrame mainFrame=null;
	private GamePanel panel = null;
	//构造里面初始化相关参数
	public GamePanel(JFrame frame){
		this.setLayout(null);
		this.setOpaque(false);
		this.mainFrame=frame;
		this.panel =this;
	}
}

再创建一个Main类,来启动这个窗口,用来启动。

package main;

//Main类
public class Main {

	public static void main(String[] args) {
		GameFrame frame = new GameFrame();
		GamePanel panel = new GamePanel(frame);
		frame.add(panel);
		frame.setVisible(true);
	}
}

右键执行这个Main类,窗口建出来了

创建菜单

private Font createFont(){
		return new Font("思源宋体",Font.BOLD,18);
	}
	//创建菜单
	private void createMenu() {
		//创建JMenuBar
		JMenuBar jmb = new JMenuBar();
		//取得字体
		Font tFont = createFont(); 
		//创建游戏选项
		JMenu jMenu1 = new JMenu("游戏");
		jMenu1.setFont(tFont);
		//创建帮助选项
		JMenu jMenu2 = new JMenu("帮助");
		jMenu2.setFont(tFont);
		
		JMenuItem jmi1 = new JMenuItem("新游戏");
		jmi1.setFont(tFont);
		JMenuItem jmi2 = new JMenuItem("退出");
		jmi2.setFont(tFont);
		//jmi1 jmi2添加到菜单项“游戏”中
		jMenu1.add(jmi1);
		jMenu1.add(jmi2);
		
		JMenuItem jmi3 = new JMenuItem("操作帮助");
		jmi3.setFont(tFont);
		JMenuItem jmi4 = new JMenuItem("胜利条件");
		jmi4.setFont(tFont);
		//jmi13 jmi4添加到菜单项“游戏”中
		jMenu2.add(jmi3);
		jMenu2.add(jmi4);
		
		jmb.add(jMenu1);
		jmb.add(jMenu2);
		
		mainFrame.setJMenuBar(jmb);
		
		//添加监听
		jmi1.addActionListener(this);
		jmi2.addActionListener(this);
		jmi3.addActionListener(this);
		jmi4.addActionListener(this);
		//设置指令
		jmi1.setActionCommand("restart");
		jmi2.setActionCommand("exit");
		jmi3.setActionCommand("help");
		jmi4.setActionCommand("win");
	}

此时直接把这个代码加入到GamePanel中,发现是会报错的,需要实现ActionListener,并重写actionPerformed 方法。

此时GamePanel的代码如下:

package main;

import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.plaf.FontUIResource;

/*
 * 画布类
 */
public class GamePanel extends JPanel implements ActionListener{
	private JFrame mainFrame=null;
	private GamePanel panel = null;
	//构造里面初始化相关参数
	public GamePanel(JFrame frame){
		this.setLayout(null);
		this.setOpaque(false);
		this.mainFrame=frame;
		this.panel =this;
		
		//创建菜单
		createMenu();
	}
	
	private Font createFont(){
		return new Font("思源宋体",Font.BOLD,18);
	}
	//创建菜单
	private void createMenu() {
		//创建JMenuBar
		JMenuBar jmb = new JMenuBar();
		//取得字体
		Font tFont = createFont(); 
		//创建游戏选项
		JMenu jMenu1 = new JMenu("游戏");
		jMenu1.setFont(tFont);
		//创建帮助选项
		JMenu jMenu2 = new JMenu("帮助");
		jMenu2.setFont(tFont);
		
		JMenuItem jmi1 = new JMenuItem("新游戏");
		jmi1.setFont(tFont);
		JMenuItem jmi2 = new JMenuItem("退出");
		jmi2.setFont(tFont);
		//jmi1 jmi2添加到菜单项“游戏”中
		jMenu1.add(jmi1);
		jMenu1.add(jmi2);
		
		JMenuItem jmi3 = new JMenuItem("操作帮助");
		jmi3.setFont(tFont);
		JMenuItem jmi4 = new JMenuItem("胜利条件");
		jmi4.setFont(tFont);
		//jmi13 jmi4添加到菜单项“游戏”中
		jMenu2.add(jmi3);
		jMenu2.add(jmi4);
		
		jmb.add(jMenu1);
		jmb.add(jMenu2);
		
		mainFrame.setJMenuBar(jmb);
		
		//添加监听
		jmi1.addActionListener(this);
		jmi2.addActionListener(this);
		jmi3.addActionListener(this);
		jmi4.addActionListener(this);
		//设置指令
		jmi1.setActionCommand("restart");
		jmi2.setActionCommand("exit");
		jmi3.setActionCommand("help");
		jmi4.setActionCommand("win");
	}
	@Override
	public void actionPerformed(ActionEvent e) {
		String command = e.getActionCommand();
		UIManager.put("OptionPane.buttonFont", new FontUIResource(new Font("思源宋体", Font.ITALIC, 18)));
		UIManager.put("OptionPane.messageFont", new FontUIResource(new Font("思源宋体", Font.ITALIC, 18)));
		if ("exit".equals(command)) {
			Object[] options = { "确定", "取消" };
			int response = JOptionPane.showOptionDialog(this, "您确认要退出吗", "",
					JOptionPane.YES_OPTION, JOptionPane.QUESTION_MESSAGE, null,
					options, options[0]);
			if (response == 0) {
				System.exit(0);
			} 
		}else if("restart".equals(command)){
		}else if("help".equals(command)){
			JOptionPane.showMessageDialog(null, "通过键盘的上下左右来移动,相同数字会合并!",
					"提示!", JOptionPane.INFORMATION_MESSAGE);
		}else if("win".equals(command)){
			JOptionPane.showMessageDialog(null, "得到数字2048获得胜利,当没有空卡片则失败!",
					"提示!", JOptionPane.INFORMATION_MESSAGE);
		}
	}
}

创建Card

建立Card类

package main;

import java.awt.Graphics;

public class Card {
	private int x = 0;// x坐标
	private int y = 0;// y坐标
	private int w = 80;// 宽
	private int h = 80;// 高
	private int i = 0;//下标i
	private int j = 0;//下标j
	private int start=10;//偏移量(固定值)
	private int num=0;//显示数字
	private boolean merge=false;//当前是否被合并过,如果合并了,则不能继续合并,针对当前轮
	
	public Card(int i,int j){
		this.i=i;
		this.j=j;
	}
	//根据i j计算x y坐标
	private void cal(){
		this.x = start + j*w + (j+1)*5;
		this.y = start + i*h + (i+1)*5;
	}
	//绘制方法
	public void draw(Graphics g) {
		cal();
		g.fillRoundRect(x, y, w, h, 4, 4);
	}
	
	
	public int getNum() {
		return num;
	}
	public void setNum(int num) {
		this.num = num;
	}
	public boolean isMerge() {
		return merge;
	}
	public void setMerge(boolean merge) {
		this.merge = merge;
	}
}

在GamePanel中加入相关参数

private final int COLS=4;//列
private final int ROWS=4;//行
private Card cards[][] = new Card[ROWS][COLS];
private String gameFlag = "start";//游戏状态

实例化Card对象

//初始化
private void init() {
	Card card;
	for (int i = 0; i < ROWS; i++) {
		for (int j = 0; j < COLS; j++) {
			card = new Card(i,j);
			cards[i][j]=card;
		}
	}
}

在构造方法中调用

//构造里面初始化相关参数
public GamePanel(JFrame frame){
	this.setLayout(null);
	this.setOpaque(false);
	this.mainFrame=frame;
	this.panel =this;
	
	//创建菜单
	createMenu();
	
	//初始化
	init();
}

在GamePanel中重写paint方法,并在此方法中绘制这些卡片。

@Override
public void paint(Graphics g) {
	super.paint(g);
	//绘制卡片
	drawCard(g);
}
//绘制卡片
private void drawCard(Graphics g) {
	Card card;
	for (int i = 0; i < ROWS; i++) {
		for (int j = 0; j < COLS; j++) {
			card = cards[i][j];
			card.draw(g);
		}
	}		
}

运行

这个黑色不是我们想要的,要根据不同的数字来设置不同的颜色,于是我们在Card修改一下。

//获取color
private Color getColor(){
	Color color=null;
	//根据num设定颜色
	switch (num) {
	case 2:
		color = new Color(238,244,234);
		break;
	case 4:
		color = new Color(222,236,200);
		break;
	case 8:
		color = new Color(174,213,130);
		break;
	case 16:
		color = new Color(142,201,75);
		break;
	case 32:<

以上是关于Java实现2048小游戏,我竟然一盘都没赢,你们说我到底行不行?的主要内容,如果未能解决你的问题,请参考以下文章

2048小游戏竟然还有3D版?使用MATLAB制作一款3D版2048小游戏

Java版2048

Java实现2048小游戏代码

Java 实现2048游戏之详细教程

JavaScript实现2048小游戏,我终于赢了一把

2048小游戏主要算法实现