用户在线时长增加经验并升级功能
需求描述
- 每一小时为用户增加 10 点经验。
- 当用户的经验值增加到一定数值后,用户自动升级。
数据库设计
我们需要两张表来支持该功能:
1. 用户等级表:user_level
用于保存用户的当前等级和经验值。
- 字段说明:
id
(主键)uid
(用户ID)now_level
(当前等级)exp
(当前经验值)
2. 等级经验对照表:level_exp
用于定义经验值与等级的对应关系,例如:1-200 经验值对应等级 1,201-300 经验值对应等级 2。
- 字段说明:
id
(主键)level
(等级)min
(起始经验值)max
(结束经验值)
实现思路
- 每当为用户增加经验后,获取该用户的总经验值。
- 例如:当前经验值为 200,增加 10 点经验后,总经验为 210。
- 通过二分查找,确定当前经验值属于哪个等级区间。
- 假设总经验为 210,则需要在
level_exp
表中找到对应的等级区间。
- 假设总经验为 210,则需要在
- 比较该用户当前等级与计算得出的等级:
- 如果两个值相同,说明用户不能升级;
- 如果两个值不同,说明用户可以升级,更新用户等级信息。
二分查找算法
以下是用于查找用户当前经验值所属等级的二分查找算法:
/**
* 二分查找法,用于根据经验值查找对应的等级区间
*
* @param int $score 用户当前经验值
* @param array $filter 经验与等级的对应关系数组
* @return array 返回经验值所在的等级区间
*/
function levelSearch($score, $filter)
{
$half = floor(count($filter) / 2); // 取出中间数
// 判断经验值在哪个区间
if ($score <= $filter[$half - 1]['max']) {
$filter = array_slice($filter, 0 , $half);
} else {
$filter = array_slice($filter, $half , count($filter));
}
// 继续递归直到只剩一个元素
if (count($filter) != 1) {
$filter = levelSearch($score, $filter);
}
return $filter;
}
实现过程
假设 level_exp
中的经验与等级对应关系如下:
$filter = [
['level' => 1, 'min' => 1, 'max' => 50],
['level' => 2, 'min' => 51, 'max' => 110],
['level' => 3, 'min' => 111, 'max' => 180],
['level' => 4, 'min' => 181, 'max' => 260],
['level' => 5, 'min' => 261, 'max' => 500],
];
例如,用户当前经验值为 240
,则通过 levelSearch
函数查找该经验值对应的等级:
$result = levelSearch(240, $filter);
echo current($result)['level']; // 输出:4
总结
通过这种实现方式,我们可以快速确定用户的当前经验值属于哪个等级区间,并在用户经验值增加后自动升级。这种基于二分查找的方案可以有效提升查询性能,尤其是在等级区间较多的情况下。