最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

教你怎么用Java開發(fā)掃雷游戲

 更新時間:2021年05月14日 10:30:17   作者:編程界明世隱  
我們那時候上機經常玩掃雷,試想如果我當年可以用 java 寫個掃雷出來,那場面不用我多說了吧,大家讓開,我要開始裝逼了,之前用JavaScript寫過了一個掃雷,這次我用java再寫了一遍,權當是復習咯.文中有非常詳細的代碼示例,需要的朋友可以參考下

一、效果圖

      

二、實現(xiàn)思路

1.界面上可以點開的各種實際都是按鈕,創(chuàng)建9行9列的二維數(shù)組,然后根據(jù)這個數(shù)組來創(chuàng)建JButton。

2.對應創(chuàng)建二維數(shù)組data,用來存取數(shù)據(jù),0表示周圍無雷,-1表示當前是雷,其他數(shù)字表示周圍雷的數(shù)量。

3.對應創(chuàng)建二維數(shù)組state,用來存取按鈕狀態(tài),0未打開,1 打開  2旗子  3 未知(控制顯示對應的圖標)

4.設置雷:隨機行數(shù) i 和列數(shù) j,根據(jù)隨機到 i、j 從二維數(shù)組data中取出對應的元素值,若值不為-1(不是雷),則將此元素data[i][j]設置為-1,若值是-1(已經是雷了),則跳過,不管是否跳過都進行遞歸,直到雷的數(shù)量達到設定的最大數(shù)量,跳出遞歸。

5.設置周圍雷的數(shù)量:計算每個元素周圍的雷數(shù)量(周圍指的是 左上、上、右上、右、右下、下、左下、左 這8個位置),循環(huán)二維數(shù)組data,判斷當前值不是-1,則需要計算周圍雷的數(shù)量,等會細說。

6.有任一格子被揭開,則游戲開始并且計時,當格子被揭開的時候分3種情況

(1)格子是雷,執(zhí)行爆炸動畫,游戲結束。

(2)當前格子周圍有雷,則僅僅打開此格子,對應顯示周圍雷數(shù)量的數(shù)字圖片。

(3)當前格子不是雷且周圍沒有雷(data取到的元素值為0),則依次打開周圍,并且被打開的周圍元素也沒有雷的情況下,繼續(xù)打開(遞歸)。

7.右鍵可以進行插小旗、打問號等操作(對數(shù)組state進行的操作)。

三、代碼實現(xiàn)

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 設置游戲區(qū)域按鈕

1.創(chuàng)建容器,并采用GridLayout 布局。

2.根據(jù)設定的ROWS、COLS創(chuàng)建二維數(shù)組,數(shù)組存儲JButton,給每個按鈕設置圖標。

3.給每個按鈕添加鼠標點擊事件,右鍵事件。

private void setButtons() {
	Container container = new Container();
	container.setLayout(new GridLayout(ROWS, COLS));
	ImageIcon icon=null;
	for (int i = 0; i <ROWS; i++) {
		for (int j = 0; j < COLS; j++) {
			JButton btn = new JButton();
			btn.setBounds(0, 0, 39, 39);
			icon = (ImageIcon)imageMap.get(10);
			setBtnImage(btn,icon);
			container.add(btn);
			btns[i][j]=btn;
			
			btn.addActionListener(this);
			
			btn.addMouseListener(this);
		}
	}
	mainFrame.add(container,BorderLayout.CENTER);
}

 

3.3 設置雷

1.隨機行數(shù) i 和列數(shù) j,根據(jù)隨機到 i、j 從二維數(shù)組data中取出對應的元素值。

2.判斷值,若值不為-1(不是雷),則將此元素data[i][j]設置為-1,若值是-1(已經是雷了),則跳過。

3.不管上一步是否跳過都進行遞歸,直到雷數(shù)量達到設定的最大數(shù)量,跳出遞歸。

