JAVA 实现《2048游戏》游戏

这篇具有很好参考价值的文章主要介绍了JAVA 实现《2048游戏》游戏。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

2014年Gabriele Cirulli利用周末的时间写2048这个游戏的程序,仅仅只是好玩而已。他想用一种不同的视觉展现效果和更快速的动画来创造属于自己的游戏版本。

游戏是用java语言实现,采用了swing技术进行了界面化处理,设计思路用了面向对象思想。

主要需求

每次控制所有方块向同一个方向运动,两个相同数字的方块撞在一起之后合并成为他们的和,每次操作之后会在空白的方格处随机生成一个2或者4,最终得到一个“2048”的方块就算胜利了。如果16个格子全部填满并且相邻的格子都不相同也就是无法移动的话,那么游戏就会结束。

主要设计

1、游戏面板生成显示

2、方块设计

3、键盘监听,方向键控制数字移动

4、数字移动逻辑算法处理

5、数字累加到2048,游戏胜利

功能截图

游戏开始

JAVA 实现《2048游戏》游戏

移动效果

JAVA 实现《2048游戏》游戏

代码实现

界面布局类


public class Game2048View implements ActionListener{
	Block[] blocks;		//方块
	JPanel myJPanel;	//主面板
	JPanel jp1,jp2;		//子面板
//	int moveFlag;				// 用于累计移动的次数
	boolean numFlag;		// 用于判断是否还能加入新的数字
	JLabel scroeValue;		//显示分数
	
	public Game2048View(JFrame myJFrame){
		blocks=new Block[16];
//		moveFlag=0;
		numFlag=true;
		this.myJPanel=(JPanel)myJFrame.getContentPane();///获取内容面板
		setJp1();
		myJPanel.add(jp1,BorderLayout.NORTH);
		setJp2();
		myJPanel.add(jp2, BorderLayout.CENTER);
		myJFrame.addKeyListener(new Game2048Logic(this,myJFrame,blocks,numFlag,scroeValue));
	}
	
	public void addc(JPanel jp1,Component component, GridBagConstraints gbc,int gridwidth,int gridheight, int weightx,int weighty,int gridx,int gridy) {
		//此方法用来添加控件到容器中
		gbc.gridwidth=gridwidth;		//该方法是设置组件水平所占用的格子数,如果为0,就说明该组件是该行的最后一个
		gbc.gridheight=gridheight;		//该方法是设置组件垂直所占用的格子数
		gbc.weightx=weightx;				//该方法设置组件水平的拉伸幅度,如果为0就说明不拉伸,不为0就随着窗口增大进行拉伸,0到1之间
		gbc.weighty=weighty;				//该方法设置组件垂直的拉伸幅度,如果为0就说明不拉伸,不为0就随着窗口增大进行拉伸,0到1之间
		gbc.gridx=gridx;
		gbc.gridy=gridy;
		gbc.fill=GridBagConstraints.BOTH;
		jp1.add(component,gbc);
	}
	
	public void setJp1() {
		GridBagLayout gbLayout=new GridBagLayout();
		jp1=new JPanel(gbLayout);
		
		JPanel Jtitle=new JPanel();		
		JLabel title=new JLabel("2048");
		title.setFont(new Font("font", Font.PLAIN, 45));//类型、风格、大小
		title.setHorizontalAlignment(JLabel.LEFT);//jLabel的文本左右对齐属性设置方法,对齐方式
		Jtitle.add(title);
		jp1.add(Jtitle);
		
		JPanel Jscroe=new JPanel(new GridLayout(2, 1));//new GridLayout(2, 1)为网格布局样式。其中的参数“2”“1”分别为网格的“行数”和“列数”。
		JLabel scroe=new JLabel("Scroe");
		scroe.setFont(new Font("font", Font.PLAIN, 16));
		scroe.setHorizontalAlignment(JLabel.CENTER);
		scroeValue=new JLabel("0");
		scroeValue.setFont(new Font("font", Font.PLAIN, 16));
		scroeValue.setHorizontalAlignment(JLabel.CENTER);
		Jscroe.add(scroe);
		Jscroe.add(scroeValue);
		jp1.add(Jscroe);
		
		JPanel Jnoite=new JPanel();
		JLabel noite=new JLabel("方向键移动数字累加至2048");
		noite.setFont(new Font("font", Font.PLAIN, 14));
		noite.setHorizontalAlignment(JLabel.LEFT);
		Jnoite.add(noite);
		jp1.add(Jnoite);
		
		JPanel JnewGame=new JPanel();
		JButton newGame=new JButton("New Game");
		newGame.setHorizontalAlignment(JButton.CENTER);
		newGame.addActionListener(this);
		JnewGame.add(newGame);
		jp1.add(JnewGame);
				
		GridBagConstraints gbc=new GridBagConstraints();		
		addc(jp1, Jtitle, gbc, 3, 2, 60, 60, 0, 0);
		addc(jp1, Jscroe, gbc, 0, 2, 40, 60, 3, 0);
		addc(jp1, Jnoite, gbc, 3, 1, 60, 40, 0, 2);
		addc(jp1, JnewGame, gbc, 0, 1, 40, 40, 3, 2);
	}
	
