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

📄 datafile.cs

📁 手机软件开发..手机软件开发..手机软件开发..手机软件开发..
💻 CS
📖 第 1 页 / 共 2 页
字号:
    /// <param name="isNew">是否新建</param>
    /// <param name="level">要保存的关数</param>
    public void SaveDesign(bool isNew, int level)
    {
      if (isNew && level != maxLevel) throw new Exception("新建的关必须在最后一关之后");
      bw.BaseStream.Seek(addrs[level], SeekOrigin.Begin);
      WriteLevel(level, string.Empty); // 如果不是新建,则关尺寸不能比原来的大
      if (isNew)
      {
        Fcl.Resize(ref addrs, addrs.Length + 1);
        addrs[++maxLevel] = (int)bw.BaseStream.Position;
        WriteAddrs();
      }
      DeleteStepsFile(level); // 删除通关步骤文件
    }

    /// <summary>
    /// 删除最后一关
    /// </summary>
    /// <param name="level">关数(必须是最后一关)</param>
    public void DeleteLastLevel(int level)
    {
      if (level != maxLevel - 1) throw new Exception("要删除的关必须是最后一关");
      DeleteLevel(level);
      DeleteStepsFile(level); // 删除通关步骤文件,如果被删除的关不是最后一关,以后各关的通关步骤文件就不对了
    }

    /// <summary>
    /// 删除指定的关
    /// </summary>
    /// <param name="level">关数</param>
    void DeleteLevel(int level)
    {
      bw.Seek(addrs[maxLevel] + 4 * level, SeekOrigin.Begin); // 要删除的关起始地址位置
      for (int i = level + 1; i < maxLevel; i++) bw.Write(addrs[i]); // 之后的关起始地址前移
      bw.BaseStream.SetLength(bw.BaseStream.Position); // 关起始地址列表位于数据文件最后
      bw.Seek(24, SeekOrigin.Begin); // 总关数
      bw.Write(--maxLevel);
    }

    /// <summary>
    /// 更新各关起始地址列表及总关数和第1关起始地址位置
    /// </summary>
    private void WriteAddrs()
    {
      bw.Seek(addrs[maxLevel], SeekOrigin.Begin);
      for (int i = 0; i < maxLevel; i++) bw.Write(addrs[i]); // 各关起始地址
      bw.Seek(24, SeekOrigin.Begin);
      bw.Write(maxLevel); // 总关数
      bw.Write(addrs[maxLevel]); // 第1关起始地址位置
    }

    /// <summary>
    /// 更新组名
    /// </summary>
    void WriteGroupName()
    {
      byte[] bs = new byte[16];
      byte[] bn = Pub.Encode.GetBytes(groupName);
      for (int i = 0; i < bs.Length && i < bn.Length; i++) bs[i] = bn[i];
      for (int i = bn.Length; i < bs.Length; i++) bs[i] = 32;
      bw.Seek(8, SeekOrigin.Begin);
      bw.Write(bs); // 组名
    }

    /// <summary>
    /// 写关数据和通关步骤
    /// 注意:调用本函数前必须定位到数据文件的正确位置
    /// </summary>
    /// <param name="level">关数</param>
    /// <param name="steps">通关步骤</param>
    /// <returns>本关的统计信息</returns>
    string WriteLevel(int level, string steps)
    {
      bw.Write(LevelFlag); // 关标志
      bw.Write((byte)(string.IsNullOrEmpty(steps) ? 0 : 1)); // 标志:是否已通关
      bw.Write(steps.Length); // 总步数
      bw.Write(GetPushSteps(steps)); // 推箱子步数
      bw.Write(new byte[14]); // 保留
      bw.Write(levelSize.Width); // 当前关宽度
      bw.Write(levelSize.Height); // 当前关高度
      mans = slots = boxs = 0;
      int lands = 0, walls = 0, bricks = 0;
      for (int i = 1; i <= levelSize.Height; i++)
      {
        for (int j = 1; j <= levelSize.Width; j++)
        {
          bw.Write(map[i, j]);
          switch (map[i, j])
          {
            case Block.Land: lands++; break;
            case Block.Slot: slots++; break;
            case Block.Wall: walls++; break;
            case Block.Brick: bricks++; break;
            case Block.Box0: lands++; boxs++; break;
            case Block.Box1: slots++; boxs++; break;
            case Block.Man0: lands++; mans++; break;
            case Block.Man1: slots++; mans++; break;
          }
        }
      }
      if (mans != 1) ErrorExit(true, level + 1, "必须刚好有一个工人");
      if (!string.IsNullOrEmpty(steps)) SaveLevelSteps(level, steps);
      return string.Format("{1}: {2} {3} {4} {5} {6} {7} {8}{0}",
        Fcl.NewLine, level + 1, Pub.ToString(levelSize), walls, bricks, lands, slots, boxs, steps.Length);
    }

    /// <summary>
    /// 根据通关步骤给出推箱子步数
    /// </summary>
    /// <param name="steps">通关步骤</param>
    /// <returns>推箱子步数</returns>
    int GetPushSteps(string steps)
    {
      int n = 0;
      foreach (char c in steps) if (((Step)c).IsBox) n++;
      return n;
    }

    /// <summary>
    /// 数据导入
    /// </summary>
    /// <param name="name">数据文件主名</param>
    /// <param name="maxLevelSize">最大关尺寸</param>
    /// <param name="tbxMsg">显示相关信息的文本框</param>
    public void Import(string name, int maxLevelSize, TextBox tbxMsg)
    {
      try
      {
        tbxMsg.Text = string.Format("{1} => {2}{0}", Fcl.NewLine, name + Pub.TextExtName, name + Pub.DataExtName);
        if (!Directory.Exists(Pub.DataDirectory)) Directory.CreateDirectory(Pub.DataDirectory);
        using (StreamReader sr = new StreamReader(Path.Combine(Pub.TextDirectory, name + Pub.TextExtName), Pub.Encode))
        {
          Dispose();
          fs = new FileStream(Path.Combine(Pub.DataDirectory, name + Pub.DataExtName), FileMode.Create, FileAccess.Write);
          bw = new BinaryWriter(fs, Pub.Encode);
          byte[] buf = new byte[32];
          buf[4] = DataVersion;
          buf[5] = (byte)'B';
          buf[6] = (byte)'O';
          buf[7] = (byte)'X';
          bw.Write(buf);
          map = new byte[maxLevelSize + 2, maxLevelSize + 2];
          List<int> addrList = new List<int>(); // 各关起始地址列表,最后一项为第1关起始地址位置
          addrList.Add((int)bw.BaseStream.Position); // 第1关起始地址
          groupName = name; // 组名
          int level = 0;
          levelSize = Size.Empty;
          string steps = ""; // 通关步骤
          bool isFirst = true;
          for (int line = 1; ; line++)
          {
            string s = sr.ReadLine();
            if (s != null) s = s.Trim();
            if (line == 1 && s != null && s.Length > 0 && s[0] == '!')
            {
              groupName = s.Substring(1).Trim();
              tbxMsg.Text += "组名: [" + groupName + "]" + Fcl.NewLine;
              continue;
            }
            if (isFirst)
            {
              isFirst = false;
              tbxMsg.Text += "#: 宽x高 墙 砖 地 槽 箱 通关步数" + Fcl.NewLine;
            }
            if ((s == null || s.Length == 0) && levelSize != Size.Empty)
            {
              tbxMsg.Text += WriteLevel(level, steps);
              addrList.Add((int)bw.BaseStream.Position); // 下一关起始地址
              level++;
              levelSize = Size.Empty;
              steps = "";
            }
            if (s == null) break;
            if (s.Length == 0 || s[0] == RemChar) continue;
            if (s[0] == StepsChar)
            {
              steps = s.Substring(1).Trim(); // 通关步骤
              continue;
            }
            levelSize.Height++;
            if (levelSize.Height == 1) levelSize.Width = s.Length;
            else if (levelSize.Width != s.Length) ErrorExit(false, line, "宽度不齐");
            if (levelSize.Width > maxLevelSize) ErrorExit(false, line, GetMessage("宽度太大", true));
            if (levelSize.Height > maxLevelSize) ErrorExit(false, line, GetMessage("高度太大", true));
            for (int i = 0; i < levelSize.Width; i++)
              if (!Block.IsBlock(map[levelSize.Height, i + 1] = Block.GetByte(s[i])))
                ErrorExit(false, line, "非法字符:[" + s[i] + "]");
          }
          addrs = addrList.ToArray();
          maxLevel = level;
          WriteAddrs();
          WriteGroupName();
        }
      }
      catch (OutOfMemoryException ex)
      {
        throw new Exception(GetMessage("内存不足", false), ex);
      }
      finally
      {
        Dispose();
      }
      tbxMsg.Text += "导入完成";
    }

    string GetMessage(string msg1, bool isIncrease)
    {
      return msg1 + ",请在“菜单 -> 选项”对话框中" + (isIncrease ? "增加" : "减少") +"“最大关尺寸”";
    }

    /// <summary>
    /// 数据导出
    /// </summary>
    /// <param name="name">数据文件主名</param>
    /// <param name="tbxMsg">显示相关信息的文本框</param>
    public void Export(string name, TextBox tbxMsg)
    {
      try
      {
        tbxMsg.Text = string.Format("{1} => {2}{0}", Fcl.NewLine, name + Pub.DataExtName, name + Pub.TextExtName);
        LoadGroup(name);
        if (!Directory.Exists(Pub.TextDirectory)) Directory.CreateDirectory(Pub.TextDirectory);
        using (StreamWriter sw = new StreamWriter(
          Path.Combine(Pub.TextDirectory, name + Pub.TextExtName), false, Pub.Encode))
        {
          sw.WriteLine("! {0}", groupName);
          tbxMsg.Text += "组名: [" + groupName + "]" + Fcl.NewLine;
          tbxMsg.Text += "#: 宽x高 总任务数 通关步数" + Fcl.NewLine;
          for (int level = 0; level < maxLevel; level++)
          {
            LoadLevel(level);
            sw.WriteLine("{0}[{1}]", RemChar, level + 1); // 注释:第几关
            for (int y = 0; y < levelSize.Height; y++)
            {
              for (int x = 0; x < levelSize.Width; x++) sw.Write(Block.GetChar(map[y + 1, x + 1]));
              sw.WriteLine();
            }
            string steps = GetSteps(name, level); // 通关步骤
            if (!string.IsNullOrEmpty(steps)) sw.WriteLine(StepsChar + steps);
            sw.WriteLine();
            tbxMsg.Text += string.Format("{1}: {2} {3} {4}{0}",
              Fcl.NewLine, level + 1, Pub.ToString(levelSize), tasks, steps.Length);
          }
        }
      }
      finally
      {
        Dispose();
      }
      tbxMsg.Text += "导出完成";
    }

    void ErrorExit(bool isLevel, int idx, string msg)
    {
      throw new Exception(string.Format("错误:第{0}{1}:{2}", idx, isLevel ? "关" : "行", msg));
    }

    public void Dispose()
    {
      if (br != null) br.Close();
      if (bw != null) bw.Close();
      if (fs != null) fs.Close();
      br = null;
      bw = null;
      fs = null;
    }
  }
}

⌨️ 快捷键说明

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