⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 env.cs

📁 手机软件开发..手机软件开发..手机软件开发..手机软件开发..
💻 CS
📖 第 1 页 / 共 2 页
字号:
    /// 保存设计数据
    /// </summary>
    public void SaveDesign()
    {
      if (HasError) return;
      try
      {
        db.SaveDesign(active == Action.Create, Level);
      }
      catch (Exception ex)
      {
        SetExceptionMessage(ex);
      }
    }

    /// <summary>
    /// 删除最后一关
    /// </summary>
    public void DeleteLastLevel()
    {
      if (HasError) return;
      try
      {
        db.DeleteLastLevel(Level);
      }
      catch (Exception ex)
      {
        SetExceptionMessage(ex);
      }
    }

    /// <summary>
    /// 更新主窗体客户区
    /// </summary>
    /// <param name="dc">画布</param>
    /// <param name="rectangle">要在其中绘画的矩形</param>
    public void Draw(Graphics dc, Rectangle rectangle)
    {
      if (HasError) return;
      Rectangle box = PixelToBox(rectangle);
      Rectangle box2 = new Rectangle(box.Left, box.Top, box.Width + 1, box.Height + 1);
      for (int i = 1; i <= LevelSize.Height; i++)
      {
        for (int j = 1; j <= LevelSize.Width; j++)
        {
          if (!box2.Contains(j, i)) continue;
          DrawBox(dc, j, i);
        }
      }
    }

    /// <summary>
    /// 绘制一个单元格
    /// </summary>
    /// <param name="dc">画布</param>
    /// <param name="x">单元格的横坐标</param>
    /// <param name="y">单元格的纵坐标</param>
    void DrawBox(Graphics dc, int x, int y)
    {
      DrawBox(dc, db.Map[y, x], (x - 1) * boxSize.Width, (y - 1) * boxSize.Height);
    }

    /// <summary>
    /// 绘制一个单元格
    /// </summary>
    /// <param name="dc">画布</param>
    /// <param name="idx">单元格的类型: 地 槽 墙 砖 箱子 工人</param>
    /// <param name="x">单元格的横坐标</param>
    /// <param name="y">单元格的纵坐标</param>
    void DrawBox(Graphics dc, int idx, int x, int y)
    {
      dc.DrawImage(img, x, y, new Rectangle(idx * boxSize.Width, 0, boxSize.Width, boxSize.Height), GraphicsUnit.Pixel);
    }

    /// <summary>
    /// 将单元格换算为像素
    /// </summary>
    /// <param name="box">单元格矩形</param>
    /// <returns>像素矩形</returns>
    Rectangle BoxToPixel(Rectangle box)
    {
      return new Rectangle((box.Left - 1) * boxSize.Width, (box.Top - 1) * boxSize.Height,
        (box.Width + 1) * boxSize.Width, (box.Height + 1) * boxSize.Height);
    }

    /// <summary>
    /// 将像素换算为单元格
    /// </summary>
    /// <param name="pixel">像素矩形</param>
    /// <returns>单元格矩形</returns>
    Rectangle PixelToBox(Rectangle pixel)
    {
      int x0 = pixel.Left / boxSize.Width + 1;
      int y0 = pixel.Top / boxSize.Height + 1;
      int x1 = (pixel.Right - 1) / boxSize.Width + 1;
      int y1 = (pixel.Bottom - 1) / boxSize.Height + 1;
      return new Rectangle(x0, y0, x1 - x0, y1 - y0);
    }

    /// <summary>
    /// 根据指定的对角顶点创建矩形
    /// </summary>
    /// <param name="a">顶点</param>
    /// <param name="b">对角的顶点</param>
    /// <returns>所需要的矩形</returns>
    Rectangle GetRectangle(Point a, Point b)
    {
      return Rectangle.FromLTRB(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y), Math.Max(a.X, b.X), Math.Max(a.Y, b.Y));
    }

    /// <summary>
    /// 设计模式下,当鼠标点击时要采取的动作
    /// </summary>
    /// <param name="invalid">输出:要重绘的区域</param>
    /// <returns>是否发生动作</returns>
    public bool Design(out Rectangle invalid)
    {
      invalid = Rectangle.Empty;
      Point to;
      if (!ValidClick(out to)) return false;
      db.UpdateCounts(to.X, to.Y, false);
      Block.Update(ref db.Map[to.Y, to.X], pen);
      db.UpdateCounts(to.X, to.Y, true);
      if (pen == Block.Man0 && HasWorker) pen = Block.Box0;
      invalid = BoxToPixel(GetRectangle(to, to));
      return true;
    }

    /// <summary>
    /// 工人往指定方向前进一步(可能推着箱子)
    /// </summary>
    /// <param name="dir">前进的方向</param>
    /// <param name="isStop">“撤销”时是否停留</param>
    /// <param name="invalid">输出:要重绘的区域</param>
    /// <returns>是否成功</returns>
    public bool StepIt(Direction dir, bool isStop, out Rectangle invalid)
    {
      invalid = Rectangle.Empty;
      if (HasError) return false;
      if (Direction.None == dir) return false;
      Point p1 = worker; // 工人前进方向一步的位置
      Point p2 = worker; // 箱子前进方向一步的位置
      switch (dir)
      {
        case Direction.East: p1.X++; p2.X += 2; break;
        case Direction.South: p1.Y++; p2.Y += 2; break;
        case Direction.West: p1.X--; p2.X -= 2; break;
        case Direction.North: p1.Y--; p2.Y -= 2; break;
      }
      byte b1 = db.Map[p1.Y, p1.X]; // 工人前进方向一步位置上的东西
      bool isBox = Block.IsBox(b1); // 是否推着箱子前进
      if (!isBox && !Block.IsBlank(b1)) return false; // 如果没有推着箱子且前方不是空地则失败
      if (isBox && !Block.IsBlank(db.Map[p2.Y, p2.X])) return false; // 如果推着箱子且箱子前方不是空地则失败
      invalid = BoxToPixel(GetRectangle(worker, isBox ? p2 : p1)); // 要重绘的区域
      stack.Push(new Step(dir, isBox, isStop)); // 记录走法步骤
      Block.ManOut(ref db.Map[worker.Y, worker.X]); // 工人离开当前位置
      Block.ManIn(ref db.Map[p1.Y, p1.X]); // 工人进入前方位置
      if (isBox)
      {
        pushSteps++; // 更新推箱子步数
        db.Boths += (db.Map[p2.Y, p2.X] - Block.Land) - (b1 - Block.Box0); // 更新已完成任务数
        Block.BoxOut(ref db.Map[p1.Y, p1.X]); // 箱子离开当前位置
        Block.BoxIn(ref db.Map[p2.Y, p2.X]); // 箱子进入前方位置
      }
      worker = p1; // 更新工人位置
      return true; // 工人成功前进一步(可能推着条子)
    }

    /// <summary>
    /// 工人后退一步(可能连带箱子一起后退)
    /// </summary>
    /// <param name="invalid">输出:要重绘的区域</param>
    /// <returns>是否完成“撤消”</returns>
    public bool Back(out Rectangle invalid)
    {
      invalid = Rectangle.Empty;
      if (HasError) return true;
      if (stack.Count == 0) return true;
      Step step = stack.Pop(); // 当前步骤
      Point p1 = worker; // 工人后退方向一步的位置
      Point p2 = worker; // 箱子的当前位置
      switch (step.Direct)
      {
        case Direction.East: p1.X--; p2.X++; break;
        case Direction.South: p1.Y--; p2.Y++; break;
        case Direction.West: p1.X++; p2.X--; break;
        case Direction.North: p1.Y++; p2.Y--; break;
      }
      invalid = BoxToPixel(GetRectangle(p1, step.IsBox ? p2 : worker)); // 要重绘的区域
      Block.ManOut(ref db.Map[worker.Y, worker.X]); // 工人离开当前位置
      Block.ManIn(ref db.Map[p1.Y, p1.X]); // 工人进入后退方向一步的位置
      if (step.IsBox)
      {
        Block.BoxOut(ref db.Map[p2.Y, p2.X]); // 箱子离开当前位置
        Block.BoxIn(ref db.Map[worker.Y, worker.X]); // 箱子进入工人原来的位置
        db.Boths += (db.Map[worker.Y, worker.X] - Block.Box0) - (db.Map[p2.Y, p2.X] - Block.Land); // 更新已完成任务数
        pushSteps--; // 更新推箱子步数
      }
      worker = p1; // 更新工人位置
      return step.IsStop; // 是否完成“撤消”
    }

    /// <summary>
    /// 寻找一条将工人移动到鼠标点击的位置的路线
    /// </summary>
    /// <returns>移动的路线</returns>
    public Queue<Direction> GetMoveInfo()
    {
      Point to;
      if (!CanTo(out to)) return null;
      return FindPath.Seek(db.Map, worker, to);
    }

    /// <summary>
    /// 给出将箱子推动到鼠标点击的位置所需的信息
    /// </summary>
    /// <param name="dir">输出:工人移动的方向</param>
    /// <returns>工人移动的步数</returns>
    public int GetPushInfo(out Direction dir)
    {
      dir = Direction.None;
      if (HasError) return 0;
      Point to; // 目的地
      if (!CanTo(out to)) return 0; // 无效的目的地
      if (to.Y != worker.Y && to.X != worker.X) return 0; // 目的地和工人不在同一条直线上
      int z0 = (to.Y == worker.Y) ? worker.X : worker.Y;
      int z9 = (to.Y == worker.Y) ? to.X : to.Y;
      if (to.Y == worker.Y) dir = (z9 > z0) ? Direction.East : Direction.West;
      else dir = (z9 > z0) ? Direction.South : Direction.North;
      int i0 = Math.Min(z9, z0);
      int i9 = Math.Max(z9, z0);
      int steps = i9 - i0; // 目的地和工人之间的距离
      int boxs = 0;
      for (int i = i0 + 1; i < i9; i++)
      {
        byte bi = (to.Y == worker.Y) ? db.Map[worker.Y, i] : db.Map[i, worker.X];
        if (Block.IsBox(bi)) boxs++; // 计算工人和目的地之间的箱子的个数
        else if (!Block.IsBlank(bi)) boxs += 2; // “墙”和“砖”折算为两个箱子
      }
      if (boxs > 1) return 0; // 最多只能推着一个箱子前进
      return steps - boxs; // 工人移动的步数
    }

    /// <summary>
    /// 检查鼠标点击位置是否可达, 并将像素换算为单元格
    /// </summary>
    /// <param name="to">输出:换算后的位置</param>
    /// <returns>是否可达</returns>
    bool CanTo(out Point to)
    {
      if (!ValidClick(out to)) return false;
      if (!Block.IsMan(db.Map[worker.Y, worker.X])) throw new Exception("内部错误:工人的位置上不是工人");
      if (!Block.IsBlank(db.Map[to.Y, to.X])) return false; // 目的地必须是“地”或“槽”
      if (to.Y == worker.Y && to.X == worker.X) return false; // 目的地不能是工人当前的位置
      return true; // 目的地可达
    }

    /// <summary>
    /// 检查鼠标点击位置是否有效, 并将像素换算为单元格
    /// </summary>
    /// <param name="to">输出:换算后的位置</param>
    /// <returns>是否有效位置</returns>
    bool ValidClick(out Point to)
    {
      to = Point.Empty;
      if (HasError) return false;
      to.Y = toPixel.Y / boxSize.Height + 1;
      to.X = toPixel.X / boxSize.Width + 1;
      if (toPixel.X >= boxSize.Width * LevelSize.Width || toPixel.Y >= boxSize.Height * LevelSize.Height)
        return false; // 目的地超出当前关的有效范围
      return true; // 目的地有效
    }
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -