專案程式碼可以從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);
}
狀態儲存完成了。下一步,我們引入資料庫,儲存遊戲結果,並增加新遊戲的錄入功能。