編輯:Android開發實例
最近由於項目需要學習了一下Android ,感覺汗不錯。做了一個Android版的掃雷游戲。
游戲簡介
在此游戲中,我們使用一個塊的網格,其中有一些隨機的地雷
下面是效果圖
一、應用程序布局
使用TableLayout布局控件。設置3行。
- <?xml version="1.0" encoding="utf-8"?>
- <TableLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:background="@drawable/back">
- <TableRow>
- <TextView android:id="@+id/timer" android:layout_column="0"
- android:layout_width="fill_parent" android:layout_height="48px"
- android:gravity="center_horizontal" android:padding="5dip"
- android:textColor="#FFFFFF" android:textSize="35sp"
- android:text=" 0" />
- <ImageButton android:id="@+id/smiley"
- android:layout_column="1" android:scaleType="center" android:padding="5dip"
- android:layout_width="48px" android:background="@drawable/smiley_button_states"
- android:layout_height="48px" />
- <TextView android:id="@+id/minecount" android:layout_column="2"
- android:layout_width="fill_parent" android:layout_height="48px"
- android:gravity="center_horizontal" android:padding="5dip"
- android:textColor="#FFFFFF" android:textSize="35sp" android:text="000" />
- </TableRow>
- <TableRow>
- <TextView android:layout_column="0" android:layout_height="50px"
- android:layout_width="fill_parent" android:layout_span="3"
- android:padding="10dip" />
- </TableRow>
- <TableRow>
- <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/minefield" android:layout_width="260px"
- android:layout_height="260px" android:gravity="bottom"
- android:stretchColumns="*" android:layout_span="3" android:padding="5dip">
- </TableLayout>
- </TableRow>
- </TableLayout>
二、地雷塊
Block.java
- /**
- * 地雷的塊,繼承自Button
- * @author 記憶的永恆
- *
- */
- public class Block extends Button {
- private boolean isCovered; // 塊是否覆蓋
- private boolean isMined; // 下個塊
- private boolean isFlagged; // 是否將該塊標記為一個潛在的地雷
- private boolean isQuestionMarked; // 是否是塊的問題標記
- private boolean isClickable; // 是否可以單擊
- private int numberOfMinesInSurrounding; // 在附近的地雷數量塊
- public Block(Context context) {
- super(context);
- // TODO Auto-generated constructor stub
- }
- public Block(Context context, AttributeSet attrs) {
- super(context, attrs);
- // TODO Auto-generated constructor stub
- }
- public Block(Context context, AttributeSet attrs, int defStyle)
- {
- super(context, attrs, defStyle);
- }
- /**
- * 設置默認參數
- */
- public void setDefaults() {
- isCovered = true;
- isMined = false;
- isFlagged = false;
- isQuestionMarked = false;
- isClickable = true;
- numberOfMinesInSurrounding = 0;
- this.setBackgroundResource(R.drawable.square_blue);
- setBoldFont();
- }
- public void setNumberOfSurroundingMines(int number) {
- this.setBackgroundResource(R.drawable.square_grey);
- updateNumber(number);
- }
- public void setMineIcon(boolean enabled) {
- this.setText("M");
- if (!enabled) {
- this.setBackgroundResource(R.drawable.square_grey);
- this.setTextColor(Color.RED);
- }
- else {
- this.setTextColor(Color.BLACK);
- }
- }
- public void setFlagIcon(boolean enabled) {
- this.setText("F");
- if (!enabled) {
- this.setBackgroundResource(R.drawable.square_grey);
- this.setTextColor(Color.RED);
- }
- else {
- this.setTextColor(Color.BLACK);
- }
- }
- public void setQuestionMarkIcon(boolean enabled) {
- this.setText("?");
- if (!enabled) {
- this.setBackgroundResource(R.drawable.square_grey);
- this.setTextColor(Color.RED);
- }
- else {
- this.setTextColor(Color.BLACK);
- }
- }
- public void setBlockAsDisabled(boolean enabled) {
- if (!enabled) {
- this.setBackgroundResource(R.drawable.square_grey);
- }
- else {
- this.setTextColor(R.drawable.square_blue);
- }
- }
- public void clearAllIcons() {
- this.setText("");
- }
- private void setBoldFont() {
- this.setTypeface(null, Typeface.BOLD);
- }
- public void OpenBlock() {
- if (!isCovered) {
- return;
- }
- setBlockAsDisabled(false);
- isCovered = false;
- if (hasMine()) {
- setMineIcon(false);
- }
- else {
- setNumberOfSurroundingMines(numberOfMinesInSurrounding);
- }
- }
- public void updateNumber(int text) {
- if (text != 0) {
- this.setText(Integer.toString(text));
- switch (text) {
- case 1:
- this.setTextColor(Color.BLUE);
- break;
- case 2:
- this.setTextColor(Color.rgb(0, 100, 0));
- break;
- case 3:
- this.setTextColor(Color.RED);
- break;
- case 4:
- this.setTextColor(Color.rgb(85, 26, 139));
- break;
- case 5:
- this.setTextColor(Color.rgb(139, 28, 98));
- break;
- case 6:
- this.setTextColor(Color.rgb(238, 173, 14));
- break;
- case 7:
- this.setTextColor(Color.rgb(47, 79, 79));
- break;
- case 8:
- this.setTextColor(Color.rgb(71, 71, 71));
- break;
- case 9:
- this.setTextColor(Color.rgb(205, 205, 0));
- break;
- }
- }
- }
- public void plantMine() {
- isMined = true;
- }
- public void triggerMine() {
- setMineIcon(true);
- this.setTextColor(Color.RED);
- }
- public boolean isCovered() {
- return isCovered;
- }
- public boolean hasMine() {
- return isMined;
- }
- public void setNumberOfMinesInSurrounding(int number) {
- numberOfMinesInSurrounding = number;
- }
- public int getNumberOfMinesInSorrounding() {
- return numberOfMinesInSurrounding;
- }
- public boolean isFlagged() {
- return isFlagged;
- }
- public void setFlagged(boolean flagged) {
- isFlagged = flagged;
- }
- public boolean isQuestionMarked() {
- return isQuestionMarked;
- }
- public void setQuestionMarked(boolean questionMarked) {
- isQuestionMarked = questionMarked;
- }
- public boolean isClickable() {
- return isClickable;
- }
- public void setClickable(boolean clickable) {
- isClickable = clickable;
- }
- }
三、主界面
1.TableLayout動態添加行
- mineField = (TableLayout)findViewById(R.id.MineField);
- private void showMineField()
- {
- for (int row = 1; row < numberOfRowsInMineField + 1; row++)
- {
- TableRow tableRow = new TableRow(this);
- tableRow.setLayoutParams(new LayoutParams((blockDimension + 2 * blockPadding) *
- numberOfColumnsInMineField, blockDimension + 2 * blockPadding));
- for (int column = 1; column < numberOfColumnsInMineField + 1; column++)
- {
- blocks[row][column].setLayoutParams(new LayoutParams(
- blockDimension + 2 * blockPadding,
- blockDimension + 2 * blockPadding));
- blocks[row][column].setPadding(blockPadding, blockPadding, blockPadding, blockPadding);
- tableRow.addView(blocks[row][column]);
- }
- mineField.addView(tableRow,new TableLayout.LayoutParams(
- (blockDimension + 2 * blockPadding) * numberOfColumnsInMineField, blockDimension + 2 * blockPadding));
- }
- }
2.定時器Handler
- private Handler timer = new Handler();
- private int secondsPassed = 0;
- public void startTimer(){ if (secondsPassed == 0)
- {
- timer.removeCallbacks(updateTimeElasped);
- // tell timer to run call back after 1 second
- timer.postDelayed(updateTimeElasped, 1000);
- }
- }
- public void stopTimer()
- {
- // disable call backs
- timer.removeCallbacks(updateTimeElasped);
- }
- // timer call back when timer is ticked
- private Runnable updateTimeElasped = new Runnable()
- {
- public void run()
- {
- long currentMilliseconds = System.currentTimeMillis();
- ++secondsPassed;
- txtTimer.setText(Integer.toString(secondsPassed));
- // add notification
- timer.postAtTime(this, currentMilliseconds);
- // notify to call back after 1 seconds
- // basically to remain in the timer loop
- timer.postDelayed(updateTimeElasped, 1000);
- }
- };
3.第一次點擊
- private boolean isTimerStarted; // check if timer already started or not
- blocks[row][column].setOnClickListener(new OnClickListener()
- {
- @Override
- public void onClick(View view)
- {
- // start timer on first click
- if (!isTimerStarted)
- {
- startTimer();
- isTimerStarted = true;
- }
- ...
- }
- });
4.第一次點擊無雷
- private boolean areMinesSet; // check if mines are planted in blocks
- blocks[row][column].setOnClickListener(new OnClickListener()
- {
- @Override
- public void onClick(View view)
- {
- ...
- // set mines on first click
- if (!areMinesSet)
- {
- areMinesSet = true;
- setMines(currentRow, currentColumn);
- }
- }
- });
- private void setMines(int currentRow, int currentColumn)
- {
- // set mines excluding the location where user clicked
- Random rand = new Random();
- int mineRow, mineColumn;
- for (int row = 0; row < totalNumberOfMines; row++)
- {
- mineRow = rand.nextInt(numberOfColumnsInMineField);
- mineColumn = rand.nextInt(numberOfRowsInMineField);
- if ((mineRow + 1 != currentColumn) || (mineColumn + 1 != currentRow))
- {
- if (blocks[mineColumn + 1][mineRow + 1].hasMine())
- {
- row--; // mine is already there, don't repeat for same block
- }
- // plant mine at this location
- blocks[mineColumn + 1][mineRow + 1].plantMine();
- }
- // exclude the user clicked location
- else
- {
- row--;
- }
- }
- int nearByMineCount;
- // count number of mines in surrounding blocks
- ...
- }
5.點擊雷塊的效果
- private void rippleUncover(int rowClicked, int columnClicked)
- {
- // don't open flagged or mined rows
- if (blocks[rowClicked][columnClicked].hasMine() || blocks[rowClicked][columnClicked].isFlagged())
- {
- return;
- }
- // open clicked block
- blocks[rowClicked][columnClicked].OpenBlock();
- // if clicked block have nearby mines then don't open further
- if (blocks[rowClicked][columnClicked].getNumberOfMinesInSorrounding() != 0 )
- {
- return;
- }
- // open next 3 rows and 3 columns recursively
- for (int row = 0; row < 3; row++)
- {
- for (int column = 0; column < 3; column++)
- {
- // check all the above checked conditions
- // if met then open subsequent blocks
- if (blocks[rowClicked + row - 1][columnClicked + column - 1].isCovered()
- && (rowClicked + row - 1 > 0) && (columnClicked + column - 1 > 0)
- && (rowClicked + row - 1 < numberOfRowsInMineField + 1)
- && (columnClicked + column - 1 < numberOfColumnsInMineField + 1))
- {
- rippleUncover(rowClicked + row - 1, columnClicked + column - 1 );
- }
- }
- }
- return;
- }
6.以問好標記空白
- blocks[row][column].setOnLongClickListener(new OnLongClickListener()
- {
- public boolean onLongClick(View view)
- {
- // simulate a left-right (middle) click
- // if it is a long click on an opened mine then
- // open all surrounding blocks
- ...
- // if clicked block is enabled, clickable or flagged
- if (blocks[currentRow][currentColumn].isClickable() &&
- (blocks[currentRow][currentColumn].isEnabled() || blocks[currentRow][currentColumn].isFlagged()))
- {
- // for long clicks set:
- // 1. empty blocks to flagged
- // 2. flagged to question mark
- // 3. question mark to blank
- // case 1. set blank block to flagged
- if (!blocks[currentRow][currentColumn].isFlagged() && !blocks[currentRow][currentColumn].isQuestionMarked())
- {
- blocks[currentRow][currentColumn].setBlockAsDisabled(false);
- blocks[currentRow][currentColumn].setFlagIcon(true);
- blocks[currentRow][currentColumn].setFlagged(true);
- minesToFind--; //reduce mine count
- updateMineCountDisplay();
- }
- // case 2. set flagged to question mark
- else if (!blocks[currentRow][currentColumn].isQuestionMarked())
- {
- blocks[currentRow][currentColumn].setBlockAsDisabled(true);
- blocks[currentRow][currentColumn].setQuestionMarkIcon(true);
- blocks[currentRow][currentColumn].setFlagged(false);
- blocks[currentRow][currentColumn].setQuestionMarked(true);
- minesToFind++; // increase mine count
- updateMineCountDisplay();
- }
- // case 3. change to blank square
- else
- {
- blocks[currentRow][currentColumn].setBlockAsDisabled(true);
- blocks[currentRow][currentColumn].clearAllIcons();
- blocks[currentRow][currentColumn].setQuestionMarked(false);
- // if it is flagged then increment mine count
- if (blocks[currentRow][currentColumn].isFlagged())
- {
- minesToFind++; // increase mine count
- updateMineCountDisplay();
- }
- // remove flagged status
- blocks[currentRow][currentColumn].setFlagged(false);
- }
- updateMineCountDisplay(); // update mine display
- }
- return true;
- }
- });
7.記錄勝負
- // check status of the game at each step
- if (blocks[currentRow + previousRow][currentColumn + previousColumn].hasMine())
- {
- // oops game over
- finishGame(currentRow + previousRow, currentColumn + previousColumn);
- }
- // did we win the game
- if (checkGameWin())
- {
- // mark game as win
- winGame();
- }
- private boolean checkGameWin()
- {
- for (int row = 1; row < numberOfRowsInMineField + 1; row++)
- {
- for (int column = 1; column < numberOfColumnsInMineField + 1; column++)
- {
- if (!blocks[row][column].hasMine() && blocks[row][column].isCovered())
- {
- return false;
- }
- }
- }
- return true;
- }
8.完整代碼
MinesweeperGame.java
- package com.VertexVerveInc.Games;
- import java.util.Random;
- import android.app.Activity;
- import android.os.Bundle;
- import android.os.Handler;
- import android.util.Log;
- import android.view.Gravity;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.view.View.OnLongClickListener;
- import android.widget.ImageButton;
- import android.widget.ImageView;
- import android.widget.LinearLayout;
- import android.widget.TableLayout;
- import android.widget.TableRow;
- import android.widget.TextView;
- import android.widget.Toast;
- import android.widget.TableRow.LayoutParams;
- public class MinesweeperGame extends Activity {
- private TextView txtMineCount;
- private TextView txtTimer;
- private ImageButton btnSmile;
- private TableLayout mineField;
- private Block blocks[][]; // blocks for mine field
- private int blockDimension = 24; // width of each block
- private int blockPadding = 2; // padding between blocks
- private int numberOfRowsInMineField = 9;
- private int numberOfColumnsInMineField = 9;
- private int totalNumberOfMines = 10;
- // timer to keep track of time elapsed
- private Handler timer = new Handler();
- private int secondsPassed = 0;
- private boolean isTimerStarted; // check if timer already started or not
- private boolean areMinesSet; // check if mines are planted in blocks
- private boolean isGameOver;
- private int minesToFind; // number of mines yet to be discovered
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.test);
- txtMineCount = (TextView) findViewById(R.id.minecount);
- txtTimer = (TextView) findViewById(R.id.timer);
- btnSmile = (ImageButton) findViewById(R.id.smiley);
- btnSmile.setOnClickListener(new OnClickListener()
- {
- @Override
- public void onClick(View view)
- {
- endExistingGame();
- startNewGame();
- }
- });
- mineField = (TableLayout)findViewById(R.id.minefield);
- showDialog("Click smiley to start New Game", 2000, true, false);
- }
- private void startNewGame() {
- createMineField();
- // display all blocks in UI
- showMineField();
- minesToFind = totalNumberOfMines;
- isGameOver = false;
- secondsPassed = 0;
- }
- private void createMineField() {
- // we take one row extra row for each side
- // overall two extra rows and two extra columns
- // first and last row/column are used for calculations purposes only
- // x|xxxxxxxxxxxxxx|x
- // ------------------
- // x| |x
- // x| |x
- // ------------------
- // x|xxxxxxxxxxxxxx|x
- // the row and columns marked as x are just used to keep counts of near
- // by mines
- blocks = new Block[numberOfRowsInMineField + 2][numberOfColumnsInMineField + 2];
- for (int row = 0; row < numberOfColumnsInMineField + 2; row++) {
- for (int column = 0; column < numberOfColumnsInMineField + 2; column++) {
- blocks[row][column] = new Block(this);
- blocks[row][column].setDefaults();
- // pass current row and column number as final int's to event
- // listeners
- // this way we can ensure that each event listener is associated
- // to
- // particular instance of block only
- final int currentRow = row;
- final int currentColumn = column;
- blocks[row][column].setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- // start timer on first click
- if (!isTimerStarted) {
- startTimer();
- isTimerStarted = true;
- }
- // set mines on first click
- if (!areMinesSet) {
- areMinesSet = true;
- setMines(currentRow, currentColumn);
- }
- // this is not first click
- // check if current block is flagged
- // if flagged the don't do anything
- // as that operation is handled by LongClick
- // if block is not flagged then uncover nearby blocks
- // till we get numbered mines
- if (!blocks[currentRow][currentColumn].isFlagged()) {
- // open nearby blocks till we get numbered blocks
- rippleUncover(currentRow, currentColumn);
- // did we clicked a mine
- if (blocks[currentRow][currentColumn].hasMine()) {
- // Oops, game over
- finishGame(currentRow, currentColumn);
- }
- // check if we win the game
- if (checkGameWin()) {
- // mark game as win
- winGame();
- }
- }
- }
- });
- // add Long Click listener
- // this is treated as right mouse click listener
- blocks[row][column]
- .setOnLongClickListener(new OnLongClickListener() {
- public boolean onLongClick(View view) {
- // simulate a left-right (middle) click
- // if it is a long click on an opened mine then
- // open all surrounding blocks
- if (!blocks[currentRow][currentColumn]
- .isCovered()
- && (blocks[currentRow][currentColumn]
- .getNumberOfMinesInSorrounding() > 0)
- && !isGameOver) {
- int nearbyFlaggedBlocks = 0;
- for (int previousRow = -1; previousRow < 2; previousRow++) {
- for (int previousColumn = -1; previousColumn < 2; previousColumn++) {
- if (blocks[currentRow + previousRow][currentColumn
- + previousColumn]
- .isFlagged()) {
- nearbyFlaggedBlocks++;
- }
- }
- }
- // if flagged block count is equal to nearby
- // mine count
- // then open nearby blocks
- if (nearbyFlaggedBlocks == blocks[currentRow][currentColumn]
- .getNumberOfMinesInSorrounding()) {
- for (int previousRow = -1; previousRow < 2; previousRow++) {
- for (int previousColumn = -1; previousColumn < 2; previousColumn++) {
- // don't open flagged blocks
- if (!blocks[currentRow
- + previousRow][currentColumn
- + previousColumn]
- .isFlagged()) {
- // open blocks till we get
- // numbered block
- rippleUncover(
- currentRow
- + previousRow,
- currentColumn
- + previousColumn);
- // did we clicked a mine
- if (blocks[currentRow
- + previousRow][currentColumn
- + previousColumn]
- .hasMine()) {
- // oops game over
- finishGame(
- currentRow
- + previousRow,
- currentColumn
- + previousColumn);
- }
- // did we win the game
- if (checkGameWin()) {
- // mark game as win
- winGame();
- }
- }
- }
- }
- }
- // as we no longer want to judge this
- // gesture so return
- // not returning from here will actually
- // trigger other action
- // which can be marking as a flag or
- // question mark or blank
- return true;
- }
- // if clicked block is enabled, clickable or
- // flagged
- if (blocks[currentRow][currentColumn]
- .isClickable()
- && (blocks[currentRow][currentColumn]
- .isEnabled() || blocks[currentRow][currentColumn]
- .isFlagged())) {
- // for long clicks set:
- // 1. empty blocks to flagged
- // 2. flagged to question mark
- // 3. question mark to blank
- // case 1. set blank block to flagged
- if (!blocks[currentRow][currentColumn]
- .isFlagged()
- && !blocks[currentRow][currentColumn]
- .isQuestionMarked()) {
- blocks[currentRow][currentColumn]
- .setBlockAsDisabled(false);
- blocks[currentRow][currentColumn]
- .setFlagIcon(true);
- blocks[currentRow][currentColumn]
- .setFlagged(true);
- minesToFind--; // reduce mine count
- updateMineCountDisplay();
- }
- // case 2. set flagged to question mark
- else if (!blocks[currentRow][currentColumn]
- .isQuestionMarked()) {
- blocks[currentRow][currentColumn]
- .setBlockAsDisabled(true);
- blocks[currentRow][currentColumn]
- .setQuestionMarkIcon(true);
- blocks[currentRow][currentColumn]
- .setFlagged(false);
- blocks[currentRow][currentColumn]
- .setQuestionMarked(true);
- minesToFind++; // increase mine count
- updateMineCountDisplay();
- }
- // case 3. change to blank square
- else {
- blocks[currentRow][currentColumn]
- .setBlockAsDisabled(true);
- blocks[currentRow][currentColumn]
- .clearAllIcons();
- blocks[currentRow][currentColumn]
- .setQuestionMarked(false);
- // if it is flagged then increment mine
- // count
- if (blocks[currentRow][currentColumn]
- .isFlagged()) {
- minesToFind++; // increase mine
- // count
- updateMineCountDisplay();
- }
- // remove flagged status
- blocks[currentRow][currentColumn]
- .setFlagged(false);
- }
- updateMineCountDisplay();
- // update mine
- // display
- }
- return true;
- }
- });
- }
- }
- }
- private void showMineField() {
- for (int row = 1; row < numberOfRowsInMineField + 1; row++) {
- TableRow tableRow = new TableRow(this);
- tableRow.setLayoutParams(new LayoutParams(
- (blockDimension + 2 * blockPadding)
- * numberOfColumnsInMineField, blockDimension + 2
- * blockPadding));
- for (int column = 1; column < numberOfColumnsInMineField + 1; column++) {
- blocks[row][column].setLayoutParams(new LayoutParams(
- blockDimension + 2 * blockPadding, blockDimension + 2
- * blockPadding));
- blocks[row][column].setPadding(blockPadding, blockPadding,
- blockPadding, blockPadding);
- tableRow.addView(blocks[row][column]);
- }
- mineField.addView(tableRow, new TableLayout.LayoutParams(
- (blockDimension + 2 * blockPadding)
- * numberOfColumnsInMineField, blockDimension + 2
- * blockPadding));
- }
- }
- private void endExistingGame() {
- stopTimer(); // stop if timer is running
- txtTimer.setText("000"); // revert all text
- txtMineCount.setText("000"); // revert mines count
- btnSmile.setBackgroundResource(R.drawable.smile);
- // remove all rows from mineField TableLayout
- mineField.removeAllViews();
- // set all variables to support end of game
- isTimerStarted = false;
- areMinesSet = false;
- isGameOver = false;
- minesToFind = 0;
- }
- private boolean checkGameWin() {
- for (int row = 1; row < numberOfRowsInMineField + 1; row++) {
- for (int column = 1; column < numberOfColumnsInMineField + 1; column++) {
- if (!blocks[row][column].hasMine()
- && blocks[row][column].isCovered()) {
- return false;
- }
- }
- }
- return true;
- }
- private void updateMineCountDisplay() {
- if (minesToFind < 0) {
- txtMineCount.setText(Integer.toString(minesToFind));
- } else if (minesToFind < 10) {
- txtMineCount.setText("00" + Integer.toString(minesToFind));
- } else if (minesToFind < 100) {
- txtMineCount.setText("0" + Integer.toString(minesToFind));
- } else {
- txtMineCount.setText(Integer.toString(minesToFind));
- }
- }
- private void winGame() {
- stopTimer();
- isTimerStarted = false;
- isGameOver = true;
- minesToFind = 0; // set mine count to 0
- // set icon to cool dude
- btnSmile.setBackgroundResource(R.drawable.cool);
- updateMineCountDisplay(); // update mine count
- // disable all buttons
- // set flagged all un-flagged blocks
- for (int row = 1; row < numberOfRowsInMineField + 1; row++) {
- for (int column = 1; column < numberOfColumnsInMineField + 1; column++) {
- blocks[row][column].setClickable(false);
- if (blocks[row][column].hasMine()) {
- blocks[row][column].setBlockAsDisabled(false);
- blocks[row][column].setFlagIcon(true);
- }
- }
- }
- // show message
- showDialog("You won in " + Integer.toString(secondsPassed)
- + " seconds!", 1000, false, true);
- }
- private void finishGame(int currentRow, int currentColumn) {
- isGameOver = true; // mark game as over
- stopTimer(); // stop timer
- isTimerStarted = false;
- btnSmile.setBackgroundResource(R.drawable.sad);
- // show all mines
- // disable all blocks
- for (int row = 1; row < numberOfRowsInMineField + 1; row++) {
- for (int column = 1; column < numberOfColumnsInMineField + 1; column++) {
- // disable block
- blocks[row][column].setBlockAsDisabled(false);
- // block has mine and is not flagged
- if (blocks[row][column].hasMine()
- && !blocks[row][column].isFlagged()) {
- // set mine icon
- blocks[row][column].setMineIcon(false);
- }
- // block is flagged and doesn't not have mine
- if (!blocks[row][column].hasMine()
- && blocks[row][column].isFlagged()) {
- // set flag icon
- blocks[row][column].setFlagIcon(false);
- }
- // block is flagged
- if (blocks[row][column].isFlagged()) {
- // disable the block
- blocks[row][column].setClickable(false);
- }
- }
- }
- // trigger mine
- blocks[currentRow][currentColumn].triggerMine();
- // show message
- showDialog("You tried for " + Integer.toString(secondsPassed)
- + " seconds!", 1000, false, false);
- }
- private void setMines(int currentRow, int currentColumn) {
- // set mines excluding the location where user clicked
- Random rand = new Random();
- int mineRow, mineColumn;
- for (int row = 0; row < totalNumberOfMines; row++) {
- mineRow = rand.nextInt(numberOfColumnsInMineField);
- mineColumn = rand.nextInt(numberOfRowsInMineField);
- if ((mineRow + 1 != currentColumn)
- || (mineColumn + 1 != currentRow)) {
- if (blocks[mineColumn + 1][mineRow + 1].hasMine()) {
- row--; // mine is already there, don't repeat for same block
- }
- // plant mine at this location
- blocks[mineColumn + 1][mineRow + 1].plantMine();
- }
- // exclude the user clicked location
- else {
- row--;
- }
- }
- int nearByMineCount;
- for (int row = 0; row < numberOfRowsInMineField + 2; row++) {
- for (int column = 0; column < numberOfColumnsInMineField + 2; column++) {
- // for each block find nearby mine count
- nearByMineCount = 0;
- if ((row != 0) && (row != (numberOfRowsInMineField + 1))
- && (column != 0)
- && (column != (numberOfColumnsInMineField + 1))) {
- // check in all nearby blocks
- for (int previousRow = -1; previousRow < 2; previousRow++) {
- for (int previousColumn = -1; previousColumn < 2; previousColumn++) {
- if (blocks[row + previousRow][column
- + previousColumn].hasMine()) {
- // a mine was found so increment the counter
- nearByMineCount++;
- }
- }
- }
- blocks[row][column]
- .setNumberOfMinesInSurrounding(nearByMineCount);
- }
- // for side rows (0th and last row/column)
- // set count as 9 and mark it as opened
- else {
- blocks[row][column].setNumberOfMinesInSurrounding(9);
- blocks[row][column].OpenBlock();
- }
- }
- }
- }
- private void rippleUncover(int rowClicked, int columnClicked) {
- // don't open flagged or mined rows
- if (blocks[rowClicked][columnClicked].hasMine()
- || blocks[rowClicked][columnClicked].isFlagged()) {
- return;
- }
- // open clicked block
- blocks[rowClicked][columnClicked].OpenBlock();
- // if clicked block have nearby mines then don't open further
- if (blocks[rowClicked][columnClicked].getNumberOfMinesInSorrounding() != 0) {
- return;
- }
- // open next 3 rows and 3 columns recursively
- for (int row = 0; row < 3; row++) {
- for (int column = 0; column < 3; column++) {
- // check all the above checked conditions
- // if met then open subsequent blocks
- if (blocks[rowClicked + row - 1][columnClicked + column - 1]
- .isCovered()
- && (rowClicked + row - 1 > 0)
- && (columnClicked + column - 1 > 0)
- && (rowClicked + row - 1 < numberOfRowsInMineField + 1)
- && (columnClicked + column - 1 < numberOfColumnsInMineField + 1)) {
- rippleUncover(rowClicked + row - 1, columnClicked + column
- - 1);
- }
- }
- }
- return;
- }
- public void startTimer() {
- if (secondsPassed == 0) {
- timer.removeCallbacks(updateTimeElasped);
- // tell timer to run call back after 1 second
- timer.postDelayed(updateTimeElasped, 1000);
- Log.i("tag",String.valueOf((timer.postDelayed(updateTimeElasped, 1000))) );
- }
- }
- public void stopTimer() {
- // disable call backs
- timer.removeCallbacks(updateTimeElasped);
- }
- // timer call back when timer is ticked
- private Runnable updateTimeElasped = new Runnable() {
- public void run() {
- long currentMilliseconds = System.currentTimeMillis();
- ++secondsPassed;
- txtTimer.setText(Integer.toString(secondsPassed));
- // add notification
- timer.postAtTime(this, currentMilliseconds);
- // notify to call back after 1 seconds
- // basically to remain in the timer loop
- timer.postDelayed(updateTimeElasped, 1000);
- }
- };
- private void showDialog(String message, int milliseconds,
- boolean useSmileImage, boolean useCoolImage) {
- // show message
- Toast dialog = Toast.makeText(getApplicationContext(), message,
- Toast.LENGTH_LONG);
- dialog.setGravity(Gravity.CENTER, 0, 0);
- LinearLayout dialogView = (LinearLayout) dialog.getView();
- ImageView coolImage = new ImageView(getApplicationContext());
- if (useSmileImage) {
- coolImage.setImageResource(R.drawable.smile);
- } else if (useCoolImage) {
- coolImage.setImageResource(R.drawable.cool);
- } else {
- coolImage.setImageResource(R.drawable.sad);
- }
- dialogView.addView(coolImage, 0);
- dialog.setDuration(milliseconds);
- dialog.show();
- Log.i("tag", "showDialog()");
- }
- }
源碼下載
轉自:http://www.cnblogs.com/salam/archive/2010/10/03/1841650.html
目前有越來越多的手機具備自動對焦的拍攝功能,這也意味著這些手機可以具備條碼掃描的功能。手機具備條碼掃描的功能,可以優化購物流程,快速存儲電子名片(二維碼)等。 本
本文實例講述了Android編程實現QQ表情的發送和接收。分享給大家供大家參考,具體如下: 在自己做一個聊天應用練習的時候,需要用到表情,於是就想著模仿一下QQ表
可以顯示在的Android任務,通過加載進度條的進展。進度條有兩種形狀。加載欄和加載微調(spinner)。在本章中,我們將討論微調(spinner)。Spinner 用
繪制圓環其實很簡單,有大概以下三種思路. 這裡先說網上提到的一種方法。思路是先繪制內圓,然後繪制圓環(圓環的寬度就是paint設置的paint.setStroke