热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

教你怎么用Java开发扫雷游戏

我们那时候上机经常玩扫雷,试想如果我当年可以用java写个扫雷出来,那场面不用我多说了吧,大家让开,我要开始装逼了,之前用JavaScript写过了一个扫雷,这次我用java再写了一遍,权当是复习咯.文中有非常详细的代码示例,需要的朋友可以参考下

一、效果图

      

二、实现思路

1.界面上可以点开的各种实际都是按钮,创建9行9列的二维数组,然后根据这个数组来创建JButton。

2.对应创建二维数组data,用来存取数据,0表示周围无雷,-1表示当前是雷,其他数字表示周围雷的数量。

3.对应创建二维数组state,用来存取按钮状态,0未打开,1 打开  2旗子  3 未知(控制显示对应的图标)

4.设置雷:随机行数 i 和列数 j,根据随机到 i、j 从二维数组data中取出对应的元素值,若值不为-1(不是雷),则将此元素data[i][j]设置为-1,若值是-1(已经是雷了),则跳过,不管是否跳过都进行递归,直到雷的数量达到设定的最大数量,跳出递归。

5.设置周围雷的数量:计算每个元素周围的雷数量(周围指的是 左上、上、右上、右、右下、下、左下、左 这8个位置),循环二维数组data,判断当前值不是-1,则需要计算周围雷的数量,等会细说。

6.有任一格子被揭开,则游戏开始并且计时,当格子被揭开的时候分3种情况

(1)格子是雷,执行爆炸动画,游戏结束。

(2)当前格子周围有雷,则仅仅打开此格子,对应显示周围雷数量的数字图片。

(3)当前格子不是雷且周围没有雷(data取到的元素值为0),则依次打开周围,并且被打开的周围元素也没有雷的情况下,继续打开(递归)。

7.右键可以进行插小旗、打问号等操作(对数组state进行的操作)。

三、代码实现

3.1 设置头部

//设置头部
private void setHeader() {
	Container cOntainer= new Container();
	container.setLayout(new GridLayout(1, 3));
	
	timeJLabel = new JLabel("时间:"+time,JLabel.CENTER);
	timeJLabel.setForeground(Color.DARK_GRAY);
	timeJLabel.setFont(new Font("微软雅黑",Font.BOLD, 16));
	
	leiJLabel = new JLabel("雷:"+curLeiCount,JLabel.CENTER);
	leiJLabel.setForeground(Color.DARK_GRAY);
	leiJLabel.setFont(new Font("微软雅黑",Font.BOLD, 16));
	
	reStart = new JButton((ImageIcon)imageMap.get(21));
	Dimension preferredSize = new Dimension(100,40);
	reStart.setPreferredSize(preferredSize);
	reStart.addActionListener(this);
	
	//注意添加顺序
	container.add(timeJLabel);
	container.add(reStart);
	container.add(leiJLabel);
	
	mainFrame.add(container,BorderLayout.NORTH);
}

3.2 设置游戏区域按钮

1.创建容器,并采用GridLayout 布局。

2.根据设定的ROWS、COLS创建二维数组,数组存储JButton,给每个按钮设置图标。

3.给每个按钮添加鼠标点击事件,右键事件。

private void setButtons() {
	Container cOntainer= new Container();
	container.setLayout(new GridLayout(ROWS, COLS));
	ImageIcon icon=null;
	for (int i = 0; i 

 

3.3 设置雷

1.随机行数 i 和列数 j,根据随机到 i、j 从二维数组data中取出对应的元素值。

2.判断值,若值不为-1(不是雷),则将此元素data[i][j]设置为-1,若值是-1(已经是雷了),则跳过。

3.不管上一步是否跳过都进行递归,直到雷数量达到设定的最大数量,跳出递归。

private void setLei() {
	if(computedLeiCount==LEICOUNT){//如果达到雷的最大数量则跳出
		return;			
	}	
	Random random = new Random();
	int r = random.nextInt(ROWS);
	int c = random.nextInt(COLS);
	
	//0 无; -1表示雷 ; 其他表示周围的雷数量
	if(data[r][c]!=-1){//如果不是雷则设置为雷
		data[r][c]=-1;
		computedLeiCount++;
	}
	setLei();//递归调用
}

3.4 计算周围雷的数量并显示

1.循环之前的二维数组data,元素值是-1(雷)跳过,不是-1则继续。

2.如果当前元素的下标是(i,j),则左上为(i-1,j-1),上为(i-1,j ),右上为(i-1,j+1),以此类推,如下图所示:

3.分别取出这8个元素,并判断他们是不是雷,如果是则计数累加,最后把这个计数赋值给元素data[i][j]。

//设置周围雷的数量
private void setAroundLei() {
	for (int i = 0; i =0 && cj>=0){
		if(data[ci][cj]==-1){
			count++;
		}
	}
	//上
	ci = i-1;
	cj = j;
	if(ci>=0){
		if(data[ci][cj]==-1){
			count++;
		}
	}
	//右上
	ci = i-1;
	cj = j+1;
	if(ci>=0 && cj=0){
		if(data[ci][cj]==-1){
			count++;
		}
	}
	//左
	ci = i;
	cj = j-1;
	if(cj >= 0){
		if(data[ci][cj]==-1){
			count++;
		}
	}
	return count;
}

3.5 添加点击事件

1.让代码实现 ActionListener

2.重写方法actionPerformed,获取点击的按钮进行揭开操作(分3种情况):

(1)格子是雷,执行爆炸动画,游戏结束。

(2)当前格子周围有雷,则仅仅打开此格子,显示周围雷数量的数字图片。

(3)当前格子不是雷且周围没有雷(data取到的元素值为0),则依次打开周围,并且被打开的周围元素也没有雷的情况下,继续打开(递归)。

3.6 打开指定按钮

//打开指定的button
private void open(int i,int j) {
	JButton button = btns[i][j];
	if(state[i][j]==1){//已经打开直接返回
		return ;
	}
	state[i][j]=1;//设置打开状态
	int num = data[i][j];
	if(num==-1){//直接使用雷的图片
		setBtnImage(button,(ImageIcon)imageMap.get(18));
		//游戏结束,并爆炸
		boom(button);
	}else{//如果当前不是雷,显示对应数字类图片
		if(num==0){
			num=9;
			//显示周围的图标,并且递归
			openAround(i,j);
		}
		setBtnImage(button,(ImageIcon)imageMap.get(num));
		setBtnEnabled(button,false);//按钮被打开设置不能再点击了
		
		//判定是否成功
		successOrNot(1);
	}
}

3.7 触雷爆炸

爆炸采用线程来执行,就是切换图片,图片切换到最后一张后线程结束,回调定义好的方法进行结束提示、打开所有格子等操作。

//爆炸效果
private void boom(JButton button) {
	flag=true;
	
	GameRunnable gameRunnable = new GameRunnable();
	gameRunnable.setParam(button, boomImageMap,this);
	thread = new Thread(gameRunnable);
	thread.start();
}
//爆炸回调方法
public void reback(JButton button) {
	setBtnImage(button,(ImageIcon)imageMap.get(18));
	flag=false;
	
	//设置全部按钮打开
	openAll();
	//弹出结束提示
	UIManager.put("OptionPane.buttonFont", new FontUIResource(new Font("宋体", Font.ITALIC, 13)));
	UIManager.put("OptionPane.messageFont", new FontUIResource(new Font("宋体", Font.ITALIC, 13)));
	JOptionPane.showMessageDialog(mainFrame, "你失败了!点击上方按钮重新开始");
}

3.8 递归打开周围

//打开周围
private void openAround(int i,int j) {
	//左上
	int ci = i-1;
	int cj = j-1;
	if(ci>=0 && cj>=0){
		open(ci,cj);
	}
	//上
	ci = i-1;
	cj = j;
	if(ci>=0){
		open(ci,cj);
	}
	//右上
	ci = i-1;
	cj = j+1;
	if(ci>=0 && cj=0){
		open(ci,cj);
	}
	//左
	ci = i;
	cj = j-1;
	if(cj >= 0){
		open(ci,cj);
	}
}

 

3.9 鼠标右键事件

1.实现MouseListener,重写mouseClicked方法。

2.如果按钮是未打开状态则设置为旗子(设置state数组对应的元素值:2)。

3.如果按钮是旗子状态则设置为未知(设置state数组对应的元素值:3)。

4.如果按钮是未知状态则设置为原来的状态未打开(设置state数组对应的元素值:0)。

//鼠标右键的处理
@Override
public void mouseClicked(MouseEvent e) {
	if(e.getButton()==MouseEvent.BUTTON3){
		JButton button = (JButton)e.getSource();
		for (int i = 0; i 

四、胜利判定

1.判断旗子的位置是不是正确的雷,并统计数量,如果统计到的数量刚好和设定的雷总数一样,证明雷全部被查出了,判定为胜利。

2.如果未打开的数量与设定雷的总数一样,也判定为胜利。

//判断是否成功 参数type=2表示判断右键插旗子,参数 type=其他  表示判断鼠标点击
private void successOrNot(int type) {
	int count=0;
	if(type==2){
		/*
		 * 1.判断旗子的位置是否是正确的雷,并统计数量
		 * 2.如果统计到的数量刚好和雷的总数一样,证明全部被查出了,判定为胜利
		*/
		for (int i = 0; i 

最后加入重新开始事件就完成了。

重新开始就是重新设置相关参数。

//重新开始游戏
private void restart() {
	//关闭计时线程(可能正在进行游戏,所以要把计时线程关闭)
	gameTimeRunnable.setFlag(false);
	
	startFlag=false;
	computedLeiCount=0;
	
	curLeiCount=10;
	leiJLabel.setText("雷:"+curLeiCount);
	time=0;
	timeJLabel.setText("时间:"+time);
	
	data= new int[ROWS][COLS];//存取数据
	state= new int[ROWS][COLS];//存取打开状态,0未打开,1 打开
	setLei();
	setAroundLei();
	
	ImageIcon icon = null;
	for (int i = 0; i 

到此这篇关于教你怎么用Java开发扫雷游戏的文章就介绍到这了,更多相关Java扫雷游戏内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!


推荐阅读
  • 使用Spring AOP实现切面编程的步骤和注意事项
    本文介绍了使用Spring AOP实现切面编程的步骤和注意事项。首先解释了@EnableAspectJAutoProxy、@Aspect、@Pointcut等注解的作用,并介绍了实现AOP功能的方法。然后详细介绍了创建切面、编写测试代码的过程,并展示了测试结果。接着讲解了关于环绕通知的使用方法,并修改了FirstTangent类以添加环绕通知方法。最后介绍了利用AOP拦截注解的方法,只需修改全局切入点即可实现。使用Spring AOP进行切面编程可以方便地实现对代码的增强和拦截。 ... [详细]
  • 顶新国际PMI集团与美云智数再次携手,共同开启“数智化”采购的新篇章。顶新国际集团作为中国领先的综合食品企业,成立于1958年,旗下品牌包括著名的方便面品牌康师傅、快餐品牌德克士以及开创中国便利店先河的全家FamilyMart。此次合作将借助美云智数在数字化转型领域的专业优势,进一步提升顶新国际的供应链管理效率和智能化水平,推动其在竞争激烈的市场环境中实现可持续发展。 ... [详细]
  • 在处理 GridView 中的行记录时,有时需要动态地添加或删除行,而无需对数据库中的实际数据进行任何更改。本文介绍了如何实现这一功能,确保操作仅限于前端展示层面,而不影响后端数据库的完整性。通过这种方法,用户可以在不修改数据库记录的情况下,灵活地管理 GridView 中的数据展示。 ... [详细]
  • 在C#和ASP.NET开发中,TypeParse 是一个非常实用的类型解析扩展方法库,提供了简便的类型转换功能。例如,通过 `var int1 = "12".TryToInt();` 可以将字符串安全地转换为整数,如果转换失败则返回0。此外,还支持更多复杂的类型转换场景,如 `var int2 = "22x".TryToInt();` 和 `var int3 = "3.14".TryToInt();`,确保了代码的健壮性和易用性。 ... [详细]
  • 本文深入探讨了 C# 中 `SqlCommand` 和 `SqlDataAdapter` 的核心差异及其应用场景。`SqlCommand` 主要用于执行单一的 SQL 命令,并通过 `DataReader` 获取结果,具有较高的执行效率,但灵活性较低。相比之下,`SqlDataAdapter` 则适用于复杂的数据操作,通过 `DataSet` 提供了更多的数据处理功能,如数据填充、更新和批量操作,更适合需要频繁数据交互的场景。 ... [详细]
  • 在 Asp.net 应用中,动态加载 DropDownList 控件的数据源是一项常见需求。本文探讨了如何高效地从数据库中获取数据,并实时更新下拉列表,确保用户界面始终与后台数据保持同步。通过使用 ADO.NET 和 LINQ to SQL 技术,开发者可以轻松实现这一功能,同时提高应用的性能和用户体验。文中还提供了代码示例和最佳实践,帮助开发者解决常见的数据绑定问题。 ... [详细]
  • c#中Excel数据的导入、导出
    **导出到Excel文件含完整路径含字段标题 ... [详细]
  • nsitionalENhttp:www.w3.orgTRxhtml1DTDxhtml1-transitional.dtd ... [详细]
  • 1.方法一:采用OleDB读取EXCEL文件:把EXCEL文件当做一个数据源来进行数据的读取操作,实例如下:publicDa ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • 本文介绍了Windows操作系统的版本及其特点,包括Windows 7系统的6个版本:Starter、Home Basic、Home Premium、Professional、Enterprise、Ultimate。Windows操作系统是微软公司研发的一套操作系统,具有人机操作性优异、支持的应用软件较多、对硬件支持良好等优点。Windows 7 Starter是功能最少的版本,缺乏Aero特效功能,没有64位支持,最初设计不能同时运行三个以上应用程序。 ... [详细]
  • 解决.net项目中未注册“microsoft.ACE.oledb.12.0”提供程序的方法
    在开发.net项目中,通过microsoft.ACE.oledb读取excel文件信息时,报错“未在本地计算机上注册“microsoft.ACE.oledb.12.0”提供程序”。本文提供了解决这个问题的方法,包括错误描述和代码示例。通过注册提供程序和修改连接字符串,可以成功读取excel文件信息。 ... [详细]
  • 手把手教你使用GraphPad Prism和Excel绘制回归分析结果的森林图
    本文介绍了使用GraphPad Prism和Excel绘制回归分析结果的森林图的方法。通过展示森林图,可以更加直观地将回归分析结果可视化。GraphPad Prism是一款专门为医学专业人士设计的绘图软件,同时也兼顾统计分析的功能,操作便捷,可以帮助科研人员轻松绘制出高质量的专业图形。文章以一篇发表在JACC杂志上的研究为例,利用其中的多因素回归分析结果来绘制森林图。通过本文的指导,读者可以学会如何使用GraphPad Prism和Excel绘制回归分析结果的森林图。 ... [详细]
  • SeMITechnologies正在使用矢量搜索引擎Weaviate构建的内容。SeMI的首席执行官兼联合创始人BobvanLuijt说,它是一种独特的AI优先数据库,使用机器学习 ... [详细]
  • OleDbDataAdapter充当DataSet和数据源之间的桥梁,用于检索和保存数据。OleDbDataAdapter通过以下方法提供这个桥接器:使用Fill将数据从数 ... [详细]
author-avatar
手机用户2602921437_525
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有