Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> 掃雷4Android(附源碼)

掃雷4Android(附源碼)

編輯:Android開發實例

 最近由於項目需要學習了一下Android ,感覺汗不錯。做了一個Android版的掃雷游戲。

游戲簡介

 在此游戲中,我們使用一個塊的網格,其中有一些隨機的地雷

下面是效果圖

 

一、應用程序布局

使用TableLayout布局控件。設置3行。

 

  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <TableLayout 
  3.   xmlns:android="http://schemas.android.com/apk/res/android" 
  4.   android:layout_width="wrap_content" 
  5.   android:layout_height="wrap_content" 
  6.   android:background="@drawable/back"> 
  7.     
  8.   <TableRow> 
  9.   <TextView android:id="@+id/timer" android:layout_column="0" 
  10.    android:layout_width="fill_parent" android:layout_height="48px" 
  11.    android:gravity="center_horizontal" android:padding="5dip" 
  12.    android:textColor="#FFFFFF" android:textSize="35sp" 
  13.       android:text=" 0" /> 
  14.   <ImageButton android:id="@+id/smiley" 
  15.    android:layout_column="1" android:scaleType="center" android:padding="5dip" 
  16.    android:layout_width="48px" android:background="@drawable/smiley_button_states" 
  17.    android:layout_height="48px" /> 
  18.   <TextView android:id="@+id/minecount" android:layout_column="2" 
  19.    android:layout_width="fill_parent" android:layout_height="48px" 
  20.    android:gravity="center_horizontal" android:padding="5dip" 
  21.    android:textColor="#FFFFFF" android:textSize="35sp" android:text="000" /> 
  22.  </TableRow> 
  23.    
  24.  <TableRow> 
  25.   <TextView android:layout_column="0" android:layout_height="50px" 
  26.    android:layout_width="fill_parent" android:layout_span="3" 
  27.    android:padding="10dip" /> 
  28.  </TableRow> 
  29.    
  30.  <TableRow> 
  31.   <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  32.    android:id="@+id/minefield" android:layout_width="260px" 
  33.    android:layout_height="260px" android:gravity="bottom" 
  34.    android:stretchColumns="*" android:layout_span="3" android:padding="5dip"> 
  35.   </TableLayout> 
  36.  </TableRow> 
  37. </TableLayout> 
  38.  

二、地雷塊

