Click here to Skip to main content
Click here to Skip to main content

A Simple Mine Sweeping Game

, 22 Sep 2008 CPOL
Rate this:
Please Sign up or sign in to vote.
A simple mine sweeping game using C#

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

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.

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)

Share

About the Author

vivounicorn
Software Developer acca
China China
I love to communicate with eachother.

Comments and Discussions

 
GeneralMy vote of 1 Pinmembergeniaz128-Jul-09 2:36 
GeneralDownload Invalid PinmemberBill Warner24-Sep-08 7:46 
GeneralRe: Download Invalid Pinmembervivounicorn24-Sep-08 15:48 
Generalsuggestions PinmemberRednaxelaFX23-Sep-08 7:40 
GeneralRe: suggestions Pinmembervivounicorn23-Sep-08 16:20 
QuestionLIAR? -- Nope! Just mis-labled downloads [modified] PinmemberBrad Bruce23-Sep-08 6:53 
AnswerRe: LIAR? Pinmemberf r i s c h23-Sep-08 6:58 
GeneralRe: LIAR? PinmemberRednaxelaFX23-Sep-08 7:42 
GeneralRe: LIAR? PinmemberBrad Bruce23-Sep-08 8:52 
GeneralRe: LIAR? PinmemberHumble Programmer23-Sep-08 9:03 
GeneralRe: LIAR? PinmemberBrad Bruce23-Sep-08 9:53 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.1411028.1 | Last Updated 23 Sep 2008
Article Copyright 2008 by vivounicorn
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid