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

📄 datafile.cs

📁 windows mobile上开发的推箱子小游戏,用C#写的,虽然只是DEMO版但大致功能已经实现
💻 CS
📖 第 1 页 / 共 2 页
字号:
     /// </summary>
     /// <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)
     {
       for (int i = level + 1; i <= maxLevel; i++) addrs[i - 1] = addrs[i]; // 之后的关起始地址前移
       --maxLevel; // 更新总关数
       WriteAddrs();
     }
 
     /// <summary>
     /// 更新各关起始地址列表及总关数和第1关起始地址位置
     /// </summary>
     private void WriteAddrs()
     {
       bw.Seek(addrs[maxLevel], SeekOrigin.Begin);
       for (int i = 0; i < maxLevel; i++) bw.Write(addrs[i]); // 各关起始地址
       bw.BaseStream.SetLength(bw.BaseStream.Position); // 关起始地址列表位于数据文件最后, 用于删除关的情况
       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 + -