游戏币管理类

调用代码

GameCoinManager gameCoinManager = GameCoinManager.getInstance(this);

//使用游戏币
    public void useCoins(int amount) {
        gameCoinManager.subtractGameCoins(amount);
        updateCoinsDisplay();
    }

    //更新游戏币数量
    private void updateCoinsDisplay() {
        int user_coin = gameCoinManager.getGameCoins();
        money_text.setText(String.valueOf(user_coin));
    }

    //增加游戏币
    private void addCoinsDisplay(int amount) {
        gameCoinManager.addGameCoins(amount);
        updateCoinsDisplay();
    }

工具类

package com.example.majia;

import android.content.Context;
import android.content.SharedPreferences;
import android.widget.Toast;

import java.util.Calendar;

/**
 * GameCoinManager 类用于管理游戏中的货币(游戏币)系统。
 * 该类采用单例模式,通过 SharedPreferences 存储和管理用户的游戏币数量、
 * 奖励领取时间和次数等信息。
 */
public class GameCoinManager {

    // SharedPreferences 文件名和键值
    private static final String PREFS_NAME                = "game_prefs";                // SharedPreferences 文件名
    private static final String KEY_GAME_COINS            = "user_coin";                 // 游戏币的键值
    private static final String KEY_LAST_REWARD_TIMESTAMP = "last_reward_timestamp";     // 上次奖励领取时间的键值
    private static final String KEY_REWARD_INDEX          = "reward_index";              // 当前奖励序列的索引键值
    private static final String KEY_DAILY_REWARD_COUNT    = "daily_reward_count";        // 每日领取奖励次数的键值

    // 默认值和限制
    private static final int  DEFAULT_COINS         = 0; // 游戏币的默认值
    private static final int  MAX_DAILY_REWARDS     = 5; // 每天最多领取奖励次数

    // 奖励时间间隔(毫秒)和每个间隔对应的奖励数量
    private static final long[] REWARD_TIMES   = {0, 15 * 60 * 1000, 30 * 60 * 1000, 30 * 60 * 1000, 60 * 60 * 1000}; // 各个奖励之间的时间间隔(毫秒)
    private static final int[]  REWARD_AMOUNTS = {500, 500, 1000, 1000, 2000};                                          // 对应每个奖励时间的奖励数量

    private static GameCoinManager   instance;          // 单例对象
    private        SharedPreferences sharedPreferences; // 用于存储游戏币和奖励信息的 SharedPreferences 对象
    private        Context           context;           // 应用程序的上下文对象

    /**
     * 私有构造函数,确保该类使用单例模式创建。
     * 初始化 SharedPreferences 对象。
     *
     * @param context 应用程序的上下文
     */
    private GameCoinManager(Context context) {
        this.context      = context.getApplicationContext(); // 获取应用级别的上下文
        sharedPreferences = this.context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); // 获取 SharedPreferences 实例
    }

    /**
     * 获取 GameCoinManager 的单例实例。
     * 
     * @param context 应用程序的上下文
     * @return GameCoinManager 的实例
     */
    public static synchronized GameCoinManager getInstance(Context context) {
        if (instance == null) {
            instance = new GameCoinManager(context); // 如果实例不存在则创建
        }
        return instance;
    }

    /**
     * 获取当前的游戏币数量。
     *
     * @return 当前游戏币数量
     */
    public int getGameCoins() {
        return sharedPreferences.getInt(KEY_GAME_COINS, DEFAULT_COINS);
    }

    /**
     * 设置游戏币数量。
     *
     * @param coins 要设置的游戏币数量
     */
    public void setGameCoins(int coins) {
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putInt(KEY_GAME_COINS, coins); // 将游戏币数量写入 SharedPreferences
        editor.apply();
    }

    /**
     * 增加游戏币数量。
     *
     * @param coins 要增加的游戏币数量
     */
    public void addGameCoins(int coins) {
        int currentCoins = getGameCoins();
        setGameCoins(currentCoins + coins); // 增加指定数量的游戏币
    }

    /**
     * 减少游戏币数量,若余额不足则返回 false 并显示提示。
     *
     * @param coins 要减少的游戏币数量
     * @return 若减少成功返回 true,否则返回 false
     */
    public boolean subtractGameCoins(int coins) {
        int currentCoins = getGameCoins();
        if (currentCoins < coins) {
            Toast.makeText(context, "NOT ENOUGH MONEY", Toast.LENGTH_SHORT).show(); // 余额不足时显示提示
            return false;
        } else {
            setGameCoins(currentCoins - coins); // 扣除游戏币
            return true;
        }
    }

    /**
     * 检查是否可以领取时间奖励。
     * 
     * @return 如果可以领取则返回 true,否则返回 false
     */
    public boolean canReceiveTimeReward() {
        resetIfMidnightPassed(); // 检查是否过了午夜,若是则重置奖励
        long lastRewardTimestamp = sharedPreferences.getLong(KEY_LAST_REWARD_TIMESTAMP, 0); // 上次领取时间
        int  rewardIndex         = sharedPreferences.getInt(KEY_REWARD_INDEX, 0);           // 当前奖励索引
        int  dailyRewardCount    = sharedPreferences.getInt(KEY_DAILY_REWARD_COUNT, 0);    // 当天已领取次数

        // 检查今天领取次数是否已经达到上限
        if (dailyRewardCount >= MAX_DAILY_REWARDS) {
            Toast.makeText(context, "Daily reward limit reached", Toast.LENGTH_SHORT).show(); // 提示已达到每日领取上限
            return false;
        }

        // 重置 rewardIndex 为 0 如果超出 REWARD_TIMES 的长度
        if (rewardIndex >= REWARD_TIMES.length) {
            rewardIndex = 0;
        }

        long currentTime  = System.currentTimeMillis();                 // 当前时间
        long elapsedTime  = currentTime - lastRewardTimestamp;          // 距离上次领取奖励的时间
        long requiredTime = REWARD_TIMES[rewardIndex];                  // 当前索引的奖励所需时间

        return elapsedTime >= requiredTime; // 如果经过时间大于等于所需时间则可以领取
    }

    /**
     * 领取时间奖励。
     * 如果不符合领取条件则直接返回。
     */
    public void receiveTimeReward() {
        if (!canReceiveTimeReward()) {
            return; // 如果不满足领取条件则直接返回
        }

        int rewardIndex      = sharedPreferences.getInt(KEY_REWARD_INDEX, 0);           // 当前奖励索引
        int dailyRewardCount = sharedPreferences.getInt(KEY_DAILY_REWARD_COUNT, 0);     // 当天已领取次数

        // 重置 rewardIndex 为 0 如果超出 REWARD_TIMES 的长度
        if (rewardIndex >= REWARD_TIMES.length) {
            rewardIndex = 0;
        }

        int rewardAmount = REWARD_AMOUNTS[rewardIndex]; // 根据索引获取奖励数量
        addGameCoins(rewardAmount);                     // 增加游戏币

        rewardIndex++;          // 索引递增,准备下次领取
        dailyRewardCount++;     // 当天领取次数增加

        // 若索引达到 REWARD_TIMES 长度,则以最后一个奖励时间(60分钟)为循环的起始点
        if (rewardIndex >= REWARD_TIMES.length) {
            rewardIndex = REWARD_TIMES.length - 1;
        }

        // 保存新的奖励状态
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putInt(KEY_REWARD_INDEX, rewardIndex);
        editor.putLong(KEY_LAST_REWARD_TIMESTAMP, System.currentTimeMillis());
        editor.putInt(KEY_DAILY_REWARD_COUNT, dailyRewardCount);
        editor.apply();

        Toast.makeText(context, "Earn rewards " + rewardAmount + " Game currency", Toast.LENGTH_SHORT).show(); // 显示领取的奖励
    }

    /**
     * 获取距离下次奖励的剩余时间。
     * 
     * @return 距离下次奖励的剩余时间(毫秒)
     */
    public long getTimeRemainingForNextReward() {
        resetIfMidnightPassed(); // 检查是否需要重置奖励
        long lastRewardTimestamp = sharedPreferences.getLong(KEY_LAST_REWARD_TIMESTAMP, 0); // 上次领取时间
        int  rewardIndex         = sharedPreferences.getInt(KEY_REWARD_INDEX, 0);           // 当前奖励索引

        // 重置 rewardIndex 为 0 如果超出 REWARD_TIMES 的长度
        if (rewardIndex >= REWARD_TIMES.length) {
            rewardIndex = 0;
        }

        long requiredTime = REWARD_TIMES[rewardIndex];                  // 当前索引的奖励所需时间
        long currentTime  = System.currentTimeMillis();                 // 当前时间
        long elapsedTime  = currentTime - lastRewardTimestamp;          // 距离上次领取的时间

        return requiredTime - elapsedTime; // 返回剩余时间
    }

    /**
     * 如果已经过了午夜,重置奖励计时器。
     */
    private void resetIfMidnightPassed() {
        long     lastRewardTimestamp = sharedPreferences.getLong(KEY_LAST_REWARD_TIMESTAMP, 0); // 上次领取奖励的时间戳
        Calendar lastRewardCalendar  = Calendar.getInstance();                                  // 创建一个日历实例用于比较时间
        lastRewardCalendar.setTimeInMillis(lastRewardTimestamp);                                // 设置为上次领取的时间

        Calendar currentCalendar = Calendar.getInstance(); // 当前时间

        // 检查是否过了午夜(日期或年份是否变化)
        if (currentCalendar.get(Calendar.DAY_OF_YEAR) != lastRewardCalendar.get(Calendar.DAY_OF_YEAR) ||
                currentCalendar.get(Calendar.YEAR) != lastRewardCalendar.get(Calendar.YEAR)) {
            // 重置奖励计数和索引
            SharedPreferences.Editor editor = sharedPreferences.edit();
            editor.putInt(KEY_REWARD_INDEX, 0);
            editor.putInt(KEY_DAILY_REWARD_COUNT, 0); // 重置每日奖励计数
            editor.putLong(KEY_LAST_REWARD_TIMESTAMP, currentCalendar.getTimeInMillis());
            editor.apply();
        }
    }
}