在我的应用程序中,我有多个不是实时的“游戏”。在每个游戏中,每个玩家都有一个分数。在游戏过程中,玩家可以轮流做一些动作。
但是,如果在可定制的时间内(1小时到1个月之间)没有采取任何行动,那么两个玩家将失去x点数。
我想有一个由cron作业调用的全局“计时器”。以1小时的间隔,计时器将调用每个游戏的deductPoints()
功能。
在deductPoints()
函数中,我将执行以下操作:
deductPoints()
{
timeSinceLastDeduction++;
if(timeSinceLastDeduction >= frequencyOfDeduction)
{
deduct();
timeSinceLastDeduction = 0;
}
}
有没有更好的方法来完成这项任务?
答案 0 :(得分:1)
当转弯发生变化时,只需将当前时间戳存储到数据库中,然后使用cron在某段时间内执行检查,如果已经过了所需的时间,则执行游戏功能。
基本上就像你有远见,但你需要在某个地方存储时间值。进入数据库或文件。
答案 1 :(得分:1)
如果您愿意存储更多数据,我建议您使用此设计。
不是每次都扣除积分(强烈依赖游戏的“状态”),而是存储玩家所采取的每一个动作。例如,我们来看看这张表:
id | playerid | action | stamp
----+----------+----------+------------------------
1 | 1 | e2 to e4 | 2011-10-27 04:00:00-04
2 | 1 | | 2011-10-27 04:30:00-04
3 | 1 | | 2011-10-27 06:00:00-04
4 | 1 | | 2011-10-27 07:45:00-04
5 | 1 | | 2011-10-27 08:00:00-04
等。等
顺便说一句,e2到e4是国际象棋的一种常见开场动作。你的游戏,我无法真正设计出来。 “动作”是可选的,但是,您只需要存储动作发生的事实来计算惩罚。 (但也可以存储额外的信息,只要你有空间这样做)。“id”是这种情况下的代理键。在Postgresql中,DDL看起来像:
CREATE TABLE actions(
id BIGSERIAL PRIMARY KEY,
playerid int,
action text,
stamp timestamptz,
UNIQUE(playerid, stamp));
元组(playerid,stamp)将是“真正的”主键。 “id”是代理密钥。
要查看时间戳的差异,使用窗口函数代码相对简单。 (继续使用PostgreSQL)
select playerid, time_between, id FROM
(SELECT playerid,
stamp - lag(stamp) OVER () as time_between,
id FROM actions
ORDER BY stamp)
as ss
WHERE playerid = 1
AND time_between > '1 hour';
示例输出,给出前面的测试数据:
playerid | time_between | id
----------+--------------+----
1 | 01:30:00 | 3
1 | 01:45:00 | 4
你根本没有cron工作。您存储了更多数据(因此更容易“撤消”操作)。如果他们愿意,您的玩家可以查看过去的动作。如果计算惩罚效率低下,那么您可以随时将分数缓存在更高的水平。
MySQL btw中没有窗口函数。但是可以在PostgreSQL,SQL Server和Oracle中使用。
编辑:如果空间是一个问题,那么你可以经常“垃圾收集”这个表定期。不过,那将是很多游戏。每行占用~48个字节(假设为“动作”)。如果你有1000个玩家,每个玩40个游戏,40个动作,你只需要384MB的数据。