国产成人精品18p,天天干成人网,无码专区狠狠躁天天躁,美女脱精光隐私扒开免费观看

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

發(fā)布時(shí)間:2021-07-06 11:13 來(lái)源:腳本之家 閱讀:0 作者:編程界明世隱 欄目: 開(kāi)發(fā)技術(shù) 歡迎投稿:712375056

目錄

    一、效果圖

          

    二、實(shí)現思路

    1.界面上可以點(diǎn)開(kāi)的各種實(shí)際都是按鈕,創(chuàng )建9行9列的二維數組,然后根據這個(gè)數組來(lái)創(chuàng )建JButton。

    2.對應創(chuàng )建二維數組data,用來(lái)存取數據,0表示周?chē)鸁o(wú)雷,-1表示當前是雷,其他數字表示周?chē)椎臄盗俊?/p>

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

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

    5.設置周?chē)椎臄盗浚河嬎忝總€(gè)元素周?chē)睦讛盗浚ㄖ車(chē)傅氖?左上、上、右上、右、右下、下、左下、左 這8個(gè)位置),循環(huán)二維數組data,判斷當前值不是-1,則需要計算周?chē)椎臄盗?,等?huì )細說(shuō)。

    6.有任一格子被揭開(kāi),則游戲開(kāi)始并且計時(shí),當格子被揭開(kāi)的時(shí)候分3種情況

    (1)格子是雷,執行爆炸動(dòng)畫(huà),游戲結束。

    (2)當前格子周?chē)欣?,則僅僅打開(kāi)此格子,對應顯示周?chē)讛盗康臄底謭D片。

    (3)當前格子不是雷且周?chē)鷽](méi)有雷(data取到的元素值為0),則依次打開(kāi)周?chē)?,并且被打開(kāi)的周?chē)匾矝](méi)有雷的情況下,繼續打開(kāi)(遞歸)。

    7.右鍵可以進(jìn)行插小旗、打問(wèn)號等操作(對數組state進(jìn)行的操作)。

    三、代碼實(shí)現

    3.1 設置頭部

    //設置頭部
    private void setHeader() {
    	Container container = new Container();
    	container.setLayout(new GridLayout(1, 3));
    	
    	timeJLabel = new JLabel("時(shí)間:"+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.創(chuàng )建容器,并采用GridLayout 布局。

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

    3.給每個(gè)按鈕添加鼠標點(diǎn)擊事件,右鍵事件。

    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.隨機行數 i 和列數 j,根據隨機到 i、j 從二維數組data中取出對應的元素值。

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

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

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

    3.4 計算周?chē)椎臄盗坎@示

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

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

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

    //設置周?chē)椎臄盗?
    private void setAroundLei() {
    	for (int i = 0; i <ROWS; i++) {
    		for (int j = 0; j < COLS; j++) {
    			if(data[i][j]!=-1){如果當前不是雷,則判斷他周?chē)袔讉€(gè)雷,并設置值
    				data[i][j] = computedLei(i,j);
    			}
    		}
    	}
    }
    //計算周?chē)椎臄盗?
    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 添加點(diǎn)擊事件

    1.讓代碼實(shí)現 ActionListener

    2.重寫(xiě)方法actionPerformed,獲取點(diǎn)擊的按鈕進(jìn)行揭開(kāi)操作(分3種情況):

    (1)格子是雷,執行爆炸動(dòng)畫(huà),游戲結束。

    (2)當前格子周?chē)欣?,則僅僅打開(kāi)此格子,顯示周?chē)讛盗康臄底謭D片。

    (3)當前格子不是雷且周?chē)鷽](méi)有雷(data取到的元素值為0),則依次打開(kāi)周?chē)?,并且被打開(kāi)的周?chē)匾矝](méi)有雷的情況下,繼續打開(kāi)(遞歸)。

    3.6 打開(kāi)指定按鈕

    //打開(kāi)指定的button
    private void open(int i,int j) {
    	JButton button = btns[i][j];
    	if(state[i][j]==1){//已經(jīng)打開(kāi)直接返回
    		return ;
    	}
    	state[i][j]=1;//設置打開(kāi)狀態(tài)
    	int num = data[i][j];
    	if(num==-1){//直接使用雷的圖片
    		setBtnImage(button,(ImageIcon)imageMap.get(18));
    		//游戲結束,并爆炸
    		boom(button);
    	}else{//如果當前不是雷,顯示對應數字類(lèi)圖片
    		if(num==0){
    			num=9;
    			//顯示周?chē)膱D標,并且遞歸
    			openAround(i,j);
    		}
    		setBtnImage(button,(ImageIcon)imageMap.get(num));
    		setBtnEnabled(button,false);//按鈕被打開(kāi)設置不能再點(diǎn)擊了
    		
    		//判定是否成功
    		successOrNot(1);
    	}
    }
    

    3.7 觸雷爆炸

    爆炸采用線(xiàn)程來(lái)執行,就是切換圖片,圖片切換到最后一張后線(xiàn)程結束,回調定義好的方法進(jìn)行結束提示、打開(kāi)所有格子等操作。

    //爆炸效果
    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;
    	
    	//設置全部按鈕打開(kāi)
    	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, "你失敗了!點(diǎn)擊上方按鈕重新開(kāi)始");
    }
    

    3.8 遞歸打開(kāi)周?chē)?/h3>
    //打開(kāi)周?chē)?
    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.實(shí)現MouseListener,重寫(xiě)mouseClicked方法。

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

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

    4.如果按鈕是未知狀態(tài)則設置為原來(lái)的狀態(tài)未打開(kāi)(設置state數組對應的元素值: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){//如果是未打開(kāi)狀態(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)則設置為原來(lái)的未打開(kāi)
    						state[i][j]=0;
    						setBtnImage(button,(ImageIcon)imageMap.get(10));
    					}
    				}
    			}
    		}
    	}
    	
    }
    

    四、勝利判定

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

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

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

    最后加入重新開(kāi)始事件就完成了。

    重新開(kāi)始就是重新設置相關(guān)參數。

    //重新開(kāi)始游戲
    private void restart() {
    	//關(guān)閉計時(shí)線(xiàn)程(可能正在進(jìn)行游戲,所以要把計時(shí)線(xiàn)程關(guān)閉)
    	gameTimeRunnable.setFlag(false);
    	
    	startFlag=false;
    	computedLeiCount=0;
    	
    	curLeiCount=10;
    	leiJLabel.setText("雷:"+curLeiCount);
    	time=0;
    	timeJLabel.setText("時(shí)間:"+time);
    	
    	data= new int[ROWS][COLS];//存取數據
    	state= new int[ROWS][COLS];//存取打開(kāi)狀態(tài),0未打開(kāi),1 打開(kāi)
    	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);//按鈕重新設置可以點(diǎn)擊
    		}
    	}
     
    }
    

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

    免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。

    精品国产乱码久久久久久郑州公司| 精选国产AV精选一区二区三区| 黄 色 成 年 人免费观看| 中文无码日韩欧免费视频APP| 在线涩涩免费观看国产精品| 青青草免费公开视频|