手把手帶你用Java打造一款對(duì)對(duì)碰游戲(下篇)
上篇文章介紹了對(duì)對(duì)碰游戲的理論部分和介紹了JLabel、JButton、JPanel、ImageIcon、JTextField、JProgressBar等組件的基本使用,介紹了進(jìn)度條(JProgressBar)常用的方法。今天小編繼續(xù)帶來進(jìn)行具體的對(duì)對(duì)碰游戲功能實(shí)現(xiàn)。
項(xiàng)目實(shí)施
在實(shí)現(xiàn)對(duì)對(duì)碰功能之前,回顧一下上一節(jié)我們主要完成了開始游戲按鈕、分?jǐn)?shù)、時(shí)間進(jìn)度條、退出游戲按鈕,8X8的動(dòng)物矩陣的界面設(shè)計(jì);
效果圖如下所示:

接下來,小編繼續(xù)帶大家完成游戲功能,實(shí)現(xiàn)游戲功能需要了解什么是交換、消去、連鎖,在游戲項(xiàng)目設(shè)定那里有,在這就不重復(fù)寫了。
(一)添加DuiDuiPeng類的成員變量:定義一些變量
代碼如下所示:
- private MyListener my = new MyListener();
 - private Timer timer;
 - private int score=0;//總分
 - private int jindu=0;
 - private int x1,y1;//第一次點(diǎn)擊按鈕的坐標(biāo)位置
 - private int x2,y2;//第二次點(diǎn)擊按鈕的坐標(biāo)位置
 - private final int EMPTY=-1;//為空的標(biāo)記
 - private boolean isDoubleClicked=false;//是否點(diǎn)擊兩次
 
(二)在DuiDuiPeng構(gòu)造函數(shù)里給指定組件添加監(jiān)聽
- btn_start.addActionListener(my);//開始游戲
 - btn_exit.addActionListener(my);//退出
 
(三)實(shí)現(xiàn)事件處理的函數(shù)體
當(dāng)點(diǎn)擊開始按鈕時(shí)候,計(jì)時(shí)器啟動(dòng),設(shè)置進(jìn)度條,8X8動(dòng)物矩陣可以互換位置,當(dāng)點(diǎn)擊退出按鈕,計(jì)時(shí)器停止,8X8動(dòng)物矩陣不可以互換位置。
代碼如下所示:
- private class MyListener implements ActionListener{
 - @Override
 - public void actionPerformed(ActionEvent e) {
 - // TODO Auto-generated method stub
 - if(e.getSource()==btn_start){//開始游戲
 - btn_start.setEnabled(false);
 - timer.start();
 - jindu=0;
 - progress.setValue(jindu);
 - score=0;
 - text_score.setText(""+score);
 - for(int i=0;i<8;i++){
 - for(int j=0;j<8;j++){
 - button[i][j].setEnabled(true);
 - }
 - }
 - do{initAllAnimals();//初始化動(dòng)物矩陣
 - }while(searchAllAnimals(1));//searchAllAnimals 1為查詢連接 2為去除連接
 - }
 - if(e.getSource()==btn_exit){//退出按鈕
 - timer.stop();
 - for(int i=0;i<8;i++){
 - for(int j=0;j<8;j++){
 - button[i][j].setEnabled(false);
 - }
 - }
 - dispose();
 - }
 - for(int i=0;i<8;i++){
 - for(int j=0;j<8;j++){
 - if(e.getSource()==button[i][j]){//動(dòng)物按鈕
 - System.out.println((i+1)+"行"+(j+1)+"列");
 - swapAnimal(i,j);//實(shí)現(xiàn)交換圖片
 - }
 - }
 - }
 - }
 - }
 
(四)添加計(jì)時(shí)器
1.在DuiDuiPeng構(gòu)造函數(shù)里添加計(jì)時(shí)器;
代碼如下所示:
- timer=new Timer(1000,new TimerListener());
 
2.進(jìn)度條的值從0開始每秒加一,直到進(jìn)度條的值達(dá)到100,計(jì)時(shí)器停止,不能位置交換動(dòng)物頭像,進(jìn)度條開始加的時(shí)候,開始按鈕是不能點(diǎn)擊的,當(dāng)進(jìn)度條達(dá)到100的時(shí)候,我們?cè)O(shè)置開始按鈕可以點(diǎn)擊狀態(tài)。
代碼如下所示:
- private class TimerListener implements ActionListener{
 - @Override
 - public void actionPerformed(ActionEvent e) {
 - // TODO Auto-generated method stub
 - jindu++;
 - progress.setValue(jindu);
 - if(jindu==100){
 - timer.stop();
 - for(int i=0;i<8;i++){
 - for(int j=0;j<8;j++){
 - button[i][j].setEnabled(false);
 - }
 - }
 - btn_start.setEnabled(true);
 - }
 - }
 - }
 
(五)初始化動(dòng)物矩陣
代碼如下所示:
- public void initAllAnimals(){//初始化動(dòng)物矩陣
 - for(int i=0;i<8;i++){
 - for(int j=0;j<8;j++){
 - int temp=(int)(Math.random()*7);//0-6
 - button[i][j].setIcon(icon[temp]);
 - animal[i][j]=temp;
 - }
 - }
 - }
 