private void setLei() {
	if(computedLeiCount==LEICOUNT){//如果達到雷的最大數(shù)量則跳出
		return;			
	}	
	Random random = new Random();
	int r = random.nextInt(ROWS);
	int c = random.nextInt(COLS);
	
	//0 無; -1表示雷 ; 其他表示周圍的雷數(shù)量
	if(data[r][c]!=-1){//如果不是雷則設置為雷
		data[r][c]=-1;
		computedLeiCount++;
	}
	setLei();//遞歸調用
}

3.4 計算周圍雷的數(shù)量并顯示

1.循環(huán)之前的二維數(shù)組data,元素值是-1(雷)跳過,不是-1則繼續(xù)。

2.如果當前元素的下標是(i,j),則左上為(i-1,j-1),上為(i-1,j ),右上為(i-1,j+1),以此類推,如下圖所示:

3.分別取出這8個元素,并判斷他們是不是雷,如果是則計數(shù)累加,最后把這個計數(shù)賦值給元素data[i][j]。

//設置周圍雷的數(shù)量
private void setAroundLei() {
	for (int i = 0; i <ROWS; i++) {
		for (int j = 0; j < COLS; j++) {
			if(data[i][j]!=-1){如果當前不是雷,則判斷他周圍有幾個雷,并設置值
				data[i][j] = computedLei(i,j);
			}
		}
	}
}
//計算周圍雷的數(shù)量
private int computedLei(int i,int j) {
	int count=0;
	//左上
	int ci = i-1;
	int cj = j-1;
	if(ci>=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<COLS){
		if(data[ci][cj]==-1){
			count++;
		}
	}
	//右
	ci = i;
	cj = j+1;
	if(cj<COLS){
		if(data[ci][cj]==-1){
			count++;
		}
	}
	//右下
	ci = i+1;
	cj = j+1;
	if(ci<ROWS && cj<COLS){
		if(data[ci][cj]==-1){
			count++;
		}
	}
	//下
	ci = i+1;
	cj = j;
	if(ci<ROWS){
		if(data[ci][cj]==-1){
			count++;
		}
	}
	//左下
	ci = i+1;
	cj = j-1;
	if(ci<ROWS && 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.讓代碼實現(xiàn) ActionListener

2.重寫方法actionPerformed,獲取點擊的按鈕進行揭開操作(分3種情況):

(1)格子是雷,執(zhí)行爆炸動畫,游戲結束。

(2)當前格子周圍有雷,則僅僅打開此格子,顯示周圍雷數(shù)量的數(shù)字圖片。

(3)當前格子不是雷且周圍沒有雷(data取到的元素值為0),則依次打開周圍,并且被打開的周圍元素也沒有雷的情況下,繼續(xù)打開(遞歸)。

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;//設置打開狀態(tài)
	int num = data[i][j];
	if(num==-1){//直接使用雷的圖片
		setBtnImage(button,(ImageIcon)imageMap.get(18));
		//游戲結束,并爆炸
		boom(button);
	}else{//如果當前不是雷,顯示對應數(shù)字類圖片
		if(num==0){
			num=9;
			//顯示周圍的圖標,并且遞歸
			openAround(i,j);
		}
		setBtnImage(button,(ImageIcon)imageMap.get(num));
		setBtnEnabled(button,false);//按鈕被打開設置不能再點擊了
		
		//判定是否成功
		successOrNot(1);
	}
}

3.7 觸雷爆炸

爆炸采用線程來執(zhí)行,就是切換圖片,圖片切換到最后一張后線程結束,回調定義好的方法進行結束提示、打開所有格子等操作。

//爆炸效果
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<COLS){
		open(ci,cj);
	}
	//右
	ci = i;
	cj = j+1;
	if(cj<COLS){
		open(ci,cj);
	}
	//右下
	ci = i+1;
	cj = j+1;
	if(ci<ROWS && cj<COLS){
		open(ci,cj);
	}
	//下
	ci = i+1;
	cj = j;
	if(ci<ROWS){
		open(ci,cj);
	}
	//左下
	ci = i+1;
	cj = j-1;
	if(ci<ROWS && cj >=0){
		open(ci,cj);
	}
	//左
	ci = i;
	cj = j-1;
	if(cj >= 0){
		open(ci,cj);
	}
}

 