Block.java

  1.  
  2. /**  
  3.  * 地雷的塊,繼承自Button  
  4.  * @author 記憶的永恆  
  5.  *  
  6.  */ 
  7. public class Block extends Button {  
  8.  private boolean isCovered; // 塊是否覆蓋  
  9.  private boolean isMined; // 下個塊  
  10.  private boolean isFlagged; // 是否將該塊標記為一個潛在的地雷  
  11.  private boolean isQuestionMarked; // 是否是塊的問題標記  
  12.  private boolean isClickable; // 是否可以單擊  
  13.  private int numberOfMinesInSurrounding; // 在附近的地雷數量塊  
  14.  
  15.  public Block(Context context) {  
  16.   super(context);  
  17.   // TODO Auto-generated constructor stub  
  18.  }  
  19.  
  20.  public Block(Context context, AttributeSet attrs) {  
  21.   super(context, attrs);  
  22.   // TODO Auto-generated constructor stub  
  23.  }  
  24.    
  25.  public Block(Context context, AttributeSet attrs, int defStyle)  
  26.      {  
  27.       super(context, attrs, defStyle);  
  28.      }  
  29.  
  30.  
  31.  /**  
  32.   * 設置默認參數  
  33.   */ 
  34.  public void setDefaults() {  
  35.   isCovered = true;  
  36.   isMined = false;  
  37.   isFlagged = false;  
  38.   isQuestionMarked = false;  
  39.   isClickable = true;  
  40.   numberOfMinesInSurrounding = 0;  
  41.     
  42.   this.setBackgroundResource(R.drawable.square_blue);  
  43.   setBoldFont();  
  44.  }  
  45.  
  46.  public void setNumberOfSurroundingMines(int number) {  
  47.   this.setBackgroundResource(R.drawable.square_grey);  
  48.   updateNumber(number);  
  49.  }  
  50.  
  51.  public void setMineIcon(boolean enabled) {  
  52.   this.setText("M");  
  53.   if (!enabled) {  
  54.    this.setBackgroundResource(R.drawable.square_grey);  
  55.    this.setTextColor(Color.RED);  
  56.   }  
  57.  
  58.   else {  
  59.    this.setTextColor(Color.BLACK);  
  60.   }  
  61.  }  
  62.  
  63.  public void setFlagIcon(boolean enabled) {  
  64.   this.setText("F");  
  65.   if (!enabled) {  
  66.    this.setBackgroundResource(R.drawable.square_grey);  
  67.    this.setTextColor(Color.RED);  
  68.   }  
  69.  
  70.   else {  
  71.    this.setTextColor(Color.BLACK);  
  72.   }  
  73.  }  
  74.  
  75.  public void setQuestionMarkIcon(boolean enabled) {  
  76.   this.setText("?");  
  77.   if (!enabled) {  
  78.    this.setBackgroundResource(R.drawable.square_grey);  
  79.    this.setTextColor(Color.RED);  
  80.   }  
  81.  
  82.   else {  
  83.    this.setTextColor(Color.BLACK);  
  84.   }  
  85.  }  
  86.  
  87.  public void setBlockAsDisabled(boolean enabled) {  
  88.   if (!enabled) {  
  89.    this.setBackgroundResource(R.drawable.square_grey);  
  90.   }  
  91.  
  92.   else {  
  93.    this.setTextColor(R.drawable.square_blue);  
  94.   }  
  95.  }  
  96.  
  97.  public void clearAllIcons() {  
  98.   this.setText("");  
  99.  }  
  100.  
  101.  private void setBoldFont() {  
  102.   this.setTypeface(null, Typeface.BOLD);  
  103.  }  
  104.  
  105.  public void OpenBlock() {  
  106.   if (!isCovered) {  
  107.    return;  
  108.   }  
  109.  
  110.   setBlockAsDisabled(false);  
  111.   isCovered = false;  
  112.  
  113.   if (hasMine()) {  
  114.    setMineIcon(false);  
  115.   }  
  116.  
  117.   else {  
  118.    setNumberOfSurroundingMines(numberOfMinesInSurrounding);  
  119.   }  
  120.  }  
  121.  
  122.  public void updateNumber(int text) {  
  123.   if (text != 0) {  
  124.    this.setText(Integer.toString(text));  
  125.    switch (text) {  
  126.    case 1:  
  127.     this.setTextColor(Color.BLUE);  
  128.     break;  
  129.    case 2:  
  130.     this.setTextColor(Color.rgb(0, 100, 0));  
  131.     break;  
  132.    case 3:  
  133.     this.setTextColor(Color.RED);  
  134.     break;  
  135.    case 4:  
  136.     this.setTextColor(Color.rgb(85, 26, 139));  
  137.     break;  
  138.    case 5:  
  139.     this.setTextColor(Color.rgb(139, 28, 98));  
  140.     break;  
  141.    case 6:  
  142.     this.setTextColor(Color.rgb(238, 173, 14));  
  143.     break;  
  144.    case 7:  
  145.     this.setTextColor(Color.rgb(47, 79, 79));  
  146.     break;  
  147.    case 8:  
  148.     this.setTextColor(Color.rgb(71, 71, 71));  
  149.     break;  
  150.    case 9:  
  151.     this.setTextColor(Color.rgb(205, 205, 0));  
  152.     break;  
  153.  
  154.    }  
  155.   }  
  156.  }  
  157.  
  158.  public void plantMine() {  
  159.   isMined = true;  
  160.  }  
  161.  
  162.  public void triggerMine() {  
  163.   setMineIcon(true);  
  164.   this.setTextColor(Color.RED);  
  165.  }  
  166.  
  167.  public boolean isCovered() {  
  168.   return isCovered;  
  169.  }  
  170.  
  171.  public boolean hasMine() {  
  172.   return isMined;  
  173.  }  
  174.  
  175.  public void setNumberOfMinesInSurrounding(int number) {  
  176.   numberOfMinesInSurrounding = number;  
  177.  }  
  178.  
  179.  public int getNumberOfMinesInSorrounding() {  
  180.   return numberOfMinesInSurrounding;  
  181.  }  
  182.  
  183.  public boolean isFlagged() {  
  184.   return isFlagged;  
  185.  }  
  186.  
  187.  public void setFlagged(boolean flagged) {  
  188.   isFlagged = flagged;  
  189.  }  
  190.  
  191.  public boolean isQuestionMarked() {  
  192.   return isQuestionMarked;  
  193.  }  
  194.  
  195.  public void setQuestionMarked(boolean questionMarked) {  
  196.   isQuestionMarked = questionMarked;  
  197.  }  
  198.  
  199.  public boolean isClickable() {  
  200.   return isClickable;  
  201.  }  
  202.  
  203.  public void setClickable(boolean clickable) {  
  204.   isClickable = clickable;  
  205.  }  
  206.  
  207. }  
  208.  

 

三、主界面

1.TableLayout動態添加行

 

  1. mineField = (TableLayout)findViewById(R.id.MineField);  
  2.  
  3. private void showMineField()  
  4. {  
  5.   for (int row = 1; row < numberOfRowsInMineField + 1; row++)  
  6.   {  
  7.     TableRow tableRow = new TableRow(this);    
  8.     tableRow.setLayoutParams(new LayoutParams((blockDimension + 2 * blockPadding) *   
  9.         numberOfColumnsInMineField, blockDimension + 2 * blockPadding));  
  10.  
  11.     for (int column = 1; column < numberOfColumnsInMineField + 1; column++)  
  12.     {  
  13.       blocks[row][column].setLayoutParams(new LayoutParams(    
  14.           blockDimension + 2 * blockPadding,    
  15.           blockDimension + 2 * blockPadding));   
  16.       blocks[row][column].setPadding(blockPadding, blockPadding, blockPadding, blockPadding);  
  17.       tableRow.addView(blocks[row][column]);  
  18.     }  
  19.     mineField.addView(tableRow,new TableLayout.LayoutParams(    
  20.         (blockDimension + 2 * blockPadding) * numberOfColumnsInMineField, blockDimension + 2 * blockPadding));    
  21.   }  
  22. }  
  23.  

