`

扫雷游戏

阅读更多
MineSweeper是一个不错的Android开源扫雷游戏,对于初学Android开发网的网友可能有很大的帮助,对于Java游戏开发也有一定的参考意义。该游戏主要有以下技术值得学习:

  1. 个性化字体,计分器使用的是LED字体,可以帮助我们如何导入外部字体在Android平台中显示。

  2. 带图片的Toast,下面的You won in 36 seconds这个Toast使用了自定义的布局,可以显示图片和文字。

  3. 自定义Button控件,可以看到标记是否为雷,显示附近地雷数量的按钮控件,初学者可以很容易的学习到Android开发中常用的自定义控件技术。
 
  4.  因为游戏实时性不高,这里没有用到SurfaceView,下次Android开发网给大家提供一个将对高级些的例子。

关键代码如下:
main.xml
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:stretchColumns="0,2"
    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="40sp"
			android:text="000" />
			
		<ImageButton android:id="@+id/Smiley"
			android:layout_column="1"
			android:background="@drawable/smiley_button_states"
			android:scaleType="center"
			android:padding="5dip" 
			android:layout_width="48px"
			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="40sp"
			android:text="000" />
    </TableRow>
    
	<TableRow>
		<TextView
			android:layout_column="0"
			android:layout_width="fill_parent"
			android:layout_height="50px"
			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>

smiley_button_states.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_focused="true" 
    	  android:state_pressed="false" 
    	  android:layout_width="48px"
    	  android:layout_height="48px"
    	  android:drawable="@drawable/smile" />
    	  
    <item android:state_focused="true" 
    	  android:state_pressed="true"
    	  android:layout_width="48px"
    	  android:layout_height="48px"
    	  android:drawable="@drawable/surprise" />
    	  
    <item android:state_focused="false" 
    	  android:state_pressed="true"
    	  android:layout_width="48px"
    	  android:layout_height="48px"
	      android:drawable="@drawable/surprise" />
	      
    <item android:layout_width="48px"
     	  android:layout_height="48px"
    	  android:drawable="@drawable/smile" />
</selector>

Block.java
package com.VertexVerveInc.Games;

import android.content.Context;
import android.graphics.Color;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.widget.Button;

public class Block extends Button
{
	private boolean isCovered; // is block covered yet
	private boolean isMined; // does the block has a mine underneath
	private boolean isFlagged; // is block flagged as a potential mine
	private boolean isQuestionMarked; // is block question marked
	private boolean isClickable; // can block accept click events
	private int numberOfMinesInSurrounding; // number of mines in nearby blocks

	public Block(Context context)
	{
		super(context);
	}

	public Block(Context context, AttributeSet attrs)
	{
		super(context, attrs);
	}

	public Block(Context context, AttributeSet attrs, int defStyle)
	{
		super(context, attrs, defStyle);
	}

	// set default properties for the block
	public void setDefaults()
	{
		isCovered = true;
		isMined = false;
		isFlagged = false;
		isQuestionMarked = false;
		isClickable = true;
		numberOfMinesInSurrounding = 0;

		this.setBackgroundResource(R.drawable.square_blue);
		setBoldFont();
	}

	// mark the block as disabled/opened
	// update the number of nearby mines
	public void setNumberOfSurroundingMines(int number)
	{
		this.setBackgroundResource(R.drawable.square_grey);
		
		updateNumber(number);
	}

	// set mine icon for block
	// set block as disabled/opened if false is passed
	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);
		}
	}

	// set mine as flagged
	// set block as disabled/opened if false is passed
	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);
		}
	}

	// set mine as question mark
	// set block as disabled/opened if false is passed
	public void setQuestionMarkIcon(boolean enabled)
	{
		this.setText("?");
		
		if (!enabled)
		{
			this.setBackgroundResource(R.drawable.square_grey);
			this.setTextColor(Color.RED);
		}
		else
		{
			this.setTextColor(Color.BLACK);
		}
	}

	// set block as disabled/opened if false is passed
	// else enable/close it
	public void setBlockAsDisabled(boolean enabled)
	{
		if (!enabled)
		{
			this.setBackgroundResource(R.drawable.square_grey);
		}
		else
		{
			this.setBackgroundResource(R.drawable.square_blue);
		}
	}

	// clear all icons/text
	public void clearAllIcons()
	{
		this.setText("");
	}

	// set font as bold
	private void setBoldFont()
	{
		this.setTypeface(null, Typeface.BOLD);
	}

	// uncover this block
	public void OpenBlock()
	{
		// cannot uncover a mine which is not covered
		if (!isCovered)
			return;

		setBlockAsDisabled(false);
		isCovered = false;

		// check if it has mine
		if (hasMine())
		{
			setMineIcon(false);
		}
		// update with the nearby mine count
		else
		{
			setNumberOfSurroundingMines(numberOfMinesInSurrounding);
		}
	}

	// set text as nearby mine count
	public void updateNumber(int text)
	{
		if (text != 0)
		{
			this.setText(Integer.toString(text));

			// select different color for each number
			// we have already skipped 0 mine count
			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;
			}
		}
	}

	// set block as a mine underneath
	public void plantMine()
	{
		isMined = true;
	}

	// mine was opened
	// change the block icon and color
	public void triggerMine()
	{
		setMineIcon(true);
		this.setTextColor(Color.RED);
	}

	// is block still covered
	public boolean isCovered()
	{
		return isCovered;
	}

	// does the block have any mine underneath
	public boolean hasMine()
	{
		return isMined;
	}

	// set number of nearby mines
	public void setNumberOfMinesInSurrounding(int number)
	{
		numberOfMinesInSurrounding = number;
	}

	// get number of nearby mines
	public int getNumberOfMinesInSorrounding()
	{
		return numberOfMinesInSurrounding;
	}

	// is block marked as flagged
	public boolean isFlagged()
	{
		return isFlagged;
	}

	// mark block as flagged
	public void setFlagged(boolean flagged)
	{
		isFlagged = flagged;
	}

	// is block marked as a question mark
	public boolean isQuestionMarked()
	{
		return isQuestionMarked;
	}

	// set question mark for the block
	public void setQuestionMarked(boolean questionMarked)
	{
		isQuestionMarked = questionMarked;
	}

	// can block receive click event
	public boolean isClickable()
	{
		return isClickable;
	}

	// disable block for receive click events
	public void setClickable(boolean clickable)
	{
		isClickable = clickable;
	}
}

MinesweeperGame.java
package com.VertexVerveInc.Games;

import java.util.Random;

import android.app.Activity;
import android.graphics.Typeface;
import android.os.Bundle;
import android.os.Handler;
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.TableRow.LayoutParams;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import android.widget.Toast;

public class MinesweeperGame extends Activity
{
	private TextView txtMineCount;
	private TextView txtTimer;
	private ImageButton btnSmile;

	private TableLayout mineField; // table layout to add mines to

	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.main);
		
		txtMineCount = (TextView) findViewById(R.id.MineCount);
		txtTimer = (TextView) findViewById(R.id.Timer);
		
		// set font style for timer and mine count to LCD style
		Typeface lcdFont = Typeface.createFromAsset(getAssets(),
				"fonts/lcd2mono.ttf");
		txtMineCount.setTypeface(lcdFont);
		txtTimer.setTypeface(lcdFont);
		
		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()
	{
		// plant mines and do rest of the calculations
		createMineField();
		// display all blocks in UI
		showMineField();
		
		minesToFind = totalNumberOfMines;
		isGameOver = false;
		secondsPassed = 0;
	}

	private void showMineField()
	{
		// remember we will not show 0th and last Row and Columns
		// they are used for calculation purposes only
		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 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 < numberOfRowsInMineField + 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;

				// add Click Listener
				// this is treated as Left Mouse click
				blocks[row][column].setOnClickListener(new OnClickListener()
				{
					@Override
					public void onClick(View view)
					{
						// 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 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;

		// count number of mines in surrounding blocks 
		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);
		}
	}

	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;

			if (secondsPassed < 10)
			{
				txtTimer.setText("00" + Integer.toString(secondsPassed));
			}
			else if (secondsPassed < 100)
			{
				txtTimer.setText("0" + Integer.toString(secondsPassed));
			}
			else
			{
				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();
	}
}
  • 大小: 106 KB
分享到:
评论

相关推荐

    Java扫雷游戏完整项目代码

    【Java扫雷游戏完整项目代码】是一个基于Java编程语言实现的经典扫雷游戏的代码实现。在计算机科学领域,扫雷游戏通常被用作一个教学工具,帮助初学者理解逻辑推理、算法设计以及基本的图形用户界面(GUI)编程。在...

    java实现扫雷游戏.zip

    java实现扫雷游戏java实现扫雷游戏java实现扫雷游戏 java实现扫雷游戏java实现扫雷游戏java实现扫雷游戏 java实现扫雷游戏java实现扫雷游戏java实现扫雷游戏 java实现扫雷游戏java实现扫雷游戏java实现扫雷游戏 java...

    Qt实现扫雷游戏(毕设/课设/项目开发皆适用)

    Qt扫雷游戏是一款基于Qt框架开发的经典游戏,旨在为毕设、课设或其他项目开发提供一个有趣而具有挑战性的实践案例。这款游戏不仅实现了扫雷的核心玩法,而且在界面设计和用户体验方面进行了精心雕琢。 主要特点: ...

    AS3扫雷游戏

    AS3扫雷游戏是一款基于ActionScript 3.0(AS3)编程语言开发的经典小游戏,旨在帮助初学者理解和掌握AS3的基本语法、事件处理、显示对象以及游戏逻辑。以下是关于AS3扫雷游戏的一些关键知识点: 1. **ActionScript ...

    C#扫雷游戏源代码 C#扫雷游戏源代码 C#扫雷游戏源代码

    扫雷游戏是一款广为人知的益智游戏,它考验玩家的逻辑推理能力和观察力。通过分析提供的C#源代码,我们可以学习到游戏的核心算法、用户界面设计以及事件处理等方面的知识。 首先,扫雷游戏的实现离不开数据结构的...

    python扫雷游戏设计(课程设计版)

    【Python扫雷游戏设计】是计算机科学与工程学院的一次课程设计任务,旨在培养学生面向对象程序设计的能力,提高代码质量和效率。在这个项目中,学生需要使用Python语言来实现经典的游戏——扫雷。通过这个设计,学生...

    扫雷游戏源程序

    【扫雷游戏源程序】是一种基于C++编程语言开发的小型桌面游戏,旨在帮助程序员提升C++语言的应用技能,特别是对于Visual C++(VC)环境的掌握。扫雷游戏是微软Windows操作系统内置的经典游戏之一,它通过逻辑推理和...

    扫雷游戏源代码

    【扫雷游戏源代码】是基于C#编程语言在Visual Studio(VS)环境中开发的一款经典数字游戏。扫雷游戏的设计和实现涉及多个编程和技术知识点,包括窗口应用开发、事件处理、数组逻辑、随机数生成以及游戏规则的算法...

    cocos creator 扫雷游戏资源工程

    【Cocos Creator 扫雷游戏资源工程】 Cocos Creator 是一款强大的2D游戏开发引擎,它提供了便捷的可视化编辑工具和高效的游戏开发框架,使得开发者能够轻松创建各种类型的游戏,包括经典的扫雷游戏。扫雷游戏,作为...

    java编写的扫雷游戏

    用java编写的扫雷游戏,有兴趣的可以研究研究

    html实现扫雷游戏

    通过html+css+jquery实现经典扫雷游戏,可以直接在浏览器上运行

    Python 扫雷游戏 完整源代码+图片素材

    Python扫雷游戏是一款经典的逻辑推理游戏,通过编程实现可以让我们深入了解Python编程语言的特性以及游戏逻辑的设计。在这款基于Python3.7版本编写的扫雷游戏中,开发者充分展示了Python的面向对象编程思想、条件...

    Android扫雷游戏Mine源码

    【Android扫雷游戏Mine源码】是一个专门为Android平台设计的扫雷游戏的源代码实现,旨在帮助开发者了解和学习Android游戏开发。这个项目不仅提供了完整的扫雷游戏逻辑,还包含了丰富的注释,使得初学者能够更容易地...

    扫雷游戏Java源代码

    扫雷游戏Java源代码扫雷游戏Java源代码扫雷游戏Java源代码扫雷游戏Java源代码扫雷游戏Java源代码扫雷游戏Java源代码扫雷游戏Java源代码扫雷游戏Java源代码扫雷游戏Java源代码扫雷游戏Java源代码扫雷游戏Java源代码...

    QT扫雷游戏源码

    QT扫雷游戏源码是一个基于QT框架,使用C++编程语言实现的经典扫雷游戏项目。对于初学者来说,这是一个极好的学习资源,可以帮助他们深入理解QT框架和C++编程语言在实际项目中的应用。 首先,QT是一个跨平台的C++...

    C++MFC扫雷游戏

    【C++ MFC扫雷游戏】是一个典型的C++面向对象编程项目,主要应用于计算机专业的课程设计,通过实现扫雷游戏来巩固和应用MFC(Microsoft Foundation Classes)框架的知识。MFC是微软提供的一套用于构建Windows应用...

    扫雷游戏-Swing

    【扫雷游戏-Swing】是一款基于Java Swing图形用户界面(GUI)开发的经典益智游戏,旨在帮助初学者提升编程逻辑,巩固数组运用和深化位运算理解。Swing是Java提供的一个用于创建桌面应用的库,它允许开发者构建美观且...

    java课程设计作业-基于java实现的扫雷游戏(源码+设计说明文档+可执行文件),直接点击“扫雷.exe”即可运行

    java课程设计作业——基于java实现的扫雷游戏(源码+设计说明文档+可执行文件),直接点击“扫雷.exe”即可运行 --利用swing做出的扫雷桌面游戏,运行时直接双击可执行文件夹下的“扫雷.exe”即可 java课程设计...

    基于QT的扫雷游戏

    【扫雷游戏与QT框架】 扫雷游戏,作为一款经典的逻辑推理游戏,旨在锻炼玩家的空间想象和逻辑思维能力。在这款基于QT开发的扫雷游戏中,我们能够看到开发者充分利用了QT框架的优势,构建了一个功能丰富的游戏环境。...

    基于Java的扫雷游戏

    【Java扫雷游戏】是一款基于Java编程语言开发的桌面版小游戏,它继承了经典扫雷游戏的玩法,同时也融入了开发者独特的设计元素。在大学期间,开发者利用课余时间研究并实现了这款游戏,旨在锻炼自己的编程技能,同时...

Global site tag (gtag.js) - Google Analytics