3.9 鼠標右鍵事件

1.實現(xiàn)MouseListener,重寫mouseClicked方法。

2.如果按鈕是未打開狀態(tài)則設置為旗子(設置state數(shù)組對應的元素值:2)。

3.如果按鈕是旗子狀態(tài)則設置為未知(設置state數(shù)組對應的元素值:3)。

4.如果按鈕是未知狀態(tài)則設置為原來的狀態(tài)未打開(設置state數(shù)組對應的元素值:0)。

//鼠標右鍵的處理
@Override
public void mouseClicked(MouseEvent e) {
	if(e.getButton()==MouseEvent.BUTTON3){
		JButton button = (JButton)e.getSource();
		for (int i = 0; i <ROWS; i++) {
			for (int j = 0; j < COLS; j++) {
				if(button.equals(btns[i][j])){//找到對應的按鈕
					if(state[i][j]==0){//如果是未打開狀態(tài)則設置為旗子
						state[i][j]=2;
						setBtnImage(button,(ImageIcon)imageMap.get(12));
						
						curLeiCount--;
						leiJLabel.setText("雷:"+curLeiCount);
						
						//需求判斷是否成功
						successOrNot(2);
						
					}else if(state[i][j]==2){//如果是旗子狀態(tài)則設置為未知
						state[i][j]=3;
						setBtnImage(button,(ImageIcon)imageMap.get(13));
						
						curLeiCount++;
						leiJLabel.setText("雷:"+curLeiCount);
					}else if(state[i][j]==3){//如果是未知狀態(tài)則設置為原來的未打開
						state[i][j]=0;
						setBtnImage(button,(ImageIcon)imageMap.get(10));
					}
				}
			}
		}
	}
	
}

四、勝利判定

1.判斷旗子的位置是不是正確的雷,并統(tǒng)計數(shù)量,如果統(tǒng)計到的數(shù)量剛好和設定的雷總數(shù)一樣,證明雷全部被查出了,判定為勝利。

2.如果未打開的數(shù)量與設定雷的總數(shù)一樣,也判定為勝利。

//判斷是否成功 參數(shù)type=2表示判斷右鍵插旗子,參數(shù) type=其他  表示判斷鼠標點擊
private void successOrNot(int type) {
	int count=0;
	if(type==2){
		/*
		 * 1.判斷旗子的位置是否是正確的雷,并統(tǒng)計數(shù)量
		 * 2.如果統(tǒng)計到的數(shù)量剛好和雷的總數(shù)一樣,證明全部被查出了,判定為勝利
		*/
		for (int i = 0; i <ROWS; i++) {
			for (int j = 0; j < COLS; j++) {
				if(state[i][j]==2 && data[i][j]==-1){//是旗子,也是雷,則計數(shù)
					count++;
				}
			}
		}
	}else{
		//最終的未打開的數(shù)量與雷的數(shù)量一樣,則表示成功
		for (int i = 0; i <ROWS; i++) {
			for (int j = 0; j < COLS; j++) {
				if(state[i][j]!=1){//未打開就計數(shù)
					count++;
				}
			}
		}
	}
	
	if(count==LEICOUNT){//成功
		//關閉計時線程
		gameTimeRunnable.setFlag(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, "恭喜你獲得了勝利!你太棒了");
	}
}

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

重新開始就是重新設置相關參數(shù)。

//重新開始游戲
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];//存取數(shù)據(jù)
	state= new int[ROWS][COLS];//存取打開狀態(tài),0未打開,1 打開
	setLei();
	setAroundLei();
	
	ImageIcon icon = null;
	for (int i = 0; i <ROWS; i++) {
		for (int j = 0; j < COLS; j++) {
			icon = (ImageIcon)imageMap.get(10);
			setBtnImage(btns[i][j],icon);
			setBtnEnabled(btns[i][j],true);//按鈕重新設置可以點擊
		}
	}
 
}

到此這篇關于教你怎么用Java開發(fā)掃雷游戲的文章就介紹到這了,更多相關Java掃雷游戲內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java的引用類型常用的四種方法

    Java的引用類型常用的四種方法

    這篇文章主要介紹了Java的引用類型常用的幾種方法,Java為引用類型專門定義了一個類Reference,它是引用對象的抽象基類,相關內容需要的小伙伴可以參考一下
    2022-06-06
  • 新手初學Java繼承、封裝與多態(tài)

    新手初學Java繼承、封裝與多態(tài)

    封裝、繼承、多態(tài)三大特征是java中比較常用的,務必要掌握,下面給大家介紹Java封裝、繼承、多態(tài)三大特征的理解,有不清楚的朋友可以一起學習下
    2021-07-07
  • Linux實時查看Java接口數(shù)據(jù)的案例方法

    Linux實時查看Java接口數(shù)據(jù)的案例方法

    在Linux系統(tǒng)中實時查看Java接口數(shù)據(jù)通常涉幾個步驟,通過示例代碼說明如何使用Python的requests庫和Linux的cron作業(yè)來定期查詢Java應用程序的接口并打印結果,感興趣的朋友跟隨小編一起看看吧
    2024-06-06
  • 攔截JSP頁面,校驗是否已登錄詳解及實現(xiàn)代碼

    攔截JSP頁面,校驗是否已登錄詳解及實現(xiàn)代碼

    這篇文章主要介紹了攔截JSP頁面,校驗是否已登錄詳解及實現(xiàn)代碼的相關資料,需要的朋友可以參考下
    2016-11-11
  • Netty中的DelimiterBasedFrameDecoder使用方法詳解

    Netty中的DelimiterBasedFrameDecoder使用方法詳解

    這篇文章主要介紹了Netty中的DelimiterBasedFrameDecoder使用方法詳解,DelimiterBasedFrameDecoder與LineBasedFrameDecoder類似,只不過更加通用,允許我們指定任意特殊字符作為分隔符,我們還可以同時指定多個分隔符,需要的朋友可以參考下
    2023-12-12
  • 在java的Map集合中,如何更改value的值

    在java的Map集合中,如何更改value的值

    這篇文章主要介紹了在java的Map集合中,如何更改value的值問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • Java命令行參數(shù)解析工具jcommander詳解

    Java命令行參數(shù)解析工具jcommander詳解

    這篇文章主要為大家介紹了Java命令行參數(shù)解析工具jcommander命令詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-09-09
  • Java下Struts框架中的ActionForm類詳解

    Java下Struts框架中的ActionForm類詳解

    這篇文章主要介紹了Java下Struts框架中的ActionForm類詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-07-07
  • Java定時任務ScheduledThreadPoolExecutor示例詳解

    Java定時任務ScheduledThreadPoolExecutor示例詳解

    這篇文章主要介紹了Java定時任務ScheduledThreadPoolExecutor示例詳解,這里使用scheduleAtFixedRate方法安排一個任務,該任務是一個 Runnable 匿名類,其run方法中調用了new LoginViewTimeTask().loginStatisticsHandle()方法,需要的朋友可以參考下
    2023-11-11
  • Jpa中Specification的求和sum不生效原理分析

    Jpa中Specification的求和sum不生效原理分析

    這篇文章主要為大家介紹了Jpa中Specification的求和sum不生效原理示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-08-08

最新評論

安化县| 遂宁市| 安阳县| 两当县| 乐安县| 乌鲁木齐市| 漳平市| 曲阜市| 伽师县| 秦安县| 唐海县| 福贡县| 湖北省| 孙吴县| 油尖旺区| 东丽区| 平罗县| 延川县| 舞阳县| 大连市| 防城港市| 岱山县| 呈贡县| 自贡市| 崇明县| 册亨县| 阿拉善盟| 曲水县| 灯塔市| 龙州县| 手游| 封丘县| 日土县| 静海县| 宿州市| 防城港市| 北辰区| 长乐市| 五莲县| 县级市| 寻甸|