65.9K
CodeProject 正在变化。 阅读更多。
Home

一个简单的扫雷游戏

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.08/5 (9投票s)

2008年9月23日

CPOL
viewsIcon

54525

downloadIcon

2456

一个用 C# 编写的简单扫雷游戏。

引言

这篇文章是一个简单的示例,供刚开始学习 C# 的初学者使用。Windows 的扫雷是一个有趣的游戏,所以我喜欢编写这个游戏来学习以下内容:

  1. 如何在编程中使用观察者模式
  2. 如何使用 DataGridView 及其事件
  3. 如何使用委托
  4. 如何制作用户控件

Using the Code

主要的类和接口如下所示。

接口

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);
}

主类

SweepingMap 类定义了窗体的宽度、高度和地雷数量,该类的主要方法是 LeftClick,表示鼠标左键单击 DataGridView 单元格,RightClick 表示鼠标右键单击 DataGridView 单元格,BothClick 表示鼠标双击 DataGridView 单元格。

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
    }

历史

  • 2008年9月22日:初始发布
© . All rights reserved.