走迷宮C#版(一)

//迷宮類相關

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Collections;

namespace MazeDemo
{
 /// <summary>
 /// 迷宮類
 /// </summary>
 public class CMaze
 {
  bool[,] mg;  //地圖格子
  Stack stack; //堆棧
  Point in_p;  //入口點
  Point out_p; //出口點
  Point start_p; //繪製迷時候的起始點
  Size boxsize; //每個格子的大小
  int step_count; //共走多少步

  public CMaze()
  {
   stack=new Stack();
   this.start_p=new Point(0,0);
   this.boxsize=new Size(50,50);
   step_count=0;
  }

  public CMaze(bool[,] _mg):this()
  {
   this.mg=_mg;
  }

  public CMaze(bool[,] _mg,Point _in,Point _out):this()
  {
   this.mg=_mg;
   this.in_p=_in;
   this.out_p=_out;
   Stack way=this.Test(this.in_p,_in);
   stack.Push(new CCoor(this.in_p,way));
   this.step_count++;
  }


  /// <summary>
  /// 繪製迷宮時窗口的起始座標
  /// </summary>
  public Point StartPoint
  {
   set{this.start_p=value;}
   get{return this.start_p;}
  }

  /// <summary>
  /// 當前迷宮共走多少步
  /// </summary>
  public int StepCount
  {
   get{return this.step_count;}
  }

  /// <summary>
  /// 迷宮格子大小
  /// </summary>
  public Size BoxSize
  {
   set{this.boxsize=value;}
   get{return this.boxsize;}
  }

  /// <summary>
  /// 堆棧數據個數
  /// </summary>
  public int StackCount
  {
   get{return this.stack.Count;}
  }

  /// <summary>
  /// 繪製迷宮
  /// </summary>
  /// <param name="g"></param>
  public void DrawBox(Graphics g)
  {
   for(int i=0;i<mg.GetLength(0);i++)
   {
    for(int j=0;j<mg.GetLength(1);j++)
    {
     Point pp=new Point((j*BoxSize.Width)+StartPoint.X,(i*BoxSize.Height)+StartPoint.Y); //位置
     SolidBrush brush;
     Rectangle rect=new Rectangle(pp,BoxSize);

     if(mg[i,j])
      brush=new SolidBrush(Color.Green);
     else
      brush=new SolidBrush(Color.Red);
     g.FillRectangle(brush,rect);
    }
   }
  }

  /// <summary>
  /// 繪製所走線路
  /// </summary>
  /// <param name="g"></param>
  public void DrawPath(Graphics g)
  {
   IEnumerator myEnumerator = stack.GetEnumerator();
   while ( myEnumerator.MoveNext() )
   {
    CCoor c=new CCoor();
    c=(CCoor)myEnumerator.Current;
    Point pp=new Point((c.CurrentPoint.Y*BoxSize.Width)+StartPoint.X,(c.CurrentPoint.X*BoxSize.Height)+StartPoint.Y);
    SolidBrush brush=new SolidBrush(Color.Blue);
    Rectangle rect=new Rectangle(pp,BoxSize);
    g.FillRectangle(brush,rect);
   }
  }

  /// <summary>
  /// 繪製當前位置的可行路徑
  /// </summary>
  /// <param name="g"></param>
  public void DrawNextPath(Graphics g)
  {
   CCoor c=(CCoor)this.stack.Peek();
   Stack s=c.WayPath;
   IEnumerator myEnumerator=s.GetEnumerator();
   while(myEnumerator.MoveNext())
   {
    Point p=(Point)myEnumerator.Current;
    Point pp=new Point((p.Y*BoxSize.Width)+StartPoint.X,(p.X*BoxSize.Height)+StartPoint.Y);
    SolidBrush brush=new SolidBrush(Color.Yellow);
    Rectangle rect=new Rectangle(pp,BoxSize);
    g.FillRectangle(brush,rect);
   }
  }

  /// <summary>
  /// 判斷迷宮是否走完
  /// </summary>
  /// <returns></returns>
  public bool IsEnd()
  {
   CCoor coor=(CCoor)this.stack.Peek(); //當前位置信息
   if( coor.CurrentPoint.X==this.out_p.X && coor.CurrentPoint.Y==this.out_p.Y )
    return true;
   else
    return false;
  }