	public void setJp2() {
		addBlock();
		initBlock();
		initBlock();
	}
	
	/**
	 * 添加方块
	 */
	public void addBlock(){
		jp2=new JPanel();
		/*
		 * setLayout是对当前组件设置为流式布局.组件在窗体中从左到右依次排列 如果排到行的末尾 换行排列 
		 * GridLayout(int rows, int cols, int hgap, int vgap)
			创建具有指定行数和列数的网格布局。
			rows - 该 rows 具有表示任意行数的值
			cols - 该 cols 具有表示任意列数的值
			hgap - 水平间距
			vgap - 垂直间距
		 */
		jp2.setLayout(new GridLayout(4, 4, 5, 5));
		for (int i = 0; i < blocks.length; i++) {
			blocks[i]=new Block();
			blocks[i].setHorizontalAlignment(JLabel.CENTER);// 不透明的标签
			blocks[i].setOpaque(true);// 设置控件不透明
			jp2.add(blocks[i]);
		}
	}
	
	/**
	 * 初始化方块
	 */
	public void initBlock(){
		while (numFlag) {
			int index=(int) (Math.random()*16);
			if (blocks[index].getText().trim().equals("")) {
				blocks[index].setValue("2");
				break;
			} else {
				continue;
			}	
		}
	}
	
	/**
	 * 获得第一个子面板的高度
	 */
	public int getMyJPanelHeidth() {
		return jp1.getSize().height;
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO 自动生成的方法存根
		newGame();
	}
	
	/**
	 * 重新开始游戏
	 */	
	public void newGame() {
		for (int i = 0; i < blocks.length; i++) {			
			blocks[i].setValue("");			
		}
		numFlag=true;
		scroeValue.setText("0");
		initBlock();
		initBlock();
	}
}

业务逻辑类

public class Game2048Logic implements KeyListener{
	Block[] blocks;
	boolean numFlag;		// 用于判断是否还能加入新的数字
	JLabel scroeValue;		//显示分数
	int blocksarr[]=new int[4];		//保存一行/列方块中的数值
	JFrame myJFrame;
	int scroe=0;
	Game2048View game2048View;
	
	//初始化键盘事件
	public Game2048Logic(Game2048View game2048View, JFrame myJFrame, Block[] blocks,boolean numFlag,JLabel scroeValue) {
		// TODO 自动生成的构造函数存根
		this.blocks=blocks;
		this.numFlag=numFlag;
		this.scroeValue=scroeValue;
		this.myJFrame=myJFrame;
		this.game2048View=game2048View;
	}
	
	//初始化按钮事件
	public Game2048Logic() {
		// TODO 自动生成的构造函数存根
	}
	
	public boolean getnumFlag() {
		return numFlag;
	}

	@Override
	public void keyPressed(KeyEvent e) {
		// TODO 自动生成的方法存根
		int[] blocksarr=getBlock();
		switch (e.getKeyCode()) {
		case KeyEvent.VK_UP:
			colBlock("up");
			hasEmptyBlock();
			if (Arrays.equals(blocksarr, getBlock())) {
			} else {
				refershBlock();
			}			
			isGameFail("up");
			break;
		case KeyEvent.VK_DOWN:
			colBlock("down");
			hasEmptyBlock();
			if (Arrays.equals(blocksarr, getBlock())) {
			} else {
				refershBlock();
			}	
			isGameFail("down");
			break;
		case KeyEvent.VK_LEFT:
			rowBlock("left");
			hasEmptyBlock();
			if (Arrays.equals(blocksarr, getBlock())) {
			} else {
				refershBlock();
			}	
			isGameFail("left");
			break;
		case KeyEvent.VK_RIGHT:
			rowBlock("right");
			hasEmptyBlock();
			if (Arrays.equals(blocksarr, getBlock())) {
			} else {
				refershBlock();
			}	
			isGameFail("right");
			break;
		default:
			break;
		}
		scroeValue.setText(""+scroe);
		win();
	}
	