2.定時器Handler

  1. private Handler timer = new Handler();  
  2. private int secondsPassed = 0;  
  3.  
  4. public void startTimer(){ if (secondsPassed == 0)   
  5.   {  
  6.     timer.removeCallbacks(updateTimeElasped);  
  7.     // tell timer to run call back after 1 second  
  8.     timer.postDelayed(updateTimeElasped, 1000);  
  9.   }  
  10. }  
  11.  
  12. public void stopTimer()  
  13. {  
  14.   // disable call backs  
  15.   timer.removeCallbacks(updateTimeElasped);  
  16. }  
  17.  
  18. // timer call back when timer is ticked  
  19. private Runnable updateTimeElasped = new Runnable()  
  20. {  
  21.   public void run()  
  22.   {  
  23.     long currentMilliseconds = System.currentTimeMillis();  
  24.     ++secondsPassed;  
  25.     txtTimer.setText(Integer.toString(secondsPassed));  
  26.  
  27.     // add notification  
  28.     timer.postAtTime(this, currentMilliseconds);  
  29.     // notify to call back after 1 seconds  
  30.     // basically to remain in the timer loop  
  31.     timer.postDelayed(updateTimeElasped, 1000);  
  32.   }  
  33. };  
  34.  

3.第一次點擊

  1. private boolean isTimerStarted; // check if timer already started or not  
  2. blocks[row][column].setOnClickListener(new OnClickListener()  
  3. {  
  4.   @Override 
  5.   public void onClick(View view)  
  6.   {  
  7.     // start timer on first click  
  8.     if (!isTimerStarted)  
  9.     {  
  10.       startTimer();  
  11.       isTimerStarted = true;  
  12.     }  
  13.     ...  
  14.   }  
  15. });  
  16.  

4.第一次點擊無雷

 

  1. private boolean areMinesSet; // check if mines are planted in blocks  
  2.  
  3. blocks[row][column].setOnClickListener(new OnClickListener()  
  4. {  
  5.   @Override 
  6.   public void onClick(View view)  
  7.   {  
  8.     ...  
  9.     // set mines on first click  
  10.     if (!areMinesSet)  
  11.     {  
  12.       areMinesSet = true;  
  13.       setMines(currentRow, currentColumn);  
  14.     }  
  15.   }  
  16. });  
  17.  
  18. private void setMines(int currentRow, int currentColumn)  
  19. {  
  20.   // set mines excluding the location where user clicked  
  21.   Random rand = new Random();  
  22.   int mineRow, mineColumn;  
  23.  
  24.   for (int row = 0; row < totalNumberOfMines; row++)  
  25.   {  
  26.     mineRow = rand.nextInt(numberOfColumnsInMineField);  
  27.     mineColumn = rand.nextInt(numberOfRowsInMineField);  
  28.     if ((mineRow + 1 != currentColumn) || (mineColumn + 1 != currentRow))  
  29.     {  
  30.       if (blocks[mineColumn + 1][mineRow + 1].hasMine())  
  31.       {  
  32.         row--; // mine is already there, don't repeat for same block  
  33.       }  
  34.       // plant mine at this location  
  35.       blocks[mineColumn + 1][mineRow + 1].plantMine();  
  36.     }  
  37.     // exclude the user clicked location  
  38.     else 
  39.     {  
  40.       row--;  
  41.     }  
  42.   }  
  43.  
  44.   int nearByMineCount;  
  45.  
  46.   // count number of mines in surrounding blocks   
  47.   ...  
  48. }  
  49.  

5.點擊雷塊的效果

 

  1. private void rippleUncover(int rowClicked, int columnClicked)  
  2. {  
  3.   // don't open flagged or mined rows  
  4.   if (blocks[rowClicked][columnClicked].hasMine() || blocks[rowClicked][columnClicked].isFlagged())  
  5.   {  
  6.     return;  
  7.   }  
  8.  
  9.   // open clicked block  
  10.   blocks[rowClicked][columnClicked].OpenBlock();  
  11.  
  12.   // if clicked block have nearby mines then don't open further  
  13.   if (blocks[rowClicked][columnClicked].getNumberOfMinesInSorrounding() != 0 )  
  14.   {  
  15.     return;  
  16.   }  
  17.  
  18.   // open next 3 rows and 3 columns recursively  
  19.   for (int row = 0; row < 3; row++)  
  20.   {  
  21.     for (int column = 0; column < 3; column++)  
  22.     {  
  23.       // check all the above checked conditions  
  24.       // if met then open subsequent blocks  
  25.       if (blocks[rowClicked + row - 1][columnClicked + column - 1].isCovered()  
  26.           && (rowClicked + row - 1 > 0) && (columnClicked + column - 1 > 0)  
  27.           && (rowClicked + row - 1 < numberOfRowsInMineField + 1)   
  28.           && (columnClicked + column - 1 < numberOfColumnsInMineField + 1))  
  29.       {  
  30.         rippleUncover(rowClicked + row - 1, columnClicked + column - 1 );  
  31.       }   
  32.     }  
  33.   }  
  34.   return;  
  35. }  
  36.  

