zoukankan      html  css  js  c++  java
  • 使用 C# 开发智能手机软件:推箱子(二十二)

    这是“使用 C# 开发智能手机软件:推箱子” 系列文章的第二十二篇。在这篇文章中。介绍 Window/MainForm.Replay.cs 源程序文件。这个源程序文件是 MainForm 类的一部分,该类继承自 System.Windows.Forms.Form 类,表示推箱子的主窗口。

    而本篇文章讲述的是推箱子“回放”过程,例如以下图所看到的:

    我们先看看 MainForm.Designer.cs 源程序文件(该文件是由 Visual Studio 2005 IDE 自己主动生成的)中和“回放”相关的部分:

    namespace Skyiv.Ben.PushBox.Window
    {
      partial 
    class MainForm
      {
          
    // 注意:省略了非常多代码,仅保留和 miReplayOrLand 相关的部分。
        private void InitializeComponent()
        {
          
    this.miReplayOrLand = new System.Windows.Forms.MenuItem();
          
    this.mnuMain.MenuItems.Add(this.miReplayOrLand);
          
    this.miReplayOrLand.Text = "回放";
          
    this.miReplayOrLand.Click += new System.EventHandler(this.miReplayOrLand_Click);
        }
        
    private System.Windows.Forms.MenuItem miReplayOrLand;
      }
    }

    上述代码片断展示了在推箱子游戏的主窗口上点击“回放”时发生的事件:

    this.miReplayOrLand.Click += new System.EventHandler(this.miReplayOrLand_Click);

    也就是说假设曾经使用“录像”功能保存过通关步骤的话,能够通过“回放”功能将该通关步骤又一次播放出来。

    这是由以下的 MainForm.Replay.cs 源程序代码实现的:

     1 using System;
     2 using System.Drawing;
     3 using System.Threading;
     4 using Skyiv.Ben.PushBox.Common;
     5 
     6 namespace Skyiv.Ben.PushBox.Window
     7 {
     8   partial class MainForm
     9   {
    10     Rectangle workerThreadInvalidRectangle;
    11     bool workerThreadIsStop;
    12 
    13     private void miReplayOrLand_Click(object sender, EventArgs e)
    14     {
    15       if (env.IsDesign)
    16       {
    17         env.Pen = Block.Land;
    18         UpdateStatus();
    19       }
    20       else
    21       {
    22         env.IsReplay = true;
    23         workerThreadIsStop = false;
    24         UpdateStatus();
    25         ThreadPool.QueueUserWorkItem(WorkerThreadReplay, env.GetSteps());
    26       }
    27     }
    28 
    29     /// <summary>
    30     /// 回放通关步骤,使用后台工作线程
    31     /// </summary>
    32     /// <param name="steps">通关步骤</param>
    33     private void WorkerThreadReplay(object steps)
    34     {
    35       try
    36       {
    37         foreach (char c in (string)steps)
    38         {
    39           if (workerThreadIsStop) break;
    40           if (env.ReplayDelay > 0) Thread.Sleep(env.ReplayDelay);
    41           Step step = c;
    42           if (!env.StepIt(step.Direct, step.IsStop, out workerThreadInvalidRectangle)) break;
    43           Invoke(new EventHandler(WorkerThreadUpdateStatus));
    44         }
    45       }
    46       finally
    47       {
    48         env.IsReplay = false;
    49         Invoke(new EventHandler(WorkerThreadUpdateStatus));
    50       }
    51     }
    52 
    53     /// <summary>
    54     /// 更新主窗口状态
    55     /// </summary>
    56     /// <param name="sender">事件源</param>
    57     /// <param name="e">不包括不论什么事件数据的事件參数</param>
    58     void WorkerThreadUpdateStatus(object sender, EventArgs e)
    59     {
    60       Invalidate(workerThreadInvalidRectangle);
    61       UpdateStatus();
    62     }
    63   }
    64 }
    65 
    66 

    几点说明:

    • 由于“回放”是一个长时间的过程,为了防止用户界面失去响应。所以使用了多线程技术,在后台工作线程进行回放。

      也说是将回放通关步骤的 WorkerThreadReplay 方法增加到线程池中去:ThreadPool.QueueUserWorkItem(WorkerThreadReplay, env.GetSteps());

    • workerThreadInvalidRectangle 字段(Rectangle 类型)表明“回放”时主窗口须要更新的矩形区域。

      该值是由 Env 类的 StepIt 方法设定。

    • workerThreadIsStop 字段(bool 类型)指示是否停止回放,初始值为 false。当用户按“停止”button时,该字段被设置为 true。从而停止回放。
    • miReplayOrLand_Click 方法响应用户的“回放”请求,启动后台“回放”线程。
    • WorkerThreadReplay 方法在后台线程运行实际的“回放”动作,她实际上是对已经保存的通关步骤的每一步调用 Env 类的 StepIt 方法来进行“回放”,并通过 Invoke 调用  WorkerThreadUpdateStatus 方法更新主窗口状态。

    • WorkerThreadUpdateStatus 方法负责更新主窗口状态。

    • 假设在智能手机上进行“回放”,就是不使用后台线程,用户界面也不会失去响应,不知是什么原因。

  • 相关阅读:
    11.14 mii-tool:管理网络接口的状态
    11.15 dmidecode:查询系统硬件信息
    11.11 ntsysv:管理开机服务
    HDU 2476 String painter 刷字符串(区间DP)
    HDU 1085 Holding Bin-Laden Captive! 活捉本拉登(普通型母函数)
    母函数的应用
    HDU 1028 Ignatius and the Princess III伊格和公主III(AC代码)母函数
    HDU 1059 Dividing 分配(多重背包,母函数)
    HDU 2955 Robberies抢劫案(01背包,变形)
    HDU 1011 Starship Troopers星河战队(树形dp)
  • 原文地址:https://www.cnblogs.com/wgwyanfs/p/7060721.html
Copyright © 2011-2022 走看看