数据设计
要去设计一个独立的系统。首先第一步就是要去分析整个系统的数据结构,要去思考需要用到什么数据。
那么我们来思考一下,签到系统需要用到哪些数据呢?
我们来分析一下有哪些数据需要考虑到?
签到的次数:可以得到你签到了多少天了
签到的奖励:每日签到总会给奖励吧。所以需要一个字典去存储第一日的奖励、第2日的奖励、。。。、第n日的奖励。第n+1日奖励你如何去设计,这里我们设计的是第n+1日的奖励会回到第一日,然后依次重复。
最近一次签到的时间:最近一次签到的时间 + 24h =》就是下一次签到的时间,如果当前的时间小于下一次签到的时间就无法签到,否则就可以签到。
需求分析
接着我们来分析一下签到的逻辑:用户一打开应用APP,进入主页后,需要拿到上一次签到的日期(这里需要读取数据)。然后检查当前日期与上一次签到的日期。如果上一次签到日期不是今天,且已经过了一天,那么说明可以签到。然后接下来去看你怎么设计。
如果你想要设计连续签到:如果上一次签到的日期是昨天,那么连续天数+1。如果超过1天没有签到,那么连续天数就重置为1。(怎么设计怎么来)
或者你也可以这么设计(下面的代码就是这么设计的):只要上一次签到的日期不是今天,那么签到的天数就+1。没有考虑超过一天没有签到就重置日期。
接着我们继续分析,如果当前可以签到,就要弹出签到的UI界面,只有用户点击了签到,UI界面才会消失。
点击完签到,就要获得向对应的奖励(至于获得什么奖励,你需要自己去设计)。需要准备一个数组(其他的也行),其中每一个元素对于第n天奖励。当用户签到天数达到对应的天数时,发放对应的奖励。如果超过数组长度时,进行取模,就可以回到第一天的奖励
分析完毕后,我们将分析的内容转化为数据。
代码实现
首先是数据的设计
// 签到数据
[System.Serializable]
public class SignInData
{
// 上一次签到的日期
public string lastSignInDate; // ISO8601格式的日期字符串
// 签到天数
public int currentStreak;
}
// 奖励(这个可以直接去设计)
[System.Serializable]
public class Reward
{
public string itemName; // 奖励名称(如金币、钻石)
public int amount; // 奖励数量
}
数据设计完毕,接下来就是逻辑相关的。
现在我们先不考虑实现,可以培养一下自己的封装能力。慢慢养成架构的思维方式。
public class SignInManager : MonoBehaviour
{
// 什么时候去判断当前是否签到(外部需要调用这个方法)
// 签到检测
private void 检测是否可以签到(){
// 1. 需要读取数据,拿到上一次签到的时间,才能够判断签到
// 2. 日期判断(只要超过一天就可以签到)
if(判断是否可以签到){
可以签到的方法
}else {
不可以签到的方法
}
}
private void 读取签到数据(){
}
private void 可以签到逻辑(){
// 1. 显示UI面板
// 这里UI是不是需要提供一下签到按钮,当用户按下签到按钮后,才会真正的执行签到的逻辑,并且得到奖励、然后隐藏签到UI面板
// 如果UI界面的逻辑写在这个类的话,就违背了单一职责原则,所以我们需要另一个类,专门去处理UI界面相关的
// 但是我们又不想要UI去处理按钮点击后的逻辑,所以我们可以向外部提供一个方法,专门去处理真正签到的逻辑,当点击这个按钮后,就调用这个外部的方法
}
private void 不可以签到(){
// 什么都不需要管
}
public void 真正签到的逻辑(){
// 1. 连续签到的次数+1
// 2. 上一次签到的时间 = 当前签到的时间
// 3. 根据当前签到的日期,获得签到的奖励
// 4. 将数据保存到本地
// 5. 隐藏当前的UI面板
}
public void 获得签到的奖励(){
// 通过配置表去获得
Reward reward = 配置表[签到天数];
// 将获得的奖励添加到玩家系统中(需要与玩家系统建立联系)
// InventoryManager.AddItem(奖励); 需要看具体是怎么设计
}
}
由了上面代码的分析,那么实现起来将会特别简单。至于具体细节不懂的话,也不用太担心,因为有ai辅助。
// 因为外部需要调用,所以需要把SignInManager设计为单例模式
public class SignInManager : MonoSingleTonBehaviour
{
private void LoadData()
{
// 从本地导入签到数据,并解析
if (!string.IsNullOrEmpty(json))
{
_signInData = JsonUtility.FromJson<SignInData>(json);
}
else
{
// 如果没有数据,那么说明是第一次导入,需要初始化数据
_signInData = new SignInData
{
lastSignInDate = DateTime.MinValue.ToString("O"),
currentStreak = 0
};
}
}
// 保存数据
private void SaveData()
{
将数据转化为json保存到本地
}
// 是否可以签到
public bool CanSignIn()
{
DateTime lastSignInDate = DateTime.Parse(_signInData.lastSignInDate);
DateTime nextValidDate = lastSignInDate.Date.AddDays(1);
return DateTime.Now >= nextValidDate;
}
// 真正的签到
public void SignIn()
{
if (!CanSignIn()) return;
DateTime now = DateTime.Now;
DateTime lastSignInDate = DateTime.Parse(_signInData.lastSignInDate);
// 计算连续签到
if ((now.Date - lastSignInDate.Date).TotalDays == 1)
{
_signInData.currentStreak++;
}
else if ((now.Date - lastSignInDate.Date).TotalDays > 1)
{
_signInData.currentStreak = 1;
}
else
{
_signInData.currentStreak = 1; // 首次签到
}
_signInData.lastSignInDate = now.ToString("O");
GrantReward();
SaveData();
}
}
public class SignInUI : MonoBehaviour
{
public void OnSignInButtonClicked()
{
if (SignInManager.Instance.CanSignIn())
{
SignInManager.Instance.SignIn();
}
else
{
Debug.Log("今日已签到或未到签到时间!");
}
}
}
评论区