Java课程设计——扫雷游戏程序

1. 人员分工

组员职务分工
潘鋆祥组长顶层格子的代码设计,界面UI设计
覃小杰组员扫雷素材的搜集,底层雷的代码设计

2.前期调查

扫雷截图

游戏详情

以windows 7自带扫雷为例。游戏区包括雷区、地雷计数器和计时器,确定大小的矩形雷区中随机布置一定数量的地雷(初级为99个方块10个雷,中级为1616个方块40个雷,高级为16*30个方块99个雷),玩家需要尽快找出雷区中的所有不是地雷的方块,而不许踩到地雷。

游戏的基本操作包括左键单击、右键单击、双击三种。其中左键用于打开安全的格子,推进游戏进度;右键用于标记地雷,以辅助判断,或为接下来的双击做准备;双击在一个数字周围的地雷标记完时,相当于对数字周围未打开的方块均进行一次左键单击操作:

左键单击:

在判断出不是雷的方块上按下左键,可以打开该方块。如果方块上出现数字,则该数字表示其周围3×3区域中的地雷数(一般为8个格子,对于边块为5个格子,对于角块为3个格子。所以扫雷中最大的数字为8);如果方块上为空(相当于0),则可以递归地打开与空相邻的方块;如果不幸触雷,则游戏结束。

右键单击:

在判断为地雷的方块上按下右键,可以标记地雷(显示为小红旗)。重复操作可取消标记

双击:

同时按下左键和右键完成双击。当双击位置周围已标记雷数等于该位置数字时操作有效,相当于对该数字周围未打开的方块均进行一次左键单击操作。地雷未标记完全时使用双击无效。若数字周围有标错的地雷,则游戏结束,标错的地雷上会显示一个“ ×”。

3.需求分析

3.1系统数据分析

扫雷雷区是一个二维区间,所以需要一个二维数组进行存储数据,而其中又分为了底层跟上层,底层用于存储雷跟数字,上层用于翻开格子,插旗等操作。
若翻开的格子下是雷,则判定失败;若全局中未翻开的格子数(包括插旗的格子)等于雷数,则默认将所有未翻开的格子插旗,且判定胜利。

3.2系统操作分析

进行左键右键操作的时候,我们需要对鼠标进行监听,若鼠标左键或右键点击,则读取鼠标的横纵坐标,然后通过换算之后,换算成鼠标点击的对应格子的二维数组坐标,然后在二维数组中对其进行操作。因为双击的操作过于繁琐,我们用右键进行替代,若右键点击到的是已被翻开的格子,则判定原本扫雷中的双击操作;若右键点击的是未翻开的格子,则进行插旗操作。

3.3系统界面分析

需要有能进行难度选择的按钮,难度选择后能确确实实地改变雷数与格子数,且窗口的大小能根据难度的变化进行相应的变大缩小,需要有能实时变化的地雷计数器和计时器,且能给与出随时重置游戏的按钮。

4.流程图

在这里插入图片描述
在这里插入图片描述

5.游戏运行截图

难度选择

在这里插入图片描述

简单难度

在这里插入图片描述

成功判定

在这里插入图片描述

失败判定

在这里插入图片描述

普通难度

在这里插入图片描述

困难难度

在这里插入图片描述

6.关键代码

主页面代码(包括鼠标监听)

public class GameWin extends JFrame{
	int wide = 2*GameUtil.offset + GameUtil.wide*GameUtil.squareLength;
	int high = 2*GameUtil.offset + GameUtil.high*GameUtil.squareLength;
	Image offScreenImage = null;
	
	Map map = new Map();
	MapTop mapTop = new MapTop();
	GameSelect gameSelect = new GameSelect();
	
