日本好好热aⅴ|国产99视频精品免费观看|日本成人aV在线|久热香蕉国产在线

  • <cite id="ikgdy"><table id="ikgdy"></table></cite>
    1. 西西軟件園多重安全檢測(cè)下載網(wǎng)站、值得信賴(lài)的軟件下載站!
      軟件
      軟件
      文章
      搜索

      首頁(yè)編程開(kāi)發(fā)其它知識(shí) → 菜鳥(niǎo)用WPF 實(shí)現(xiàn)俄羅斯方塊游戲

      菜鳥(niǎo)用WPF 實(shí)現(xiàn)俄羅斯方塊游戲

      相關(guān)軟件相關(guān)文章發(fā)表評(píng)論 來(lái)源:本站整理時(shí)間:2010/9/20 15:32:40字體大。A-A+

      作者:佚名點(diǎn)擊:291次評(píng)論:115次標(biāo)簽: WPF

      Actipro WPF Studiov11.1.0541 注冊(cè)版
      • 類(lèi)型:編程控件大。58.9M語(yǔ)言:英文 評(píng)分:6.6
      • 標(biāo)簽:
      立即下載

      主要思想:

      一、提供一個(gè)容器類(lèi)(Container),用來(lái)作為方塊活動(dòng)的網(wǎng)格狀區(qū)域。由于WPF自帶Grid控件支持網(wǎng)格,因此就直接利用了。

      1.Container類(lèi)需要關(guān)聯(lián)到Grid,活動(dòng)區(qū)域;和waitingGrid等候區(qū)域(下一個(gè)出現(xiàn)的方塊)

      2.在Container類(lèi)中實(shí)現(xiàn)消層的邏輯

      二、提供一個(gè)方塊基類(lèi)(Box),7中方塊全部從其派生。

      1.每個(gè)方塊包含4個(gè)Rectangle(小方格)

      2.通過(guò)一個(gè)工廠類(lèi)隨機(jī)產(chǎn)生某個(gè)方塊的實(shí)例

      3.基類(lèi)實(shí)現(xiàn)方塊移動(dòng)、變形、等邏輯、子類(lèi)定義方塊顏色、初始化方式,確定每個(gè)方格相對(duì)坐標(biāo)。

      4.在方塊下降到底部觸發(fā)OnBottom事件,Container接受此事件觸發(fā)消行邏輯。Container類(lèi)中OnGameover事件被界面層接受處理。

      運(yùn)行效果:

      image

       

      代碼部分:

       Box方塊基類(lèi) abstract class Box
      {

      public Box()
      {
      for (int i = 0; i < 4; i++)
      {
      rectangles.Add(new Rectangle());
      rectangles[i].Width = 24.0;
      rectangles[i].Height = 24.0;
      }

      dispatcherTimer = new DispatcherTimer(DispatcherPriority.Normal);
      dispatcherTimer.Tick += new EventHandler(Timer_Tick);
      dispatcherTimer.Interval = TimeSpan.FromMilliseconds(450 - Result.GetInstance().Level * 50);
      }


      protected Grid grid;

      /// <summary>
      /// 定義由四個(gè)方格組成的方塊
      /// </summary>
      protected IList<Rectangle> rectangles = new List<Rectangle>(4);

      DispatcherTimer dispatcherTimer;

      /// <summary>
      /// 當(dāng)方塊到達(dá)底部時(shí)觸發(fā)的事件句柄
      /// </summary>
      public event EventHandler OnBottom;

      /// <summary>
      /// 判斷x行y列是否包含方格
      /// </summary>
      protected bool Existence(int x, int y)
      {
      foreach (var r in grid.Children)
      {
      if (r is Rectangle)
      {
      if (this.rectangles.Contains(r as Rectangle)) return false;
      if (Convert.ToInt32((r as Rectangle).GetValue(Grid.ColumnProperty)) == x && Convert.ToInt32((r as Rectangle).GetValue(Grid.RowProperty)) == y)
      {
      return true;
      }
      }
      }
      return false;
      }

      /// <summary>
      /// 當(dāng)前方塊是否與其他方塊重疊
      /// </summary>
      public bool ISOverlapping()
      {
      foreach (var r in rectangles)
      {
      int x = Convert.ToInt32((r as Rectangle).GetValue(Grid.ColumnProperty));
      int y = Convert.ToInt32((r as Rectangle).GetValue(Grid.RowProperty));
      if (Existence(x, y)) return true;
      }
      return false;
      }


      /// <summary>
      /// 判斷由數(shù)值 x,y標(biāo)示的行列值是否在Grid范圍內(nèi)
      /// </summary>
      protected bool InGrid(int x, int y)
      {
      if (x >= 12 || y >= 24 || x < 0 || y < 0) return false;
      return true;
      }

      /// <summary>
      /// 定義活動(dòng)方塊自動(dòng)下降
      /// </summary>
      public void AtuoDown()
      {
      dispatcherTimer.Start();
      }

      private void Timer_Tick(object sender, EventArgs e)
      {
      if (!MoveDown())
      {
      dispatcherTimer.Stop();
      OnBottom(this, null);
      }
      }

      public abstract void Ready();
      public abstract void ShowWating(ref Grid WaingGrid);


      protected bool Move(int _x, int _y)
      {
      if (IsPause) return false;
      for (int i = 0; i < 4; i++)
      {
      int x = Convert.ToInt32(rectangles[i].GetValue(Grid.ColumnProperty)) + _x;
      int y = Convert.ToInt32(rectangles[i].GetValue(Grid.RowProperty)) + _y;
      if (Existence(x, y)) return false;
      if (!InGrid(x, y)) return false;
      }
      for (int i = 0; i < 4; i++)
      {
      rectangles[i].SetValue(Grid.ColumnProperty, Convert.ToInt32(rectangles[i].GetValue(Grid.ColumnProperty)) + _x);
      rectangles[i].SetValue(Grid.RowProperty, Convert.ToInt32(rectangles[i].GetValue(Grid.RowProperty)) + _y);
      }
      return true;
      }

      public bool MoveUp()
      {
      return Move(0, -1);
      }

      public bool MoveDown()
      {
      return Move(0, 1);
      }

      public bool MoveLeft()
      {
      return Move(-1, 0);
      }

      public bool MoveRight()
      {
      return Move(1, 0);
      }

      /// <summary>
      /// 快速下降
      /// </summary>
      public bool FastDown()
      {
      if (IsPause) return false;
      bool mark = false;
      int j = 0;
      while (!mark)
      {
      j++;
      for (int i = 0; i < 4; i++)
      {
      int x = Convert.ToInt32(rectangles[i].GetValue(Grid.ColumnProperty));
      int y = Convert.ToInt32(rectangles[i].GetValue(Grid.RowProperty)) + j;
      if (Existence(x, y) || !InGrid(x, y))
      {
      j--;
      mark = true;
      }
      }
      }
      for (int i = 0; i < 4; i++)
      {
      rectangles[i].SetValue(Grid.RowProperty, Convert.ToInt32(rectangles[i].GetValue(Grid.RowProperty)) + j);
      }

      //OnBottom(this, null);
      return mark;
      }

      /// <summary>
      /// 當(dāng)前方塊是否處于暫停狀態(tài)
      /// </summary>
      private bool IsPause = false;
      public void Pause()
      {
      dispatcherTimer.IsEnabled = false;
      IsPause = true;
      }

      public void UnPause()
      {
      dispatcherTimer.IsEnabled = true;
      IsPause = false;
      }

      public void StopAction()
      {
      dispatcherTimer.Stop();
      }


      /// <summary>
      /// 當(dāng)前變形狀態(tài)
      /// </summary>
      protected Status ActivityStatus;

      /// <summary>
      /// 變形
      /// </summary>
      public bool ChangeShape()
      {
      if (IsPause) return false;
      IList<Position> P = new List<Position>(4);
      for (int i = 0; i < 4; i++) P.Add(new Position());

      P[0].x = Convert.ToInt32(rectangles[0].GetValue(Grid.ColumnProperty)) + ActivityStatus.NextRelativeposition[0].x;
      P[0].y = Convert.ToInt32(rectangles[0].GetValue(Grid.RowProperty)) + ActivityStatus.NextRelativeposition[0].y;
      if (ActivityStatus.NeedCheck[0]) if (Existence(P[0].x, P[0].y) || !InGrid(P[0].x, P[0].y)) return false;

      P[1].x = Convert.ToInt32(rectangles[1].GetValue(Grid.ColumnProperty)) + ActivityStatus.NextRelativeposition[1].x;
      P[1].y = Convert.ToInt32(rectangles[1].GetValue(Grid.RowProperty)) + ActivityStatus.NextRelativeposition[1].y;
      if (ActivityStatus.NeedCheck[1]) if (Existence(P[1].x, P[1].y) || !InGrid(P[1].x, P[1].y)) return false;

      P[2].x = Convert.ToInt32(rectangles[2].GetValue(Grid.ColumnProperty)) + ActivityStatus.NextRelativeposition[2].x;
      P[2].y = Convert.ToInt32(rectangles[2].GetValue(Grid.RowProperty)) + ActivityStatus.NextRelativeposition[2].y;
      if (ActivityStatus.NeedCheck[2]) if (Existence(P[2].x, P[2].y) || !InGrid(P[2].x, P[2].y)) return false;

      P[3].x = Convert.ToInt32(rectangles[3].GetValue(Grid.ColumnProperty)) + ActivityStatus.NextRelativeposition[3].x;
      P[3].y = Convert.ToInt32(rectangles[3].GetValue(Grid.RowProperty)) + ActivityStatus.NextRelativeposition[3].y;
      if (ActivityStatus.NeedCheck[3]) if (Existence(P[3].x, P[3].y) || !InGrid(P[3].x, P[3].y)) return false;

      for (int i = 0; i < 4; i++)
      {
      rectangles[i].SetValue(Grid.ColumnProperty, P[i].x);
      rectangles[i].SetValue(Grid.RowProperty, P[i].y);
      }
      ActivityStatus = ActivityStatus.Next;

      return true;
      }
      }

      “Z”形方塊子類(lèi)

      class Box_Z : Box
      {

      public Box_Z(ref Grid grid)
      {
      this.grid = grid;
      for (int i = 0; i < 4; i++) rectangles[i].Fill = new SolidColorBrush(Colors.DarkOrange);
      }

      private void ShowAt(Position P, ref Grid grid)
      {
      rectangles[0].SetValue(Grid.ColumnProperty, P.x + 0);
      rectangles[0].SetValue(Grid.RowProperty, P.y + 0);

      rectangles[1].SetValue(Grid.ColumnProperty, P.x + 1);
      rectangles[1].SetValue(Grid.RowProperty, P.y + 0);

      rectangles[2].SetValue(Grid.ColumnProperty, P.x + 1);
      rectangles[2].SetValue(Grid.RowProperty, P.y + 1);

      rectangles[3].SetValue(Grid.ColumnProperty, P.x + 2);
      rectangles[3].SetValue(Grid.RowProperty, P.y + 1);

      for (int i = 0; i < 4; i++) grid.Children.Add(rectangles[i]);
      }

      public override void ShowWating(ref Grid WaingGrid)
      {
      ShowAt(new Position(1, 1), ref WaingGrid);
      }


      public override void Ready()
      {
      ShowAt(new Position(4, 0), ref grid);

      ActivityStatus = new Status();
      ActivityStatus.NextRelativeposition.Add(new Position(1, 2));
      ActivityStatus.NextRelativeposition.Add(new Position(0, 1));
      ActivityStatus.NextRelativeposition.Add(new Position(1, 0));
      ActivityStatus.NextRelativeposition.Add(new Position(0, -1));
      ActivityStatus.NeedCheck.Add(true);
      ActivityStatus.NeedCheck.Add(false);
      ActivityStatus.NeedCheck.Add(false);
      ActivityStatus.NeedCheck.Add(true);
      ActivityStatus.Next = new Status();

      ActivityStatus.Next.NextRelativeposition.Add(new Position(-1, -2));
      ActivityStatus.Next.NextRelativeposition.Add(new Position(0, -1));
      ActivityStatus.Next.NextRelativeposition.Add(new Position(-1, 0));
      ActivityStatus.Next.NextRelativeposition.Add(new Position(0, 1));
      ActivityStatus.Next.NeedCheck.Add(true);
      ActivityStatus.Next.NeedCheck.Add(true);
      ActivityStatus.Next.NeedCheck.Add(false);
      ActivityStatus.Next.NeedCheck.Add(false);
      ActivityStatus.Next.Next = ActivityStatus;
      }


      }

       由于每種方塊的變形方式都不一樣,Z型有4種狀態(tài),I型有2中狀態(tài),而O型只有一種狀態(tài),現(xiàn)在需要描述方塊形狀狀態(tài),需要定義循環(huán)鏈表數(shù)據(jù)類(lèi)型。

       

      定義一個(gè)坐標(biāo)點(diǎn),描述位置和相對(duì)位置 /// <summary>
      /// 定義一個(gè)方格坐標(biāo)點(diǎn)
      /// </summary>
      class Position
      {
      public Position(int x, int y)
      {
      this.x = x;
      this.y = y;
      }
      public Position()
      {
      }

      public int x { get; set; }
      public int y { get; set; }
      }

       

      /// <summary>
      /// 定義方塊形狀狀態(tài)循環(huán)鏈表,標(biāo)記變形狀態(tài)
      /// </summary>
      class Status
      {
      /// <summary>
      /// 方格[四個(gè)方塊]下一次變形將要去的相對(duì)位置
      /// </summary>
      public List<Position> NextRelativeposition = new List<Position>(4);

      /// <summary>
      /// 是否需要檢查方塊[每個(gè)方格]到這個(gè)位置的可行性
      /// </summary>
      public List<bool> NeedCheck = new List<bool>(4);

      /// <summary>
      /// 指向下一狀態(tài)
      /// </summary>
      public Status Next;
      }

       在方塊子類(lèi)中Ready方法即為每種方塊設(shè)置狀態(tài)鏈表。

       

      由于方塊的生成為隨機(jī)方式,定義簡(jiǎn)單工廠模式生成方塊如下:

      代碼 class BoxFactory
      {
      /// <summary>
      /// 隨機(jī)方塊工廠
      /// </summary>
      static public Box GetRandomBox(ref Grid grid)
      {
      //return new Box_Z(ref grid);
      Random ran = new Random();
      int index = ran.Next(7);
      switch (index)
      {
      case 0: return new Box_S(ref grid);
      case 1: return new Box_Z(ref grid);
      case 2: return new Box_J(ref grid);
      case 3: return new Box_L(ref grid);
      case 4: return new Box_I(ref grid);
      case 5: return new Box_O(ref grid);
      case 6: return new Box_T(ref grid);
      default: return null;
      }
      }
      }

        到此為止,方塊定義好了,也可以隨機(jī)產(chǎn)生了,怎么讓展示在Grid中?

      1.方塊子類(lèi)ShowAt函數(shù)標(biāo)示展示到指定Grid;

      2.ShowWating表示展示在等候區(qū)域。

       

      當(dāng)方塊展示到容器Grid中時(shí),怎么自動(dòng)下降呢?這里用到DispatcherTimer。

      dispatcherTimer = new DispatcherTimer(DispatcherPriority.Normal);
      dispatcherTimer.Tick += new EventHandler(Timer_Tick);
      dispatcherTimer.Interval = TimeSpan.FromMilliseconds(450 - Result.GetInstance().Level * 50);


      /// <summary>
      /// 定義活動(dòng)方塊自動(dòng)下降
      /// </summary>
      public void AtuoDown()
      {
      dispatcherTimer.Start();
      }         private void Timer_Tick(object sender, EventArgs e)
              {
                  if (!MoveDown())
                  {
                      dispatcherTimer.Stop();
                      OnBottom(this, null);
                  }
              }

       

      當(dāng)方塊到達(dá)底部時(shí),事件通知容器類(lèi)執(zhí)行消層函數(shù):

      在Box中:
      /// <summary>
      /// 當(dāng)方塊到達(dá)底部時(shí)觸發(fā)的事件句柄
      /// </summary>
      public event EventHandler OnBottom;

      private void Timer_Tick(object sender, EventArgs e)
      {
      if (!MoveDown())
      {
      dispatcherTimer.Stop();
      OnBottom(this, null);
      }
      }

      在Container中:
      ActivityBox.OnBottom += ActivityBox_OnBottom;
      /// <summary>
      /// 活動(dòng)方塊到達(dá)底部時(shí)觸發(fā)
      /// </summary>
      static public void ActivityBox_OnBottom(object sender, EventArgs e)
      {
      Result.GetInstance().CalculateScore(RemoveLine());
      NewBoxReadyToDown();
      }

       

      RemoveLine消層函數(shù) /// <summary>
      /// 消層,并返回消除的層數(shù)
      /// </summary>
      static int RemoveLine()
      {
      if (grid == null) new Exception("缺少活動(dòng)區(qū)域,必須為容器指定grid值。");

      int[] lineCount = new int[24];
      for (int i = 0; i < 24; i++) lineCount[i] = 0;

      int RemoveLineCount = 0;

      //計(jì)算每一行方塊總數(shù)
      foreach (var r in grid.Children)
      {
      if (r is Rectangle)
      {
      int x = Convert.ToInt32((r as Rectangle).GetValue(Grid.RowProperty));
      lineCount[x]++;
      }
      }
      for (int i = 23; i >= 0; i--)
      {
      if (lineCount[i] >= 12)
      {
      //移除一行小方格
      for (int j = 0; j < grid.Children.Count; j++)// (var r in mygrid.Children)
      {
      if (grid.Children[j] is Rectangle)
      {
      if (Convert.ToInt32((grid.Children[j] as Rectangle).GetValue(Grid.RowProperty)) == i + RemoveLineCount)
      {
      grid.Children.Remove((grid.Children[j] as Rectangle));
      j--;
      }
      }
      }

      //將上面的所有小方格下降一行
      foreach (var r in grid.Children)
      {
      if (r is Rectangle)
      {
      if (Convert.ToInt32((r as Rectangle).GetValue(Grid.RowProperty)) < i + RemoveLineCount)
      {
      (r as Rectangle).SetValue(Grid.RowProperty, Convert.ToInt32((r as Rectangle).GetValue(Grid.RowProperty)) + 1);
      }
      }
      }

      //被移除行數(shù)加1
      RemoveLineCount++;
      }
      }
      return RemoveLineCount;
      }

      OK,到此方塊可以自動(dòng)下降,可消層了,現(xiàn)在要統(tǒng)計(jì)消層得分和游戲級(jí)別(難度)。

      定義一個(gè)新類(lèi)Result

      Result類(lèi) /// <summary>
      /// 記錄分?jǐn)?shù)和級(jí)別
      /// </summary>
      class Result : INotifyPropertyChanged
      {
      Result()
      {
      Score = 0;
      Level = 1;
      }


      //單例模式
      private static Result instance;
      private static readonly object syncRoot = new object();
      public static Result GetInstance()
      {
      if (instance == null)
      {

      lock (syncRoot)
      {

      if (instance == null)
      {
      instance = new Result();
      }
      }
      }
      return instance;
      }


      int score;
      int level;

      public int Score
      {
      get { return score; }
      set { score = value; Notify("Score"); }
      }
      public int Level
      {
      get { return level; }
      set { level = value; Notify("Level"); }
      }

      public void CalculateScore(int Lines)
      {
      switch (Lines)
      {
      case 1: Score += 5;
      break;
      case 2: Score += 15;
      break;
      case 3: Score += 30;
      break;
      case 4: Score += 50;
      break;
      default: Score += 0;
      break;
      }

      if (Score < 20) Level = 1;
      else if (Score < 100) Level = 2;
      else if (Score < 300) Level = 3;
      else if (Score < 500) Level = 4;
      else if (Score < 1000) Level = 5;
      else if (Score < 3000) Level = 6;
      else if (Score < 5000) Level = 7;
      else Level = 8;

      }

      void Notify(string propName)
      {
      if (PropertyChanged != null)
      {
      PropertyChanged(this, new PropertyChangedEventArgs(propName));
      }
      }

      public event PropertyChangedEventHandler PropertyChanged;
      }

      在該類(lèi)中用單例模式控制產(chǎn)生單一實(shí)例,并通過(guò)實(shí)現(xiàn)接口綁定到界面分?jǐn)?shù)展示臺(tái)。

      界面XAML如下:

      <Grid Grid.Column="1" Grid.Row="1" Height="65" HorizontalAlignment="Left" Margin="5,6,0,0" Name="grid4" VerticalAlignment="Top" Width="100">
      <Label Content="積分:" Height="28" Name="label1" Margin="0,5,0,32" HorizontalAlignment="Left" Width="38" />
      <Label Content="{Binding Path=Score}" Height="28" Name="label2" Margin="35,5,0,32" />
      <Label Content="級(jí)別:" Height="28" Name="label3" Margin="0,34,0,3" HorizontalAlignment="Left" Width="38" />
      <Label Content="{Binding Path=Level}" Height="28" Name="label4" Margin="0,0,0,4" HorizontalAlignment="Right" VerticalAlignment="Bottom" Width="65" />
      </Grid>

       這樣,代碼中對(duì)Result賦值,直接影響界面控件展示數(shù)值的變化:

      /// <summary>
      /// 活動(dòng)方塊到達(dá)底部時(shí)觸發(fā)
      /// </summary>
      static public void ActivityBox_OnBottom(object sender, EventArgs e)
      {
      Result.GetInstance().CalculateScore(RemoveLine());
      NewBoxReadyToDown();
      }

      這里根據(jù)消行函數(shù)返回值此處對(duì)result實(shí)例進(jìn)行修改,界面數(shù)值(分?jǐn)?shù)、級(jí)別)也同步變化。

       最后,界面添加功能按鈕,實(shí)現(xiàn)Window_KeyDown事件 OnGameover事件,游戲完成。

        相關(guān)評(píng)論

        閱讀本文后您有什么感想? 已有人給出評(píng)價(jià)!

        • 8 喜歡喜歡
        • 3 頂
        • 1 難過(guò)難過(guò)
        • 5 囧
        • 3 圍觀圍觀
        • 2 無(wú)聊無(wú)聊

        熱門(mén)評(píng)論

        最新評(píng)論

        發(fā)表評(píng)論 查看所有評(píng)論(115)

        昵稱(chēng):
        表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
        字?jǐn)?shù): 0/500 (您的評(píng)論需要經(jīng)過(guò)審核才能顯示)