Click here to Skip to main content
15,895,084 members
Articles / Mobile Apps

Minesweeper and MinsweeperFlags (a multiplayer version) in one for PocketPC

Rate me:
Please Sign up or sign in to vote.
4.00/5 (14 votes)
30 May 2004CPOL4 min read 63.9K   596   16  
Pocket PC .NET Compact Framework version of Minesweeper and MinsweeperFlags (multiplayer) game in one
using System;

namespace gma.Mobile.Mines
{

	public enum Player
	{
		None	= 0,
		Red		= 1,
		Blue	= 2
	}

	public delegate void OnCellChangedEvent(byte x, byte y);
	public delegate void OnGameOverEvent(Player TheWinner);
	public delegate void OnFlagSetEvent(byte x, byte y);
	

	public interface IGame
	{
		event OnCellChangedEvent OnCellChanged;
		event OnGameOverEvent OnGameOver;
		void Restart();
		void ClickCell(byte x, byte y);
		void SetFlag(byte x, byte y);
		Field GetField();
		bool IsGameOver();
		byte GetLastX();
		byte GetLastY(); 
		bool IsMultiplayer();
	}

	public abstract class GameBase:IGame
	{
		#region Events
		
		/// <summary>
		/// This event occures when a cell was chenged.
		/// </summary>
		public event OnCellChangedEvent OnCellChanged;

		/// <summary>
		/// This event occures when the geme is over. Loose or win.
		/// </summary>
		public event OnGameOverEvent OnGameOver;

		//public event OnFlagSetEvent OnFlagSet;

		#endregion

		/// <summary>
		/// An underlaying field.
		/// </summary>
		protected Field _field;
		public Field GetField()
		{
			return _field;
		}

		public GameBase(byte aWidth, byte aHeight, byte aBombCount)
		{
			_field=new Field(aWidth, aHeight, aBombCount);
			Restart();
		}

		public GameBase(ref Field aField)
		{
			_field=aField;
			Restart();
		}

		public bool IsMultiplayer()
		{
			return (this is MultiPlayerGame);
		}


		private Player _currentPlayer=Player.Red;
		public Player CurrentPlayer
		{
			get {return _currentPlayer;}
			set {_currentPlayer=value;}
		}

		public CellState GetFlagColorOfCurrentPlayer()
		{
			if (CurrentPlayer==Player.Blue) return CellState.FlagBlue;
			else return CellState.FlagRed;
		}

		private int _closedCount=0;
		public int ClosedCount
		{
			get {return _closedCount;}
			set {_closedCount=value;}
		}

		private int _flagCountRed=0;
		public int FlagCountRed
		{
			get {return _flagCountRed;}
		}
		private int _flagCountBlue=0;
		public int FlagCountBlue
		{
			get {return _flagCountBlue;}
		}


		public int FlagCount
		{
			get {return _flagCountBlue+_flagCountRed;}
		}


		public void Restart()
		{
			_currentPlayer=Player.Red;
			_field.Init();
			_flagCountBlue=0;
			_flagCountRed=0;
			ClosedCount = _field.Width  * _field.Height;
		}

		protected void GameOver(Player TheWinner)
		{
			_currentPlayer=Player.None;
			if (OnGameOver!=null) OnGameOver(TheWinner);
		}

		public bool IsGameOver()
		{
			return (_currentPlayer==Player.None);
		}

		private byte _lastX=0;
		public byte GetLastX() {return _lastX;}
		
		private byte _lastY=0;
		public byte GetLastY() {return _lastY;}


		public virtual void ClickCell(byte x, byte y)
		{
			_lastX=x;
			_lastY=y; 
			ClickCellIntern(x,y);
		}

		/// <summary>
		/// Opens a cell and area around it when there is no mine under it.
		/// </summary>
		/// <param name="x">Horizontale coordinate.</param>
		/// <param name="y">Vertical coordinate.</param>
		/// <param name="Probably">true - when the cell must be only marked and not opened.</param>
		private void ClickCellIntern(byte x, byte y)
		{
			if (CurrentPlayer==Player.None) return;
			
			// when the cell was already opened then do nothing
			if (_field.CellStates[x,y]==CellState.Open) return;

			CellState BeforeState = _field.CellStates[x,y];

			//open it
			_field.CellStates[x,y]=CellState.Open;

			// inform others that this cell was modified.
			CellChanged(x,y, BeforeState, _field.CellStates[x,y]);

			// the cell is empty open it recursively
			if (_field.Bombs[x,y]==0) ClickOnEmptyCell(x,y);
		}

		public void CellChanged(byte x, byte y, CellState BeforeState, CellState AfterState)
		{
			if (BeforeState==AfterState) return;
			if (AfterState==CellState.Open) ClosedCount--;

			if (AfterState==CellState.FlagRed) _flagCountRed++;
			if (BeforeState==CellState.FlagRed && AfterState==CellState.Closed) _flagCountRed--;

			if (AfterState==CellState.FlagBlue) _flagCountBlue++;
			if (BeforeState==CellState.FlagBlue && AfterState==CellState.Closed) _flagCountBlue--;

			if (OnCellChanged!=null) OnCellChanged(x,y);
		}

		public abstract void SetFlag(byte x, byte y);

		private void ClickOnEmptyCell(byte x, byte y)
		{
			// when the counter is 0 im means the cell is empty
			if (_field.Bombs[x,y]==0)
				// all neighbour cells must be also recursively opened
				for(int i=-1; i<=1; i++)
					for(int j=-1; j<=1; j++)
						if (!((x+i<1) || (y+j<1) || (x+i>_field.Width) || (y+j>_field.Height) ))
							// recursion
							ClickCellIntern((byte)(x+i),(byte)(y+j));
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Germany Germany
Tweeter: @gmamaladze
Google+: gmamaladze
Blog: gmamaladze.wordpress.com

Comments and Discussions