(六)查詢是否有三個(gè)或以上相同連接的圖形,是返回true,不是返回false,判斷水平方向上是否有三個(gè)或以上相同連接的圖形,判斷垂直方向上是否有三個(gè)或以上相同連接的圖形
代碼較多,在此就不一一呈現(xiàn)了,文末有獲取代碼的方式。
(七)把三個(gè)或以上相同連接圖形設(shè)為EMPTY,判斷水平方向上是否有三個(gè)或以上相同連接的圖形,把水平方向上有三個(gè)或以上相同連接的圖形設(shè)為EMPTY。判斷垂直方向上是否有三個(gè)或以上相同連接的圖形,把垂直方向上有三個(gè)或以上相同連接的圖形設(shè)為EMPTY。
代碼較多,在此就不一一呈現(xiàn)了,文末有獲取代碼的方式。
(八)查詢所有動(dòng)物頭像(1為查詢連接 2為去除連接)
代碼如下所示:
- public boolean searchAllAnimals(int flag){
 - //1為查詢連接 2為去除連接
 - for(int i=0;i<8;i++){
 - for(int j=0;j<8;j++){
 - if(flag==1){
 - if(isThreeLinked(i,j)){//查詢是否有三個(gè)或以上連接
 - return true;
 - }
 - }else if(flag==2){
 - removeThreeLined(i,j);
 - }
 - }
 - }
 - return false;
 - }
 
(九)動(dòng)物往下移動(dòng)
代碼如下所示:
- public void downAnimal(){//動(dòng)物往下移動(dòng)
 - int temp;
 - for(int y=7;y>=0;y--){
 - for(int x=0;x<8;x++){
 - if(animal[y][x]==EMPTY){
 - //找到一個(gè)空的位置
 - for(int k=y-1;k>=0;k--){
 - if(animal[k][x]!=EMPTY){//找到上面一個(gè)非空的
 - temp=animal[k][x];
 - animal[k][x]=animal[y][x];
 - animal[y][x]=temp;
 - break;
 - }
 - }
 - }
 - }
 - }
 - }
 
(十)重新顯示所有圖形
代碼如下所示:
- public void showAllAnimals(){//重新顯示所有圖形
 - for(int i=0;i<8;i++){
 - for(int j=0;j<8;j++){
 - button[i][j].setIcon(icon[animal[i][j]]);
 - }
 - }
 - }
 
(十一)為空的重新生成隨機(jī)圖形
代碼如下所示:
- public void updateAnimal(){//為空的重新生成隨機(jī)圖形
 - for(int i=0;i<8;i++){
 - for(int j=0;j<8;j++){
 - if(animal[i][j]==EMPTY){
 - animal[i][j]=(int)(Math.random()*7);
 - }
 - }
 - }
 - }
 
(十二)交換位置
代碼如下所示
- public void swapAnimal(int y,int x){//y為行,x為列
 - if((x>=0 && x<8)&&(y>=0 && y<8)){
 - if(!isDoubleClicked){
 - //第一次單擊
 - x1=x;
 - y1=y;
 - isDoubleClicked=true;
 - System.out.println("第一次單擊的坐標(biāo)=("+(y1+1)+","+(x1+1)+")");
 - }else{
 - x2=x;
 - y2=y;
 - isDoubleClicked=false;
 - System.out.println("第一次單擊的坐標(biāo)=("+(y2+1)+","+(x2+1)+")");
 - if((Math.abs(x2-x1)==1 &&(y1==y2))
 - ||(x1==x2)&&(Math.abs(y2-y1)==1)){//相鄰兩個(gè)按鈕
 - int temp;
 - temp=animal[y2][x2];//交換
 - animal[y2][x2]=animal[y1][x1];
 - animal[y1][x1]=temp;
 - if(isThreeLinked(y1,x1)|| isThreeLinked(y2,x2)){//有三個(gè)或以上連接
 - if(isThreeLinked(y1,x1)){
 - removeThreeLined(y1,x1);
 - }
 - if(isThreeLinked(y2,x2)){
 - removeThreeLined(y2,x2);
 - }
 - downAnimal();//動(dòng)物往下移動(dòng)
 - updateAnimal();//為空的重新生成隨機(jī)圖形
 - showAllAnimals();//重新顯示所有圖形
 - while(searchAllAnimals(1)){
 - searchAllAnimals(2);//去除連接
 - downAnimal();
 - updateAnimal();
 - showAllAnimals();
 - }
 - }else{//沒有三個(gè)相鄰的
 - temp=animal[y2][x2];//交換
 - animal[y2][x2]=animal[y1][x1];
 - animal[y1][x1]=temp;
 - }
 - }
 - }
 - }
 - }
 
完成事件處理效果圖如下圖所示:

五、總結(jié)
1.本文主要介紹了JLabel、JButton、JPanel、ImageIcon、JTextField、JProgressBar、Timer等組件的基本使用,以及相應(yīng)的事件處理。
2.講解事件處理函數(shù)的添加,難點(diǎn)是運(yùn)用理解構(gòu)造函數(shù)、內(nèi)部類的創(chuàng)建。完成事件處理開始游戲按鈕,退出功能、實(shí)現(xiàn)進(jìn)度條計(jì)時(shí)、初始化動(dòng)物矩陣、在水平方向或垂直方向是否有三個(gè)或三個(gè)以上的相同連接圖形在、動(dòng)物往下移、重新顯示所有圖形、為空的重新生成隨機(jī)圖形,最后交換位置。
3.這些代碼看起來比較復(fù)雜,但其實(shí)不是很難,寫的事件處理比較多,希望通過這個(gè)對(duì)對(duì)碰的一個(gè)小游戲?qū)δ阌兴鶐椭?
















 
 
 







 
 
 
 