石頭迷陣小游戲
/*代碼及運行截圖在最后面*/
素材鏈接:https://pan.baidu.com/s/1BrmD6VSJ0Yh7LkLklaoNfg?pwd=dk71
提取碼:dk71
鏈接:https://pan.baidu.com/s/130i3OTJwGTyTNJalk2hHpA?pwd=2sjg
提取碼:2sjg
一、思路
1、我們要做的第一步就是先完成窗體的創(chuàng)建,new一個新的窗體對象然后去設置它的參數(shù)。

2、創(chuàng)建完窗體之后,我們就可以添加我們需要的圖片了。在創(chuàng)建圖片的時候,首先我們要想到,必須收拾好了再出門,也就是添加圖片這些代碼必須在設置窗體可見之前。
我們按照規(guī)律,先將16張圖片加入面板,再將背景圖片加入面板,因為最先添加的在上層。

然后我們先試著運行一下我們的代碼,看看圖片是否添加成功。

3、我們使用的窗體是Java中本身就寫好的JFrame,它里面的功能早就已經被定義好了,我們如果想要加點其他的功能,我們沒有辦法去修改Java的源代碼?,F(xiàn)在我們既想使用窗體的功能,又想加入新的功能,該怎么辦?
答案就是——繼承
我們只需要自己去編寫一個類,讓它去繼承JFrame這個類,我們就可以使用JFrame這個類中的所有功能,又可以添加自己想要的功能。
所以我們在這里新建一個類。

我們在子類中添加兩個方法,一個是初始化窗體、一個是繪制界面,然后將我們的代碼放進來。

注意:我們這里將代碼直接復制進來會報錯
首先對于數(shù)組的報錯,是因為作用域的原因,我們只需要將二維數(shù)組放在方法外面。
然后窗體對象名的報錯,也是因為作用域的原因,但是?。。∥覀兪褂么绑w對象的目的是為了調用getContentPane( )這個方法,而這個方法是來自于JFrame類,我們這個類是繼承于JFrame這個類,我們可以用super.去調用,但是?。?!我們之前學過,如果子類沒有重寫父類的方法,這個super.可以省略,所以我們直接不寫。

那么我們之前創(chuàng)建窗體對象的部分也可以直接省略不寫。

4、我們再來思考一個很重要的東西,這兩個方法什么時候被執(zhí)行呢?
答案是創(chuàng)建窗體對象的時候,我們知道有一種方法,在創(chuàng)建對象的時候會被執(zhí)行——構造方法。
所以,我們在構造方法中調用這兩個方法。

注意:設置窗體可見必須在游戲界面繪制完成后再執(zhí)行(收拾好了再出門?。?/span>
所以現(xiàn)在,只要我們一創(chuàng)建對象,構造方法就會執(zhí)行,就會初始化窗體,繪制游戲界面。
我們在主方法中試著創(chuàng)建對象:

運行結果:

現(xiàn)在我們如果想要添加自己的功能,只需要在JFrame的子類中創(chuàng)建方法,然后在構造方法中調用就可以。
5、圖片順序打亂。
我們要打亂石頭方塊其實就是要改變二維數(shù)組里的內容,我們可以遍歷這個二維數(shù)組,然后將元素做隨機交換。
我們將打亂圖片順序抽取成一個方法,然后在構造方法里面調用它,注意,他應該在繪制界面的前一步。然后我們再次運行代碼。

6、移動窗體模塊
<1>我們要為窗體注冊鍵盤監(jiān)聽,并區(qū)分出上下左右,誰被摁了。
我們之前調用監(jiān)聽,都是利用窗體對象.的形式,但是現(xiàn)在我們沒有窗體對象了我們怎么調用?
我們的子類繼承于JFrame,子類就是我們正在用的窗體,子類的對象呢?在測試類這一塊去new的,我們在子類中怎么能拿到呢?我們之前學過一個關鍵字,代表的是當前類的對象——this。我們可以直接用this.的形式去調用。

這里需要我們去給一個參數(shù),掉addKeyListener( )方法時,參數(shù)要的是一個接口,我們應該傳入的是一個實現(xiàn)類對象。所以擺在我們面前有兩種選擇,要么單獨寫一個類,要么給一個匿名內部類。
我們之前學過,一個類在繼承類的同時,也可以實現(xiàn)接口,所以我們直接讓我們的子類去實現(xiàn)KeyListenner這個接口。

報錯是因為我們要重寫KeyListener這個接口里面的方法。

現(xiàn)在我們子類就是這個接口的實現(xiàn)類,而KeyListener( )方法中需要傳入的是一個實現(xiàn)類對象,我們直接this。(直呼牛逼)
keyPressed是記錄鍵盤按下
keyReleased是記錄鍵盤松開
keyTyped是記錄鍵盤鍵入的時候
接下來我們只需要在keyPressed中加入移動邏輯。其他兩個就不用管了。

我們先用打印語句模擬執(zhí)行:

模擬運行很成功。
為了效果的美觀,我們將判斷語句抽取出一個新的方法:

<2>確定0號元素的位置
什么時候去找0號的位置呢?
在圖片順序被打亂之后就可以找了,我們在成員變量中聲明兩個變量記錄0號元素的位置。

<3>實現(xiàn)移動業(yè)務 (空白塊視角)
左移動:
空白塊和右邊數(shù)據(jù)做交換。
空白塊:行不變,列加一。
右邊的變?yōu)榭瞻卓斓奈恢谩?/span>

其它幾個操作類似。
現(xiàn)在跑起來代碼,畫面是不會動的!??!
所以我們每移動一次,需要刷新一次窗體面板。

這樣之后其實還是不會成功的,如果我們只是這樣操作的話,每刷新一次窗體面板,就相當于新添加了一次圖片,而先添加的在最上層,所以我們就相當于一直在最下層添加圖片。
解決方法:在每一次繪制界面的開始都執(zhí)行一次清空窗口的操作,每一次繪制界面的結束都執(zhí)行一次刷新窗口的操作。
super.getContentPane( ).removeAll( );
super.getContentPane( ).repaint( );
這樣就可以運行了。
但是!?。?!還有bug?。。?!
bug先放著不管,自己寫的游戲,自己寫個掛可以吧!

“Z”一鍵勝利!?。?/span>
<4>問題處理
索引越界:
如果遇到了邊界坐標,再移動會發(fā)生索引越界異常。
加入if判斷,如果橫坐標不等于3,就可以左移動。
以此類推。
7、勝利判斷
定義一個新的數(shù)組存儲過關的數(shù)據(jù),每鍵盤輸入一次,就判斷一次,如果新數(shù)組與原數(shù)組內容相同,就加載勝利圖片。
建議重新定義一個方法。

為了不浪費內存,我們將勝利的數(shù)組放到成員變量中。
這個方法在什么時候調用呢?
答案是繪制游戲界面的里邊,然后我們加一個判斷,如果結果為true就顯示勝利!

為了不讓游戲結束后繼續(xù)移動,我們還需要在控制移動的方法的開始就判斷是否勝利,如果勝利直接就結束方法。

8、統(tǒng)計步數(shù)
定義一個成員變量count,每移動一次,count++;
還要定義一個JLabel來顯示移動步數(shù)。

9、重新游戲
設置一個按鈕,點擊讓它重新游戲。
給按鈕綁定監(jiān)聽,步數(shù)歸零,順序打亂。

然后就OK了。
