使用Xamarin开发移动应用示例——数独游戏(五)保存游戏进度

项目代码可以从Github下载:https://github.com/zhenl/ZL.Shudu 。代码随项目进度更新。

保存进度是移动应用的基本功能,在应用的使用过程中会有各种各样的可能导致使用中断,再次回到应用时,应该恢复到中断前的状态。前面我们已经初步完成了数独游戏,但还不具备状态保存的功能,现在我们增加这个功能,将游戏进度保存到本地文件中。

首先确定在什么地方保存和恢复状态。在Xamarin的View退出时会触发OnDisappearing事件,在这个事件中可以保存游戏的进度。在View再次显示时,首先判断是否存在以保存的进度,如果存在,就恢复状态,否则创建新的游戏。

然后确定需要保存的内容,需要保存当前已经输入的数字和位置,还需要保存输入的过程以及花费的时间。

还有就是保存的位置,Xamarin提供了每个应用保存数据的抽象位置,我们可以使用Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)来获取路径而不需要考虑设备类型。

所有这些确定好之后,就可以编写相应的逻辑了。

首先是保存状态的方法:

      private void Save(string filename)
        {
            try
            {
                var strchess = "";
                for (var i = 0; i < 9; i++)
                {
                    for (var j = 0; j < 9; j++)
                    {
                        strchess += chess[i, j].ToString();
                    }
                }
                strchess += " ";
                for (var i = 0; i < 9; i++)
                {
                    for (var j = 0; j < 9; j++)
                    {
                        strchess += string.IsNullOrEmpty(buttons[i, j].Text) ? "0" : buttons[i, j].Text;
                    }
                }
                strchess += " ";
                foreach (var str in steps)
                {
                    strchess += str + ";";
                }
                strchess += " ";
                strchess += (DateTime.Now - dtBegin).Ticks.ToString();
                string _fileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), filename);
                File.WriteAllText(_fileName, strchess);
            }
            catch (Exception ex)
            {

                lbMessage.Text = ex.Message;
            }
        }

在OnDisappearing事件响应中调用这个方法:

        protected override void OnDisappearing()
        {
            Save("shudu_current.txt");
        }

恢复状态的函数如下:

     private bool OpenCurrent()
        {
            try
            {
                string _fileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "shudu_current.txt");
                if (File.Exists(_fileName))
                {
                    var strchess = File.ReadAllText(_fileName);
                    int[,] fchess = new int[9, 9];
                    var arr = strchess.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                    for (var i = 0; i < 9; i++)
                    {
                        for (var j = 0; j < 9; j++)
                        {
                            chess[i, j] = int.Parse(arr[0].Substring(i * 9 + j, 1));
                            fchess[i, j] = int.Parse(arr[1].Substring(i * 9 + j, 1));
                        }
                    }
                    for (var i = 0; i < 9; i++)
                    {
                        for (var j = 0; j < 9; j++)
                        {
                            var btn = buttons[i, j];
                            if (chess[i, j] > 0)
                            {
                                btn.Text = chess[i, j].ToString();
                            }
                            else
                            {
                                btn.Text = fchess[i, j] > 0 ? fchess[i, j].ToString() : "";
                            }
                            btn.IsEnabled = chess[i, j] == 0;
                            int m = i / 3;
                            int n = j / 3;

                            var c = new Color(0.9, 0.9, 0.9);
                            if ((m + n) % 2 == 0)
                            {
                                c = new Color(0.7, 0.7, 0.7);
                            }
                            btn.BackgroundColor = c;
                        }
                    }
                    if (arr.Length > 2)
                    {
                        var steparr = arr[2].Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                        steps.Clear();
                        foreach(var step in steparr) steps.Push(step);
                    }
                    if (arr.Length > 3)
                    {
                        currentDiffer = long.Parse(arr[3]);
                    }
                    dtBegin = DateTime.Now;
                    return true;
                }
            }
            catch (Exception ex)
            {

                lbMessage.Text = ex.Message;
            }
            return false;
        }

在初始化时调用这个函数:

        public Game()
        {
            try
            {
                InitializeComponent();

                SetNumButtons();
                SetLayout();
                if (!OpenCurrent()) SetNewGame();

            }
            catch (Exception ex)
            {
                lbMessage.IsVisible = true;
                rowResult.Height = 40;
                lbMessage.Text = ex.Message;
                //throw;
            }
        }

最后,在游戏完成时删除状态文件:

            if (IsFinish())
            {
                lbFinish.IsVisible = true;
                lbTime.IsVisible = true;
                rowResult.Height = 40;
                var diff = (DateTime.Now.Ticks - dtBegin.Ticks + currentDiffer) / 10000 / 1000 / 60;
                lbTime.Text = diff + "分钟";
                string _fileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "shudu_current.txt");
                File.Delete(_fileName);
            }

状态保存完成了。下一步,我们引入数据库,保存游戏结果,并增加新游戏的录入功能。

上一篇:Environment Modules 安装配置


下一篇:SpringBoot的自动装配机制