最近由于项目需要学习了一下Android ,感觉汗不错。做了一个Android版的扫雷游戏。
游戏简介
在此游戏中,我们使用一个块的网格,其中有一些随机的地雷
下面是效果图
一、应用程序布局
使用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()");
}
}