  /// <summary>
  /// 走一迷宮中的一個格子
  /// </summary>
  /// <returns>數字狀態</returns>
  public int Step()
  {
   CCoor coor=(CCoor)this.stack.Peek(); //當前位置信息
   //是否到達出口
   if(!(coor.CurrentPoint.X==this.out_p.X&&coor.CurrentPoint.Y==this.out_p.Y))
   {
    Stack ss=coor.WayPath;
    if(ss.Count==0)
    {
     this.stack.Pop();
     return 0;
    }
    Point p=(Point)ss.Pop(); //當前位置可繼續移動的下一個位置
    if(p.X==this.out_p.X&&p.Y==this.out_p.Y)
    {
     this.stack.Push(new CCoor(p,new Stack()));
     return 0;
    }
    Stack st=this.Test(p,coor.CurrentPoint); //得到下一個可移動位置的所有可移動位置
    if(st.Count==0)
    {
     return 0;
    }
    CCoor newcoor=new CCoor(p,st); //建立新的位置信息
    this.stack.Push(newcoor); //壓入堆棧
    this.step_count++; //所走步驟加1
    return 0;
   }
   else
    return 1;
  }

  /// <summary>
  /// 走迷宮
  /// </summary>
  public void Run()
  {
   while(this.Step()!=1);
  }

  /// <summary>
  /// 回覆到迷宮起點
  /// </summary>
  public void Reset()
  {
   this.stack.Clear();
   Stack way=this.Test(this.in_p,this.in_p);
   stack.Push(new CCoor(this.in_p,way));
   this.step_count=1;
  }

  /// <summary>
  /// 探測可行路線
  /// 探測順序 右->前->左->後
  ///       左
  ///       |
  ///   後--+-->前
  ///       |
  ///       右
  /// </summary>
  /// <param name="p">從當前點查詢四周是否有可行路線</param>
  /// <param name="perv_p">先前的路線</param>
  /// <returns>可行路線堆棧</returns>
  public Stack Test(Point p,Point perv_p)
  {
   Stack stack_way=new Stack(); //該點可行位置堆棧
   int x,y;

   //後
   x=p.X;
   y=p.Y-1;
   this.Signpost(x,y,stack_way,perv_p);

   //左
   x=p.X-1;
   y=p.Y;
   this.Signpost(x,y,stack_way,perv_p);

   //前
   x=p.X;
   y=p.Y+1;
   this.Signpost(x,y,stack_way,perv_p);

   //右
   x=p.X+1;
   y=p.Y;
   this.Signpost(x,y,stack_way,perv_p);

   return stack_way;
  }

  /// <summary>
  /// 判斷該方向是否可行,可行則將信息壓入堆棧,只在Test()函數中調用
  /// </summary>
  /// <param name="x">x座標</param>
  /// <param name="y">y座標</param>
  /// <param name="s">堆棧</param>
  /// <param name="perv_p">來時候的方向</param>
  private void Signpost(int x,int y,Stack s,Point perv_p)
  {
   if(  (x>=0 && x<this.mg.GetLength(0)) && (y>=0 && y<this.mg.GetLength(1)) )
   {
    if(this.mg[x,y]&&!(x==perv_p.X&&y==perv_p.Y))
     s.Push(new Point(x,y));
   }
  }

  /// <summary>
  /// 迷宮簡圖
  /// </summary>
  /// <returns>字符地圖</returns>
  public override string ToString()
  {
   string str="";
   for(int i=0;i<mg.GetLength(0);i++)
   {
    for(int j=0;j<mg.GetLength(1);j++)
    {
     if(this.mg[i,j])
      str+="□";
     else
      str+="■";
    }
    str+="/n";
   }
   return str;
  }
 }

 /// <summary>
 /// 當前座標信息,和可走方向座標
 /// </summary>
 public class CCoor
 {
  private Point curr_p; //當前座標
  private Stack way;  //可走方向座標

  public CCoor()
  {
   //...
  }

  public CCoor(Point p,Stack w)
  {
   curr_p=p;
   way=w;
  }

  public Point CurrentPoint
  {
   get{return this.curr_p;}
   set{this.curr_p=value;}
  }

  public Stack WayPath
  {
   set{this.way=value;}
   get{return this.way;}
  }
 }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章