	boolean begin=false;
	void mainPage() {
		GameUtil.start_time=System.currentTimeMillis();
		this.setVisible(true);
		if(GameUtil.state==3)
		{
			this.setSize(500,500);
		}
		else
		{
			this.setSize(wide,high);
		}
		
		this.setTitle("扫雷游戏");
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		this.addMouseListener(new MouseAdapter()
		{
			public void mouseClicked(MouseEvent e)
			{
				super.mouseClicked(e);
				switch(GameUtil.state)
				{
				case 0: if(e.getButton()==1)
				{
					GameUtil.Mouse_x=e.getX();
					GameUtil.Mouse_y=e.getY();
					GameUtil.left = true;
					
				}
				if(e.getButton()==3)
				{
					GameUtil.Mouse_x=e.getX();
					GameUtil.Mouse_y=e.getY();
					GameUtil.right = true;
				}
					
				case 1:  
				case 2: 
					if(e.getButton()==1)
					{
						if(e.getX()>GameUtil.offset +GameUtil.squareLength*(GameUtil.wide/2)&&
								e.getX()<GameUtil.offset +GameUtil.squareLength*(GameUtil.wide/2)+GameUtil.squareLength*2
								&&e.getY()>GameUtil.offset/3
								&&e.getY()<GameUtil.offset+GameUtil.squareLength)
						{
							map.reGame();
							mapTop.reGame();
							GameUtil.flag_num=0;
							GameUtil.start_time=System.currentTimeMillis();
							GameUtil.state =0;
						}
					}
					break;
				case 3:
					if(e.getButton()==1)
					{
						GameUtil.Mouse_x=e.getX();
						GameUtil.Mouse_y=e.getY();
						begin = gameSelect.hard();
						
					}
				default : 
				}
				
				
			}
		});
		while(true)
		{
			repaint();
			begin();
			try {
				Thread.sleep(40);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	void begin()
	{
		if(begin)
		{
			begin=false;
			gameSelect.hard(GameUtil.level);
			dispose();
			GameWin gameWin = new GameWin();
			GameUtil.start_time = System.currentTimeMillis();
			GameUtil.flag_num=0;
			map.reGame();
			mapTop.reGame();
			gameWin.mainPage();
		}
	}
	public void paint(Graphics g)
	{
		if(GameUtil.state==3)
		{
			g.setColor(Color.white);
			g.fillRect(0,0,500,500);
			gameSelect.paintSelf(g);
		}
		else
		{
		offScreenImage = this.createImage(wide,high);
		Graphics gImage = offScreenImage.getGraphics();
		
		map.paintMap(gImage);
		mapTop.paintMap(gImage);
		g.drawImage(offScreenImage,0,0,null);
		}
		
	}
	public static void main(String[] args)
	{
		GameWin gameWin = new GameWin();
		gameWin.mainPage();
	}

}

底层雷区绘制

public class Map {
	BottomMine bottomMine = new BottomMine();
	BottomNum bottomNum = new BottomNum();
	{
		bottomMine.newMines();
		bottomNum.newNum();
	}
	void reGame()
	{
		for(int i = 1;i <=GameUtil.wide;i++)
		{
			for(int j = 1; j<=GameUtil.high; j++)
			{
				GameUtil.bottom[i][j]=0;
				
			}
		}
		bottomMine.newMines();
		bottomNum.newNum();
	}
	void paintMap(Graphics g)
	{
		
		for(int i=0;i<=GameUtil.wide;i++)
		{
			g.setColor(Color.white);
			g.drawLine(GameUtil.offset+i*GameUtil.squareLength, 
					GameUtil.offset, 
					GameUtil.offset+i*GameUtil.squareLength, 
					GameUtil.offset+GameUtil.high*GameUtil.squareLength);
		}
		for(int i = 0;i<=GameUtil.high;i++)
		{
			g.setColor(Color.white);
			g.drawLine(GameUtil.offset, 
					GameUtil.offset+i*GameUtil.squareLength, 
					GameUtil.offset+GameUtil.wide*GameUtil.squareLength, 
					GameUtil.offset+i*GameUtil.squareLength);
		}
		for(int i = 1;i<=GameUtil.wide;i++)
		{
			for(int j=1;j<=GameUtil.high;j++)
			{
				if(GameUtil.bottom[i][j]==-1) {
				g.drawImage(GameUtil.Mine,
						GameUtil.offset+(i-1)*GameUtil.squareLength+1,
						GameUtil.offset+(j-1)*GameUtil.squareLength+1,
						GameUtil.squareLength-2,
						GameUtil.squareLength-2,
						null);
				}
				if(GameUtil.bottom[i][j]>=0) {
					g.drawImage(GameUtil.images[GameUtil.bottom[i][j]],
							GameUtil.offset+(i-1)*GameUtil.squareLength+1,
							GameUtil.offset+(j-1)*GameUtil.squareLength+1,
							GameUtil.squareLength-2,
							GameUtil.squareLength-2,
							null);
					}
			}
		}
		GameUtil.drawWord(g, ""+(GameUtil.Mine_max-GameUtil.flag_num), GameUtil.offset+GameUtil.squareLength*(GameUtil.wide-1),
				GameUtil.offset/2, 30, Color.black);
		GameUtil.drawWord(g, ""+(GameUtil.end_time-GameUtil.start_time)/1000  , GameUtil.offset, GameUtil.offset/2, 30, Color.black);
		switch (GameUtil.state) {
		case 0 :
			GameUtil.end_time=System.currentTimeMillis();
			g.drawImage(GameUtil.face, 
					GameUtil.offset+GameUtil.squareLength*(GameUtil.wide/2),
					GameUtil.offset/3,
					null);
			break;
		case 1 :
			g.drawImage(GameUtil.win, 
					GameUtil.offset+GameUtil.squareLength*(GameUtil.wide/2),
					GameUtil.offset/3,
					null);
			break;
		case 2:
			g.drawImage(GameUtil.over, 
					GameUtil.offset+GameUtil.squareLength*(GameUtil.wide/2),
					GameUtil.offset/3,
					null);
			break;
			
			default:
		}
	}
	

}


顶层方格的绘制

import java.awt.Color;
import java.awt.Graphics;
import java.security.KeyManagementException;

public class MapTop {

	int temp_x;
	int temp_y;
	void reGame()
	{
		for(int i = 1;i <=GameUtil.wide;i++)
		{
			for(int j = 1; j<=GameUtil.high; j++)
			{
				GameUtil.Data[i][j]=0;
			}
		}
	}
	void logic()
	{
		temp_x = 0;
		temp_y = 0;
		
		
		
		if (GameUtil.Mouse_x>GameUtil.offset&&GameUtil.Mouse_y>GameUtil.offset)
		{
			temp_x = (GameUtil.Mouse_x-GameUtil.offset)/GameUtil.squareLength+1;
			temp_y = (GameUtil.Mouse_y-GameUtil.offset)/GameUtil.squareLength+1;
		}
		
		if(temp_x>=1&&temp_x<=GameUtil.wide
				&&temp_y>=1&&temp_y<=GameUtil.high)
		{
			
		
			if(GameUtil.left)
			{
				if(GameUtil.Data[temp_x][temp_y]==0)
				{
					GameUtil.Data[temp_x][temp_y]=-1;
				}
				spaceOpen(temp_x,temp_y);
				GameUtil.left = false;
			}
			if(GameUtil.right)
			{
				if(GameUtil.Data[temp_x][temp_y]==0)
				{
					GameUtil.Data[temp_x][temp_y]=1;
					GameUtil.flag_num++;
				}
				else if(GameUtil.Data[temp_x][temp_y]==1)
				{
					GameUtil.Data[temp_x][temp_y]=0;
					GameUtil.flag_num--;
				}
				else if(GameUtil.Data[temp_x][temp_y]==-1)
				{
					numOpen(temp_x,temp_y);
				}
				GameUtil.right = false;
			}
		}
		boom();
		victory();
	}
	boolean victory()
	{
		int count = 0;
		for(int i = 1; i<=GameUtil.wide; i++)
		{
			for(int j = 1; j<=GameUtil.high;j++)
			{
				if(GameUtil.Data[i][j]!=-1)
				{
					count++;
					
				}
			}
		}
		if(count==GameUtil.Mine_max)
		{
			GameUtil.state=1;
			for(int i = 1; i<=GameUtil.wide; i++)
			{
				for(int j = 1;j<=GameUtil.high;j++)
				{
					
					if(GameUtil.Data[i][j]==0)
					{
						GameUtil.Data[i][j]=1;
					}
				}
			}
			return true;
			
		}
		return false;
	}
	void seeBoom()
	{
		for(int i = 1; i<=GameUtil.wide; i++)
		{
			for(int j = 1; j<=GameUtil.high;j++)
			{
				if(GameUtil.bottom[i][j]==-1&&GameUtil.Data[i][j]!=1)
				{
					GameUtil.Data[i][j]=-1;
				}
				if(GameUtil.bottom[i][j]!=-1&&GameUtil.Data[i][j]==1)
				{
					GameUtil.Data[i][j]=2;
				}
			}
		}
	}
	boolean boom()
	{
		for(int i = 1; i<=GameUtil.wide; i++)
		{
			for(int j = 1; j<=GameUtil.high;j++)
			{
				if(GameUtil.bottom[i][j]==-1&&GameUtil.Data[i][j]==-1)
				{
					GameUtil.state=2;
					seeBoom();
					return true;
				}
			}
		}
		return false;
	}
	void numOpen(int x, int y)
	{
		int count=0;
		if(GameUtil.bottom[x][y]>0)
		{
			for(int i =	x-1; i<=x+1;i++)
			{
				for(int j=y-1;j<=y+1;j++)
				{
					if(GameUtil.Data[i][j]==1)
					{
						count++;
					}
				}
			}
			if(count==GameUtil.bottom[x][y])
			{
				for(int i =	x-1; i<=x+1;i++)
				{
					for(int j=y-1;j<=y+1;j++)
					{
						if(GameUtil.Data[i][j]!=1)
						{
							GameUtil.Data[i][j]=-1;
						}
						if(i>=1&&j>=1&&i<=GameUtil.wide&&j<=GameUtil.high)
						{
							spaceOpen(i,j);
						} 
					}
					
				}
			}
		}
	}
	void spaceOpen(int x,int y)
	{
		if(GameUtil.bottom[x][y]==0)
		{
			for(int i =	x-1; i<=x+1;i++)
			{
				for(int j=y-1;j<=y+1;j++)
				{
					if(GameUtil.Data[i][j]!=-1)
					{
						if(GameUtil.Data[i][j]==1)
						{
							GameUtil.flag_num--;
						}
						GameUtil.Data[i][j]=-1;
						if(i>=1&&j>=1&&i<=GameUtil.wide&&j<=GameUtil.high)
						{
							spaceOpen(i,j);
						}
						
					}
					
				}
			}
		}
	}
	void paintMap(Graphics g)
	{
		logic();
		
		for(int i = 1;i<=GameUtil.wide;i++)
		{
			for(int j=1;j<=GameUtil.high;j++)
			{
				if(GameUtil.Data[i][j]==0) {
				g.drawImage(GameUtil.unknown,
						GameUtil.offset+(i-1)*GameUtil.squareLength+1,
						GameUtil.offset+(j-1)*GameUtil.squareLength+1,
						GameUtil.squareLength-2,
						GameUtil.squareLength-2,
						null);
				}
				if(GameUtil.Data[i][j]==1) {
					g.drawImage(GameUtil.flag,
							GameUtil.offset+(i-1)*GameUtil.squareLength+1,
							GameUtil.offset+(j-1)*GameUtil.squareLength+1,
							GameUtil.squareLength-2,
							GameUtil.squareLength-2,
							null);
				}
				if(GameUtil.Data[i][j]==2) {
					g.drawImage(GameUtil.noflag,
							GameUtil.offset+(i-1)*GameUtil.squareLength+1,
							GameUtil.offset+(j-1)*GameUtil.squareLength+1,
							GameUtil.squareLength-2,
							GameUtil.squareLength-2,
							null);
				}
			}
		}
	}
}

  • 5
    点赞
  • 68
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值