6.以問好標記空白

 

  1. blocks[row][column].setOnLongClickListener(new OnLongClickListener()  
  2. {  
  3.   public boolean onLongClick(View view)  
  4.   {  
  5.     // simulate a left-right (middle) click  
  6.     // if it is a long click on an opened mine then  
  7.     // open all surrounding blocks  
  8.     ...  
  9.  
  10.     // if clicked block is enabled, clickable or flagged  
  11.     if (blocks[currentRow][currentColumn].isClickable() &&   
  12.         (blocks[currentRow][currentColumn].isEnabled() || blocks[currentRow][currentColumn].isFlagged()))  
  13.     {  
  14.  
  15.       // for long clicks set:  
  16.       // 1. empty blocks to flagged  
  17.       // 2. flagged to question mark  
  18.       // 3. question mark to blank  
  19.  
  20.       // case 1. set blank block to flagged  
  21.       if (!blocks[currentRow][currentColumn].isFlagged() && !blocks[currentRow][currentColumn].isQuestionMarked())  
  22.       {  
  23.         blocks[currentRow][currentColumn].setBlockAsDisabled(false);  
  24.         blocks[currentRow][currentColumn].setFlagIcon(true);  
  25.         blocks[currentRow][currentColumn].setFlagged(true);  
  26.         minesToFind--; //reduce mine count  
  27.         updateMineCountDisplay();  
  28.       }  
  29.       // case 2. set flagged to question mark  
  30.       else if (!blocks[currentRow][currentColumn].isQuestionMarked())  
  31.       {  
  32.         blocks[currentRow][currentColumn].setBlockAsDisabled(true);  
  33.         blocks[currentRow][currentColumn].setQuestionMarkIcon(true);  
  34.         blocks[currentRow][currentColumn].setFlagged(false);  
  35.         blocks[currentRow][currentColumn].setQuestionMarked(true);  
  36.         minesToFind++; // increase mine count  
  37.         updateMineCountDisplay();  
  38.       }  
  39.       // case 3. change to blank square  
  40.       else 
  41.       {  
  42.         blocks[currentRow][currentColumn].setBlockAsDisabled(true);  
  43.         blocks[currentRow][currentColumn].clearAllIcons();  
  44.         blocks[currentRow][currentColumn].setQuestionMarked(false);  
  45.         // if it is flagged then increment mine count  
  46.         if (blocks[currentRow][currentColumn].isFlagged())  
  47.         {  
  48.           minesToFind++; // increase mine count  
  49.           updateMineCountDisplay();  
  50.         }  
  51.         // remove flagged status  
  52.         blocks[currentRow][currentColumn].setFlagged(false);  
  53.       }  
  54.         
  55.       updateMineCountDisplay(); // update mine display  
  56.     }  
  57.  
  58.     return true;  
  59.   }  
  60. });  
  61.  

7.記錄勝負

  1. // check status of the game at each step  
  2. if (blocks[currentRow + previousRow][currentColumn + previousColumn].hasMine())  
  3. {  
  4.   // oops game over  
  5.   finishGame(currentRow + previousRow, currentColumn + previousColumn);  
  6. }  
  7.  
  8. // did we win the game  
  9. if (checkGameWin())  
  10. {  
  11.   // mark game as win  
  12.   winGame();  
  13. }  
  14.  
  15. private boolean checkGameWin()  
  16. {  
  17.   for (int row = 1; row < numberOfRowsInMineField + 1; row++)  
  18.   {  
  19.     for (int column = 1; column < numberOfColumnsInMineField + 1; column++)  
  20.     {  
  21.       if (!blocks[row][column].hasMine() && blocks[row][column].isCovered())  
  22.       {  
  23.         return false;  
  24.       }  
  25.     }  
  26.   }  
  27.   return true;  
  28. }  
  29.  

 

8.完整代碼

