android扫雷需求分析,扫雷4Android(附源码)

最近由于项目需要学习了一下Android ,感觉汗不错。做了一个Android版的扫雷游戏。

游戏简介

在此游戏中,我们使用一个块的网格,其中有一些随机的地雷

下面是效果图

a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

一、应用程序布局

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

encoding="utf-8"?>

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:background="@drawable/back">

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" />

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"

/>

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"

/>

android:layout_column="0"

android:layout_height="50px"

android:layout_width="fill_parent"

android:layout_span="3"

android:padding="10dip"

/>

android:id="@+id/minefield"

android:layout_width="260px"

android:layout_height="260px"

android:gravity="bottom"

android:stretchColumns="*"

android:layout_span="3"

android:padding="5dip">

二、地雷块

Block.java

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

tickedprivate 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

notblocks[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 stepif

(blocks[currentRow + previousRow][currentColumn +

previousColumn].hasMine())

{

// oops game

over finishGame(currentRow +

previousRow, currentColumn + previousColumn);

}

// did we win the

gameif

(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

@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()");

}

}

安卓 扫雷源码 添加重新开始按钮支持 Android studio ====================================== Risky Project Location: ----------------------- The tools *should* handle project locations in any directory. However, due to bugs, placing projects in directories containing spaces in the path, or characters like ", ' and &, have had issues. We're working to eliminate these bugs, but to save yourself headaches you may want to move your project to a location where this is not a problem. D:\Program Files\android_s_workplace\terrysaolei - Ignored Files: -------------- The following files were *not* copied into the new Gradle project; you should evaluate whether these are still needed in your project and if so manually move them: * ic_launcher-web.png * proguard-project.txt Moved Files: ------------ Android Gradle projects use a different directory structure than ADT Eclipse projects. Here's how the projects were restructured: * AndroidManifest.xml => app\src\main\AndroidManifest.xml * assets\ => app\src\main\assets * res\ => app\src\main\res\ * src\ => app\src\main\java\ Next Steps: ----------- You can now build the project. The Gradle project needs network connectivity to download dependencies. Bugs: ----- If for some reason your project does not build, and you determine that it is due to a bug or limitation of the Eclipse to Gradle importer, please file a bug at http://b.android.com with category Component-Tools. (This import summary is for your information only, and can be deleted after import once you are satisfied with the results.)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值