	/**
	 * 垂直方向方块移动处理函数
	 */
	public void colBlock(String direction){
		int tmp1=0;
		int tmp2=0;
		int index=0;
		for (int i = 0; i < 4; i++) {
			for (int j = 0; j < 4; j++) {
				if (blocks[tmp1].getText().trim().equals("")) {
					tmp1+=4;
					if (tmp1>=16) {
						break;
					} else {
						continue;
					}
				} else {
					blocksarr[index]=Integer.parseInt(blocks[tmp1].getText().trim());
					index+=1;
					tmp1+=4;
					if (tmp1>=16 || index>=4) {
						break;
					} else {
						continue;
					}
				}
			}
			switch (direction) {
			case "up":
				blocksarr=handleBlocksarr(blocksarr);
				break;
			case "down":
				blocksarr=reverseArr(handleBlocksarr(reverseArr(blocksarr)));
				break;
			default:
				break;
			}
			
			for (int n = 0; n < blocksarr.length; n++) {
				if (blocksarr[n]==0) {
					blocks[tmp2].setText("");
					blocks[tmp2].setBackground(Color.gray);
				} else {
					blocks[tmp2].setValue(blocksarr[n]+"");
				}
				tmp2+=4;
			}			
			index=0;
			tmp1=i+1;
			tmp2=i+1;
			//清空数组blockarr
			for (int n = 0; n < blocksarr.length; n++) {
				blocksarr[n]=0;				
			}
		}
	}
	
	/**
	 * 水平方向方块移动处理函数
	 */
	public void rowBlock(String direction) {
		int tmp1=0;
		int tmp2=0;
		int index=0;
		for (int i = 0; i < 4; i++) {
			for (int j = 0; j < 4; j++) {
				if (blocks[tmp1].getText().trim().equals("")) {
					tmp1+=1;
					if (tmp1>=16) {
						break;
					} else {
						continue;
					}
				} else {
					blocksarr[index]=Integer.parseInt(blocks[tmp1].getText().trim());
					index+=1;
					tmp1+=1;
					if (tmp1>=16 || index>=4) {
						break;
					} else {
						continue;
					}
				}
			}
			
			switch (direction) {
			case "left":
				blocksarr=handleBlocksarr(blocksarr);
				break;
			case "right":
				blocksarr=reverseArr(handleBlocksarr(reverseArr(blocksarr)));
				break;
			default:
				break;
			}
			
			for (int n = 0; n < blocksarr.length; n++) {
				if (blocksarr[n]==0) {
					blocks[tmp2].setText("");
					blocks[tmp2].setBackground(Color.gray);
				} else {
					blocks[tmp2].setValue(blocksarr[n]+"");
				}
				tmp2+=1;
			}			
			index=0;
			//清空数组blockarr
			for (int n = 0; n < blocksarr.length; n++) {
				blocksarr[n]=0;				
			}
		}		
	}
	
	/**
	 * 处理并返回一个数组
	 */
	public int[] handleBlocksarr(int[] blocksarr) {
		int index=0;
		int[] result=new int[4];
		for (int i = 0; i < blocksarr.length; i++) {			
			//排序
			if (blocksarr[i]!=0) {
				result[index]=blocksarr[i];
				index++;
			} 
		}
		if (index==0 || index==1) {
			for (int i = index; i < result.length; i++) {
				result[i]=0;
			}
		} else {
			for (int i = 0; i < blocksarr.length; i++) {
				blocksarr[i]=0;
			}
			switch (index) {
			case 2:
				if (result[0]==result[1]) {
					blocksarr[0]=result[0]+result[1];
					scroe+=result[0]*2;
				} else {
					blocksarr=result;
				}				
				break;
			case 3:
				if (result[0]==result[1]) {
					blocksarr[0]=result[0]+result[1];
					scroe+=result[0]*2;
					blocksarr[1]=result[2];
				} else {
					if (result[1]==result[2]) {
						blocksarr[0]=result[0];
						blocksarr[1]=result[1]+result[2];
						scroe+=result[1]*2;
					} else {
						blocksarr=result;
					}
				}
				break;
			case 4:
				if (result[0]==result[1]) {
					blocksarr[0]=result[0]+result[1];	
					scroe+=result[0]*2;
					if (result[2]==result[3]) {
						blocksarr[1]=result[2]+result[3];
						scroe+=result[2]*2;
					} else {
						blocksarr[1]=result[2];
						blocksarr[2]=result[3];
					}
				} else {
					if (result[1]==result[2]) {
						blocksarr[0]=result[0];
						blocksarr[1]=result[1]+result[2];
						scroe+=result[1]*2;
						blocksarr[2]=result[3];
					} else {
						blocksarr[0]=result[0];
						blocksarr[1]=result[1];
						if (result[2]==result[3]) {
							blocksarr[2]=result[2]+result[3];
							scroe+=result[2]*2;
						} else {
							blocksarr=result;
						}
					}
				}
				break;
			default:
				break;
			}
			result=blocksarr;
		}		
		return result;	
	}
	
	/**
	 * 反转数组eg:45000 --> 00054
	 */
	public int[] reverseArr(int[] arr) {
		int[] tmp=new int[arr.length];
		int index=arr.length-1;
		for (int i = 0; i < arr.length; i++) {
			tmp[index]=arr[i];
			index--;
		}
		return tmp;
	}
	
	/**
	 * 刷新方块,添加新出现的2或4
	 */
	public void refershBlock(){
		if (numFlag==false) {
		}
		while (numFlag) {
			int index=(int) (Math.random()*16);	
			if (blocks[index].getText().trim().equals("")) {
				if (Math.random()<0.8) {
					blocks[index].setValue("2");
				} else {
					blocks[index].setValue("4");
				}
				break;
			} else {
				continue;
			}	
		}
	}
	
	/**
	 * 判断是否有空的方块
	 */
	public void hasEmptyBlock() {
		for (int i = 0; i < blocks.length; i++) {
			if (blocks[i].getText().trim().equals("")) {
				this.numFlag=true;
				break;
			} else {
				this.numFlag=false;
			}
		}
	}
	
	/**
	 * 判断游戏是否失败
	 */
	public void isGameFail(String direction) {
		boolean result=true;	//true代表失败 false代表没有失败
		int tmp=0;
		if (numFlag == false) { // 表示没有空的方块
			switch (direction) {
			case "up":
			case "down":
				for (int i = 0; i < 4; i++) {
					tmp=i*4;
					for (int j = 0; j < 3; j++) {						
						if (blocks[tmp].getText().trim().equals(blocks[tmp+1].getText().trim())) {
							result = false;	//游戏未失败
							break;
						} else {
							tmp++;
						}
					}
					if (result==false) {
						break;
					}
				}
				break;
			case "left":
			case "right":
				for (int i = 0; i < 4; i++) {
					for (int j = 0; j < 3; j++) {						
						if (blocks[tmp].getText().trim().equals(blocks[tmp+4].getText().trim())) {
							result = false;	//游戏未失败
							break;
						} else {
							tmp+=4;
							if (tmp>=16) {
								break;
							} else {
								continue;
							}
						}
					}
					tmp=i+1;
					if (result==false) {
						break;
					}
				}
				break;
			default:
				break;
			}
		} else {
			result=false;
		}
		if (result==true) {
			JOptionPane.showMessageDialog( null , "Game Over",null , JOptionPane.ERROR_MESSAGE) ;
			game2048View.newGame();
		} else {
		}
	}
	
	/**
	 * 判断游戏是否成功,即成功累加至2048
	 */
	public void win() {
		for (int i = 0; i < blocks.length; i++) {
			if (blocks[i].getText().trim().equals("2048")) {
				JOptionPane.showMessageDialog( null , "YOU ARE WIN",null , JOptionPane.ERROR_MESSAGE) ;
				game2048View.newGame();
				break;
			} 
		}		
	}
	
	/**
	 * 获得全部方块内容,用于对比
	 */
	public int[] getBlock() {
		int[] blocksarr=new int[16];
		for (int i = 0; i < blocks.length; i++) {
			if (blocks[i].getText().trim().equals("")) {
				blocksarr[i]=0;
			} else {
				blocksarr[i]=Integer.parseInt(blocks[i].getText().trim());
			}			
		}
		return blocksarr;
	}
	
	@Override
	public void keyReleased(KeyEvent e) {
		// TODO 自动生成的方法存根
	}

	@Override
	public void keyTyped(KeyEvent e) {
		// TODO 自动生成的方法存根
	}

}

总结

通过此次的《2048游戏》游戏实现,让我对swing的相关知识有了进一步的了解,对java这门语言也有了比以前更深刻的认识。

java的一些基本语法,比如数据类型、运算符、程序流程控制和数组等,理解更加透彻。java最核心的核心就是面向对象思想,对于这一个概念,终于悟到了一些。

源码获取

源码下载地址:传送门------->

点赞,关注博主后,私聊博主免费获取
需要技术指导,写项目程序,等更多服务请联系博主

今天是持续写作的第 14 / 100 天。
可以关注我,点赞我、评论我、收藏我啦。文章来源地址https://www.toymoban.com/news/detail-503356.html

到了这里,关于JAVA 实现《2048游戏》游戏的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 用JAVA写一个2048的小游戏。

    如图所示: 使用软件:eclipse2021-12版 JDK版本:JDK15.0.1 链接:https://pan.baidu.com/s/1NVWaklg9K2wRmBOLew6iMQ 提取码:ts08 1. Client.java: 2.Constant.java 3.Block.java 4.BlockLoader.java 5.Drawable.java 6.Moveable.java 7.MyFrame.java 提示:代码写的有些臃肿,其中也有一些BUG,理解源码以后可以修正。 链接:

    2024年02月10日
    浏览(87)
  • python小游戏 2048小游戏设计与实现

    🔥 Hi,各位同学好呀,这里是L学长! 🥇今天向大家分享一个今年(2022)最新完成的毕业设计项目作品 python小游戏毕设 2048小游戏设计与实现 (源码) 🥇 学长根据实现的难度和等级对项目进行评分(最低0分,满分5分) 难度系数:3分 工作量:3分 创新点:4分 今天我们用python实现

    2024年02月11日
    浏览(53)
  • python快速实现2048小游戏

    《2048》是一款比较流行的数字游戏,最早于2014年3月20日发行。原版2048首先在GitHub上发布,原作者是Gabriele Cirulli,后被移植到各个平台。这款游戏是基于《1024》和《小3传奇》的玩法开发而成的新型数字游戏。 操作指南: 每次可以选择上下左右其中一个方向去滑动,每滑动

    2024年02月11日
    浏览(40)
  • python小游戏毕设 2048小游戏设计与实现 (源码)

    🔥 Hi,各位同学好呀,这里是L学长! 🥇今天向大家分享一个今年(2022)最新完成的毕业设计项目作品 python小游戏毕设 2048小游戏设计与实现 (源码) 🥇 学长根据实现的难度和等级对项目进行评分(最低0分,满分5分) 难度系数:3分 工作量:3分 创新点:4分 项目获取: https://

    2024年02月12日
    浏览(45)
  • python项目分享 2048小游戏设计与实现 (源码)

    🔥 Hi,各位同学好呀,这里是L学长! 🥇今天向大家分享一个今年(2022)最新完成的毕业设计项目作品 python小游戏毕设 2048小游戏设计与实现 (源码) 🥇 学长根据实现的难度和等级对项目进行评分(最低0分,满分5分) 难度系数:3分 工作量:3分 创新点:4分 项目获取: https://

    2024年01月18日
    浏览(46)
  • python项目分享 - 2048小游戏设计与实现 (源码)

    🔥 Hi,各位同学好呀,这里是L学长! 🥇今天向大家分享一个今年(2022)最新完成的毕业设计项目作品 python小游戏毕设 2048小游戏设计与实现 (源码) 🥇 学长根据实现的难度和等级对项目进行评分(最低0分,满分5分) 难度系数:3分 工作量:3分 创新点:4分 项目获取: https://

    2024年01月18日
    浏览(52)
  • 手把手教你用Python实现2048小游戏

    感觉好久没有写小游戏玩了,今天恰巧有空.这次我来用Python做个2048小游戏吧.废话不多说,文中有非常详细的代码示例,需要的朋友可以参考下 目录 一、开发环境 二、环境搭建 三、原理介绍 四、效果图 Python版本:3.6.4 相关模块: pygame模块; 以及一些Python自带的模块。 安装

    2024年04月28日
    浏览(69)
  • 【C/C++小游戏】2048 大作战!(基于Easyx图形窗口实现)

    写在前面 游戏简介 Easyx 图形库 编写游戏 预编译代码 第一步:初始化棋盘 第二步:绘制棋盘 第三步:用户操作 第四步:封装函数 完整代码 效果展示 大家好! 本人是一个12岁六年级小学生,今年9月开始学习C++,曾经学过1年Python。 这是我的第一篇博客,决定分享一个游戏

    2024年02月10日
    浏览(43)
  • vue3+uniapp在微信小程序实现一个2048小游戏

    微信小程序搜索《静远的工具箱》:偶数求和那个功能

    2024年04月12日
    浏览(61)
  • 分别用python和go语言来实现的风靡一时的2048 游戏,包含完整代码

    2048 游戏实现主要包括以下几个步骤: 创建一个棋盘,通常使用二维列表表示。 实现棋子的移动规则,左移、右移、上移、下移。 判断游戏是否结束,即棋盘是否已满或者无空位可移动。 实现游戏界面的显示。 下面是一个简单的 Python 实现示例,运行效果如下:

    2024年02月13日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包