MinesweeperGame.java

  1. package com.VertexVerveInc.Games;  
  2.  
  3. import java.util.Random;  
  4.  
  5. import android.app.Activity;  
  6. import android.os.Bundle;  
  7. import android.os.Handler;  
  8. import android.util.Log;  
  9. import android.view.Gravity;  
  10. import android.view.View;  
  11. import android.view.View.OnClickListener;  
  12. import android.view.View.OnLongClickListener;  
  13. import android.widget.ImageButton;  
  14. import android.widget.ImageView;  
  15. import android.widget.LinearLayout;  
  16. import android.widget.TableLayout;  
  17. import android.widget.TableRow;  
  18. import android.widget.TextView;  
  19. import android.widget.Toast;  
  20. import android.widget.TableRow.LayoutParams;  
  21.  
  22. public class MinesweeperGame extends Activity {  
  23.  private TextView txtMineCount;  
  24.  private TextView txtTimer;  
  25.  private ImageButton btnSmile;  
  26.  private TableLayout mineField;  
  27.  
  28.  private Block blocks[][]; // blocks for mine field  
  29.  private int blockDimension = 24; // width of each block  
  30.  private int blockPadding = 2; // padding between blocks  
  31.  
  32.  private int numberOfRowsInMineField = 9;  
  33.  private int numberOfColumnsInMineField = 9;  
  34.  private int totalNumberOfMines = 10;  
  35.  
  36.  // timer to keep track of time elapsed  
  37.  private Handler timer = new Handler();  
  38.  private int secondsPassed = 0;  
  39.  
  40.  private boolean isTimerStarted; // check if timer already started or not  
  41.  private boolean areMinesSet; // check if mines are planted in blocks  
  42.  private boolean isGameOver;  
  43.  private int minesToFind; // number of mines yet to be discovered  
  44.  
  45.  /** Called when the activity is first created. */ 
  46.  @Override 
  47.  public void onCreate(Bundle savedInstanceState) {  
  48.   super.onCreate(savedInstanceState);  
  49.   setContentView(R.layout.test);  
  50.     
  51.   txtMineCount = (TextView) findViewById(R.id.minecount);  
  52.        txtTimer = (TextView) findViewById(R.id.timer);  
  53.       
  54.        btnSmile = (ImageButton) findViewById(R.id.smiley);  
  55.        btnSmile.setOnClickListener(new OnClickListener()  
  56.        {  
  57.         @Override 
  58.         public void onClick(View view)  
  59.         {  
  60.          endExistingGame();  
  61.          startNewGame();  
  62.         }  
  63.        });  
  64.          
  65.        mineField = (TableLayout)findViewById(R.id.minefield);  
  66.          
  67.        showDialog("Click smiley to start New Game", 2000, true, false);  
  68.          
  69.  }  
  70.  
  71.  private void startNewGame() {  
  72.   createMineField();  
  73.   // display all blocks in UI  
  74.   showMineField();  
  75.  
  76.   minesToFind = totalNumberOfMines;  
  77.   isGameOver = false;  
  78.   secondsPassed = 0;  
  79.  
  80.  }  
  81.  
  82.  private void createMineField() {  
  83.   // we take one row extra row for each side  
  84.   // overall two extra rows and two extra columns  
  85.   // first and last row/column are used for calculations purposes only  
  86.   // x|xxxxxxxxxxxxxx|x  
  87.   // ------------------  
  88.   // x| |x  
  89.   // x| |x  
  90.   // ------------------  
  91.   // x|xxxxxxxxxxxxxx|x  
  92.   // the row and columns marked as x are just used to keep counts of near  
  93.   // by mines  
  94.  
  95.   blocks = new Block[numberOfRowsInMineField + 2][numberOfColumnsInMineField + 2];  
  96.  
  97.   for (int row = 0; row < numberOfColumnsInMineField + 2; row++) {  
  98.    for (int column = 0; column < numberOfColumnsInMineField + 2; column++) {  
  99.     blocks[row][column] = new Block(this);  
  100.     blocks[row][column].setDefaults();  
  101.  
  102.     // pass current row and column number as final int's to event  
  103.     // listeners  
  104.     // this way we can ensure that each event listener is associated  
  105.     // to  
  106.     // particular instance of block only  
  107.     final int currentRow = row;  
  108.     final int currentColumn = column;  
  109.  
  110.     blocks[row][column].setOnClickListener(new OnClickListener() {  
  111.  
  112.      @Override 
  113.      public void onClick(View v) {  
  114.       // start timer on first click  
  115.       if (!isTimerStarted) {  
  116.        startTimer();  
  117.        isTimerStarted = true;  
  118.       }  
  119.  
  120.       // set mines on first click  
  121.       if (!areMinesSet) {  
  122.        areMinesSet = true;  
  123.        setMines(currentRow, currentColumn);  
  124.       }  
  125.  
  126.       // this is not first click  
  127.       // check if current block is flagged  
  128.       // if flagged the don't do anything  
  129.       // as that operation is handled by LongClick  
  130.       // if block is not flagged then uncover nearby blocks  
  131.       // till we get numbered mines  
  132.       if (!blocks[currentRow][currentColumn].isFlagged()) {  
  133.        // open nearby blocks till we get numbered blocks  
  134.        rippleUncover(currentRow, currentColumn);  
  135.  
  136.        // did we clicked a mine  
  137.        if (blocks[currentRow][currentColumn].hasMine()) {  
  138.         // Oops, game over  
  139.         finishGame(currentRow, currentColumn);  
  140.        }  
  141.  
  142.        // check if we win the game  
  143.        if (checkGameWin()) {  
  144.         // mark game as win  
  145.         winGame();  
  146.        }  
  147.       }  
  148.      }  
  149.  
  150.     });  
  151.  
  152.     // add Long Click listener  
  153.     // this is treated as right mouse click listener  
  154.     blocks[row][column]  
  155.       .setOnLongClickListener(new OnLongClickListener() {  
  156.        public boolean onLongClick(View view) {  
  157.         // simulate a left-right (middle) click  
  158.         // if it is a long click on an opened mine then  
  159.         // open all surrounding blocks  
  160.         if (!blocks[currentRow][currentColumn]  
  161.           .isCovered()  
  162.           && (blocks[currentRow][currentColumn]  
  163.             .getNumberOfMinesInSorrounding() > 0)  
  164.           && !isGameOver) {  
  165.          int nearbyFlaggedBlocks = 0;  
  166.          for (int previousRow = -1; previousRow < 2; previousRow++) {  
  167.           for (int previousColumn = -1; previousColumn < 2; previousColumn++) {  
  168.            if (blocks[currentRow + previousRow][currentColumn  
  169.              + previousColumn]  
  170.              .isFlagged()) {  
  171.             nearbyFlaggedBlocks++;  
  172.            }  
  173.           }  
  174.          }  
  175.  
  176.          // if flagged block count is equal to nearby  
  177.          // mine count  
  178.          // then open nearby blocks  
  179.          if (nearbyFlaggedBlocks == blocks[currentRow][currentColumn]  
  180.            .getNumberOfMinesInSorrounding()) {  
  181.           for (int previousRow = -1; previousRow < 2; previousRow++) {  
  182.            for (int previousColumn = -1; previousColumn < 2; previousColumn++) {  
  183.             // don't open flagged blocks  
  184.             if (!blocks[currentRow  
  185.               + previousRow][currentColumn  
  186.               + previousColumn]  
  187.               .isFlagged()) {  
  188.              // open blocks till we get  
  189.              // numbered block  
  190.              rippleUncover(  
  191.                currentRow  
  192.                  + previousRow,  
  193.                currentColumn  
  194.                  + previousColumn);  
  195.  
  196.              // did we clicked a mine  
  197.              if (blocks[currentRow  
  198.                + previousRow][currentColumn  
  199.                + previousColumn]  
  200.                .hasMine()) {  
  201.               // oops game over  
  202.               finishGame(  
  203.                 currentRow  
  204.                   + previousRow,  
  205.                 currentColumn  
  206.                   + previousColumn);  
  207.              }  
  208.  
  209.              // did we win the game  
  210.              if (checkGameWin()) {  
  211.               // mark game as win  
  212.               winGame();  
  213.              }  
  214.             }  
  215.            }  
  216.           }  
  217.          }  
  218.  
  219.          // as we no longer want to judge this  
  220.          // gesture so return  
  221.          // not returning from here will actually  
  222.          // trigger other action  
  223.          // which can be marking as a flag or  
  224.          // question mark or blank  
  225.          return true;  
  226.         }  
  227.  
  228.         // if clicked block is enabled, clickable or  
  229.         // flagged  
  230.         if (blocks[currentRow][currentColumn]  
  231.           .isClickable()  
  232.           && (blocks[currentRow][currentColumn]  
  233.             .isEnabled() || blocks[currentRow][currentColumn]  
  234.             .isFlagged())) {  
  235.  
  236.          // for long clicks set:  
  237.          // 1. empty blocks to flagged  
  238.          // 2. flagged to question mark  
  239.          // 3. question mark to blank  
  240.  
  241.          // case 1. set blank block to flagged  
  242.          if (!blocks[currentRow][currentColumn]  
  243.            .isFlagged()  
  244.            && !blocks[currentRow][currentColumn]  
  245.              .isQuestionMarked()) {  
  246.           blocks[currentRow][currentColumn]  
  247.             .setBlockAsDisabled(false);  
  248.           blocks[currentRow][currentColumn]  
  249.             .setFlagIcon(true);  
  250.           blocks[currentRow][currentColumn]  
  251.             .setFlagged(true);  
  252.           minesToFind--; // reduce mine count  
  253.           updateMineCountDisplay();  
  254.          }  
  255.          // case 2. set flagged to question mark  
  256.          else if (!blocks[currentRow][currentColumn]  
  257.            .isQuestionMarked()) {  
  258.           blocks[currentRow][currentColumn]  
  259.             .setBlockAsDisabled(true);  
  260.           blocks[currentRow][currentColumn]  
  261.             .setQuestionMarkIcon(true);  
  262.           blocks[currentRow][currentColumn]  
  263.             .setFlagged(false);  
  264.           blocks[currentRow][currentColumn]  
  265.             .setQuestionMarked(true);  
  266.           minesToFind++; // increase mine count  
  267.           updateMineCountDisplay();  
  268.          }  
  269.          // case 3. change to blank square  
  270.          else {  
  271.           blocks[currentRow][currentColumn]  
  272.             .setBlockAsDisabled(true);  
  273.           blocks[currentRow][currentColumn]  
  274.             .clearAllIcons();  
  275.           blocks[currentRow][currentColumn]  
  276.             .setQuestionMarked(false);  
  277.           // if it is flagged then increment mine  
  278.           // count  
  279.           if (blocks[currentRow][currentColumn]  
  280.             .isFlagged()) {  
  281.            minesToFind++; // increase mine  
  282.            // count  
  283.            updateMineCountDisplay();  
  284.           }  
  285.           // remove flagged status  
  286.           blocks[currentRow][currentColumn]  
  287.             .setFlagged(false);  
  288.          }  
  289.  
  290.          updateMineCountDisplay();   
  291.          // update mine  
  292.          // display  
  293.         }  
  294.  
  295.         return true;  
  296.        }  
  297.       });  
  298.    }  
  299.   }  
  300.  }  
  301.  
  302.  private void showMineField() {  
  303.   for (int row = 1; row < numberOfRowsInMineField + 1; row++) {  
  304.    TableRow tableRow = new TableRow(this);  
  305.    tableRow.setLayoutParams(new LayoutParams(  
  306.      (blockDimension + 2 * blockPadding)  
  307.        * numberOfColumnsInMineField, blockDimension + 2 
  308.        * blockPadding));  
  309.    for (int column = 1; column < numberOfColumnsInMineField + 1; column++) {  
  310.     blocks[row][column].setLayoutParams(new LayoutParams(  
  311.       blockDimension + 2 * blockPadding, blockDimension + 2 
  312.         * blockPadding));  
  313.     blocks[row][column].setPadding(blockPadding, blockPadding,  
  314.       blockPadding, blockPadding);  
  315.     tableRow.addView(blocks[row][column]);  
  316.    }  
  317.    mineField.addView(tableRow, new TableLayout.LayoutParams(  
  318.      (blockDimension + 2 * blockPadding)  
  319.        * numberOfColumnsInMineField, blockDimension + 2 
  320.        * blockPadding));  
  321.   }  
  322.  }  
  323.  
  324.  private void endExistingGame() {  
  325.   stopTimer(); // stop if timer is running  
  326.   txtTimer.setText("000"); // revert all text  
  327.   txtMineCount.setText("000"); // revert mines count  
  328.   btnSmile.setBackgroundResource(R.drawable.smile);  
  329.  
  330.   // remove all rows from mineField TableLayout  
  331.   mineField.removeAllViews();  
  332.  
  333.   // set all variables to support end of game  
  334.   isTimerStarted = false;  
  335.   areMinesSet = false;  
  336.   isGameOver = false;  
  337.   minesToFind = 0;  
  338.  
  339.  }  
  340.  
  341.  private boolean checkGameWin() {  
  342.   for (int row = 1; row < numberOfRowsInMineField + 1; row++) {  
  343.    for (int column = 1; column < numberOfColumnsInMineField + 1; column++) {  
  344.     if (!blocks[row][column].hasMine()  
  345.       && blocks[row][column].isCovered()) {  
  346.      return false;  
  347.     }  
  348.    }  
  349.   }  
  350.   return true;  
  351.  }  
  352.  
  353.  private void updateMineCountDisplay() {  
  354.   if (minesToFind < 0) {  
  355.    txtMineCount.setText(Integer.toString(minesToFind));  
  356.   } else if (minesToFind < 10) {  
  357.    txtMineCount.setText("00" + Integer.toString(minesToFind));  
  358.   } else if (minesToFind < 100) {  
  359.    txtMineCount.setText("0" + Integer.toString(minesToFind));  
  360.   } else {  
  361.    txtMineCount.setText(Integer.toString(minesToFind));  
  362.   }  
  363.  }  
  364.  
  365.  private void winGame() {  
  366.   stopTimer();  
  367.   isTimerStarted = false;  
  368.   isGameOver = true;  
  369.   minesToFind = 0; // set mine count to 0  
  370.  
  371.   // set icon to cool dude  
  372.   btnSmile.setBackgroundResource(R.drawable.cool);  
  373.  
  374.   updateMineCountDisplay(); // update mine count  
  375.  
  376.   // disable all buttons  
  377.   // set flagged all un-flagged blocks  
  378.   for (int row = 1; row < numberOfRowsInMineField + 1; row++) {  
  379.    for (int column = 1; column < numberOfColumnsInMineField + 1; column++) {  
  380.     blocks[row][column].setClickable(false);  
  381.     if (blocks[row][column].hasMine()) {  
  382.      blocks[row][column].setBlockAsDisabled(false);  
  383.      blocks[row][column].setFlagIcon(true);  
  384.     }  
  385.    }  
  386.   }  
  387.  
  388.   // show message  
  389.   showDialog("You won in " + Integer.toString(secondsPassed)  
  390.     + " seconds!", 1000, false, true);  
  391.  }  
  392.  
  393.  private void finishGame(int currentRow, int currentColumn) {  
  394.   isGameOver = true; // mark game as over  
  395.   stopTimer(); // stop timer  
  396.   isTimerStarted = false;  
  397.   btnSmile.setBackgroundResource(R.drawable.sad);  
  398.  
  399.   // show all mines  
  400.   // disable all blocks  
  401.   for (int row = 1; row < numberOfRowsInMineField + 1; row++) {  
  402.    for (int column = 1; column < numberOfColumnsInMineField + 1; column++) {  
  403.     // disable block  
  404.     blocks[row][column].setBlockAsDisabled(false);  
  405.  
  406.     // block has mine and is not flagged  
  407.     if (blocks[row][column].hasMine()  
  408.       && !blocks[row][column].isFlagged()) {  
  409.      // set mine icon  
  410.      blocks[row][column].setMineIcon(false);  
  411.     }  
  412.  
  413.     // block is flagged and doesn't not have mine  
  414.     if (!blocks[row][column].hasMine()  
  415.       && blocks[row][column].isFlagged()) {  
  416.      // set flag icon  
  417.      blocks[row][column].setFlagIcon(false);  
  418.     }  
  419.  
  420.     // block is flagged  
  421.     if (blocks[row][column].isFlagged()) {  
  422.      // disable the block  
  423.      blocks[row][column].setClickable(false);  
  424.     }  
  425.    }  
  426.   }  
  427.  
  428.   // trigger mine  
  429.   blocks[currentRow][currentColumn].triggerMine();  
  430.  
  431.   // show message  
  432.   showDialog("You tried for " + Integer.toString(secondsPassed)  
  433.     + " seconds!", 1000, false, false);  
  434.  }  
  435.  
  436.  private void setMines(int currentRow, int currentColumn) {  
  437.   // set mines excluding the location where user clicked  
  438.   Random rand = new Random();  
  439.   int mineRow, mineColumn;  
  440.  
  441.   for (int row = 0; row < totalNumberOfMines; row++) {  
  442.    mineRow = rand.nextInt(numberOfColumnsInMineField);  
  443.    mineColumn = rand.nextInt(numberOfRowsInMineField);  
  444.    if ((mineRow + 1 != currentColumn)  
  445.      || (mineColumn + 1 != currentRow)) {  
  446.     if (blocks[mineColumn + 1][mineRow + 1].hasMine()) {  
  447.      row--; // mine is already there, don't repeat for same block  
  448.     }  
  449.     // plant mine at this location  
  450.     blocks[mineColumn + 1][mineRow + 1].plantMine();  
  451.    }  
  452.    // exclude the user clicked location  
  453.    else {  
  454.     row--;  
  455.    }  
  456.   }  
  457.  
  458.   int nearByMineCount;  
  459.  
  460.   for (int row = 0; row < numberOfRowsInMineField + 2; row++) {  
  461.    for (int column = 0; column < numberOfColumnsInMineField + 2; column++) {  
  462.     // for each block find nearby mine count  
  463.     nearByMineCount = 0;  
  464.     if ((row != 0) && (row != (numberOfRowsInMineField + 1))  
  465.       && (column != 0)  
  466.       && (column != (numberOfColumnsInMineField + 1))) {  
  467.      // check in all nearby blocks  
  468.      for (int previousRow = -1; previousRow < 2; previousRow++) {  
  469.       for (int previousColumn = -1; previousColumn < 2; previousColumn++) {  
  470.        if (blocks[row + previousRow][column  
  471.          + previousColumn].hasMine()) {  
  472.         // a mine was found so increment the counter  
  473.         nearByMineCount++;  
  474.        }  
  475.       }  
  476.      }  
  477.  
  478.      blocks[row][column]  
  479.        .setNumberOfMinesInSurrounding(nearByMineCount);  
  480.     }  
  481.     // for side rows (0th and last row/column)  
  482.     // set count as 9 and mark it as opened  
  483.     else {  
  484.      blocks[row][column].setNumberOfMinesInSurrounding(9);  
  485.      blocks[row][column].OpenBlock();  
  486.     }  
  487.    }  
  488.   }  
  489.  }  
  490.  
  491.  private void rippleUncover(int rowClicked, int columnClicked) {  
  492.   // don't open flagged or mined rows  
  493.   if (blocks[rowClicked][columnClicked].hasMine()  
  494.     || blocks[rowClicked][columnClicked].isFlagged()) {  
  495.    return;  
  496.   }  
  497.  
  498.   // open clicked block  
  499.   blocks[rowClicked][columnClicked].OpenBlock();  
  500.  
  501.   // if clicked block have nearby mines then don't open further  
  502.   if (blocks[rowClicked][columnClicked].getNumberOfMinesInSorrounding() != 0) {  
  503.    return;  
  504.   }  
  505.  
  506.   // open next 3 rows and 3 columns recursively  
  507.   for (int row = 0; row < 3; row++) {  
  508.    for (int column = 0; column < 3; column++) {  
  509.     // check all the above checked conditions  
  510.     // if met then open subsequent blocks  
  511.     if (blocks[rowClicked + row - 1][columnClicked + column - 1]  
  512.       .isCovered()  
  513.       && (rowClicked + row - 1 > 0)  
  514.       && (columnClicked + column - 1 > 0)  
  515.       && (rowClicked + row - 1 < numberOfRowsInMineField + 1)  
  516.       && (columnClicked + column - 1 < numberOfColumnsInMineField + 1)) {  
  517.      rippleUncover(rowClicked + row - 1, columnClicked + column  
  518.        - 1);  
  519.     }  
  520.    }  
  521.   }  
  522.   return;  
  523.  }  
  524.  
  525.  public void startTimer() {  
  526.   if (secondsPassed == 0) {  
  527.    timer.removeCallbacks(updateTimeElasped);  
  528.    // tell timer to run call back after 1 second  
  529.    timer.postDelayed(updateTimeElasped, 1000);  
  530.    Log.i("tag",String.valueOf((timer.postDelayed(updateTimeElasped, 1000))) );  
  531.   }  
  532.  }  
  533.  
  534.  public void stopTimer() {  
  535.   // disable call backs  
  536.   timer.removeCallbacks(updateTimeElasped);  
  537.  }  
  538.  
  539.  // timer call back when timer is ticked  
  540.  private Runnable updateTimeElasped = new Runnable() {  
  541.   public void run() {  
  542.    long currentMilliseconds = System.currentTimeMillis();  
  543.    ++secondsPassed;  
  544.    txtTimer.setText(Integer.toString(secondsPassed));  
  545.  
  546.    // add notification  
  547.    timer.postAtTime(this, currentMilliseconds);  
  548.    // notify to call back after 1 seconds  
  549.    // basically to remain in the timer loop  
  550.    timer.postDelayed(updateTimeElasped, 1000);  
  551.   }  
  552.  };  
  553.  
  554.  private void showDialog(String message, int milliseconds,  
  555.    boolean useSmileImage, boolean useCoolImage) {  
  556.   // show message  
  557.   Toast dialog = Toast.makeText(getApplicationContext(), message,  
  558.     Toast.LENGTH_LONG);  
  559.  
  560.   dialog.setGravity(Gravity.CENTER, 0, 0);  
  561.   LinearLayout dialogView = (LinearLayout) dialog.getView();  
  562.   ImageView coolImage = new ImageView(getApplicationContext());  
  563.   if (useSmileImage) {  
  564.    coolImage.setImageResource(R.drawable.smile);  
  565.   } else if (useCoolImage) {  
  566.    coolImage.setImageResource(R.drawable.cool);  
  567.   } else {  
  568.    coolImage.setImageResource(R.drawable.sad);  
  569.   }  
  570.   dialogView.addView(coolImage, 0);  
  571.   dialog.setDuration(milliseconds);  
  572.   dialog.show();  
  573.   Log.i("tag", "showDialog()");  
  574.  }  
  575.  
  576. }  
  577.  

 

源碼下載

轉自:http://www.cnblogs.com/salam/archive/2010/10/03/1841650.html

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved