Click here to Skip to main content
15,884,064 members
Articles / Programming Languages / C#
Article

A Simple Mine Sweeping Game

Rate me:
Please Sign up or sign in to vote.
4.08/5 (10 votes)
22 Sep 2008CPOL 53.4K   2.4K   38   11
A simple mine sweeping game using C#
Image 1

Introduction

This article is a simple example for beginners who are just learning C#. Windows's winmine is an interesting game, so I like to write this game to learn the following things:

  1. How to use observer pattern in your programming
  2. How to use DataGridView and its event
  3. How to use delegate
  4. How to make usercontrol

Using the Code

The main classes and interface are given below.

Interfaces

C#
public interface IClick
{
    //to set mine flag 
    bool RightClick(int x, int y, Presenter pr);
    //whether trigger mine
    bool LeftClick(int x, int y, Presenter pr);

    //double click
    bool BothClick(int x, int y, Presenter pr);
}
public interface ICoordinate
{
    int XCoordinate { get;}
    int YCoordinate { get;}
    void SetCoordinate(int x, int y);
}

public interface IGetSetValue
{
    void Initialization();
    int Lines { get;set;}
    int Columns { get;set;}
    int MineNums { get;set;}
}
public interface IOberverable
{
    void Register(IObserver ober);
    void UnRegister(IObserver ober);
}
public interface IObserver
{
    void Update(EventArgs brgs);
}

Main Class

The SweepingMap class defines form's width, height and number of mines, the main methods of the class are LeftClick which means mouse's left click on DataGridView cells, RightClick which means mouse's right click on DataGridView cells, BothClick means mouse's double click on DataGridView cells.

C#
public class SweepingMap : IClick, IGetSetValue
    {
        #region Private Field
        /// <summary>
        /// to store mines
        /// </summary>
        private readonly ObjectList mines;
        /// <summary>
        /// to store the mines which are found
        /// </summary>
        private readonly ObjectList flags;
        private readonly ObjectList hasAccessed;
        private int lines;
        private int columns;
        private int mineNums;
        private Random ran = new Random();
        #endregion
        #region Public Attributes
        public ObjectList Mines
        {
            get
            {
                return this.mines;
            }
        }
        public ObjectList Flags
        {
            get
            {
                return this.flags;
            }
        }
        public int Lines
        {
            get
            {
                return this.lines;
            }
            set
            {
                this.lines = value;
            }
        }
        public int Columns
        {
            get
            {
                return this.columns;
            }
            set
            {
                this.columns = value;
            }
        }
        public int MineNums
        {
            get
            {
                return this.mineNums;
            }
            set
            {
                this.mineNums = value;
            }
        }
        #endregion
        #region Constructor
        public SweepingMap()
        {
            this.mines = new ObjectList();
            this.flags = new ObjectList();
            hasAccessed = new ObjectList();
        }
        #endregion
        #region Private Methods
        private int CertainCondition(int x, int y, Condition condition)
        {
            int count = 0;
            for (int i = x - 1; i <= x + 1; i++)
            {
                for (int j = y - 1; j <= y + 1; j++)
                {
                    if ((i >= 0 && i < Lines) && (j >= 0 && 
			j < Columns) && !(i == x && j == y))
                    {
                        if (condition(i, j))
                            count++;
                    }
                }
            }        
            return count;
        }
        private bool CheckSuccess()
        {
            int count = 0;
            foreach (GridObject f in this.Flags.ObjectTable.Keys)
            {
                foreach (GridObject m in this.Mines.ObjectTable.Keys)
                {
                    if (this.Flags.ObjectTable[f].Equals(this.Mines.ObjectTable[m]))
                        count++;
                }
            }
            if (count == this.Mines.ObjectTable.Count)
                return true;
            else
                return false;
        }
        #endregion
        #region Public Methods
        public void Initialization()
        {
            this.mines.Clear();
            this.flags.Clear();
            this.hasAccessed.Clear();
            for (int i = 0; i < this.MineNums; i++)
            {
                int x = ran.Next(this.Lines);
                int y = ran.Next(this.Columns);
#if Debug
                System.Diagnostics.Debug.Print("Coordinate:({0},{1}) \n", x, y);
#endif
                if (!this.mines.ContainsKey(x, y))
                    this.mines.Add(x, y);
                else
                    i -= 1;
            }
        }
        //to set mine flag 
        public bool RightClick(int x, int y, Presenter pr)
        {
            if (this.flags.ContainsKey(x, y))
            {
                this.flags.Remove(x, y);
                pr(x, y, true);
            }
            else
            {
                if (!this.hasAccessed.ContainsKey(x, y) && 
				!this.flags.ContainsKey(x, y))
                {
                    this.flags.Add(x, y);
                    pr(x, y, false);
                }
            }
            if (this.Flags.Length == this.Mines.Length)
            {
                if (CheckSuccess())
                {
                    return true;
                }
            }
            return false;
        }
        //whether trigger mine
        public bool LeftClick(int x, int y, Presenter pr)
        {
            if (!this.Flags.ContainsKey(x, y))
            {
                if (this.Mines.ContainsKey(x, y))
                {
                    pr(x, y, "Mine");
                    return false;
                }
                else
                {
                    GridTraversing(x, y, pr);
                    return true;
                }
               
            }
            return true;
        }
        private void GridTraversing(int x, int y, Presenter pr)
        {
            Stack<GridObject> stack = new Stack<GridObject>();
            GridObject tmp = new GridObject(x, y);
            stack.Push(tmp);
            Condition condition = new Condition(this.Mines.ContainsKey);
            while (!(stack.Count == 0))
            {
                tmp = stack.Pop();
                int num = CertainCondition(tmp.XCoordinate, tmp.YCoordinate, condition);
                hasAccessed.Add(tmp.XCoordinate, tmp.YCoordinate);
                if (num == 0)
                {
                    pr(tmp.XCoordinate, tmp.YCoordinate, num);
                    for (int i = tmp.XCoordinate - 1; i <= tmp.XCoordinate + 1; i++)
                    {
                        for (int j = tmp.YCoordinate - 1; j <= tmp.YCoordinate + 1; j++)
                        {
                            if (i >= 0 && i < Lines && j >= 0 && j < Columns 
                                && !hasAccessed.ContainsKey(i, j) 
                                && !this.Flags.ContainsKey(i, j))
                            {
                                pr(i, j, num);
                                hasAccessed.Add(i,j);
                                stack.Push(new GridObject(i, j));
                            }
                        }
                    }
                }
                else
                {
                    pr(tmp.XCoordinate, tmp.YCoordinate, num);
                }
            }
        }
        //double click
        public bool BothClick(int x, int y, Presenter pr)
        {
            Condition condition = new Condition(this.Mines.ContainsKey);
            int num = CertainCondition(x, y, condition);
            condition = new Condition(this.flags.ContainsKey);
            int count = CertainCondition(x, y, condition);
            if (count == 0)
                return true;
            if (num == count)
            {
                for (int i = x - 1; i <= x + 1; i++)
                {
                    for (int j = y - 1; j <= y + 1; j++)
                    {
                        if (i >= 0 && i < Lines && j >= 0 && j < Columns 
                           && !(i == x && j == y))
                        {
                            if (!(this.flags.ContainsKey(i, j))) 
                            {
                                if (!LeftClick(i, j, pr))
                                    return false;
                            }
                        }
                    }
                }
            }
            return true;
        }
        public void DisplayAllMines(int x, int y, Presenter pr)
        {
            int i, j;
            foreach (GridObject cur in mines.ObjectTable.Keys)
            {
                i = mines.ObjectTable[cur].XCoordinate;
                j = mines.ObjectTable[cur].YCoordinate;
                if (i != x && j != y)
                    pr(i, j, mines.ObjectTable[cur]);
            }
        }
        #endregion
    }

History

  • 22nd September, 2008: Initial post

License

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


Written By
Software Developer acca
China China
I love to communicate with eachother.

Comments and Discussions

 
GeneralMy vote of 1 Pin
geniaz128-Jul-09 1:36
geniaz128-Jul-09 1:36 
GeneralDownload Invalid Pin
Bill Warner24-Sep-08 6:46
Bill Warner24-Sep-08 6:46 
GeneralRe: Download Invalid Pin
vivounicorn24-Sep-08 14:48
vivounicorn24-Sep-08 14:48 
Generalsuggestions Pin
RednaxelaFX23-Sep-08 6:40
RednaxelaFX23-Sep-08 6:40 
GeneralRe: suggestions Pin
vivounicorn23-Sep-08 15:20
vivounicorn23-Sep-08 15:20 
QuestionLIAR? -- Nope! Just mis-labled downloads [modified] Pin
Brad Bruce23-Sep-08 5:53
Brad Bruce23-Sep-08 5:53 
AnswerRe: LIAR? Pin
f r i s c h23-Sep-08 5:58
f r i s c h23-Sep-08 5:58 
GeneralRe: LIAR? Pin
RednaxelaFX23-Sep-08 6:42
RednaxelaFX23-Sep-08 6:42 
GeneralRe: LIAR? Pin
Brad Bruce23-Sep-08 7:52
Brad Bruce23-Sep-08 7:52 
GeneralRe: LIAR? Pin
Humble Programmer23-Sep-08 8:03
Humble Programmer23-Sep-08 8:03 
The first couple of bytes are "Rar!", so I'm guessing it's actually a RAR archive. I got the same "Compressed folder corrupt" message, but was able to open and extract it with 7-Zip.

Cheers!
Humble Programmer
,,,^..^,,,

GeneralRe: LIAR? Pin
Brad Bruce23-Sep-08 8:53
Brad Bruce23-Sep-08 8:53 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.