选择抽奖券获奖者

时间:2012-02-13 19:50:09

标签: php mysql

我创建了一个脚本,用户可以通过完成任务获得积分,然后获得的积分越多,获得奖励的机会就越大。 它就像抽奖活动一样。

我的问题是赢得胜利者。

我可以选择一个随机获胜者,其代码如下:

    function selectWinners($count){
    $select = mysql_query("SELECT first_name from `users` ORDER BY RAND() LIMIT {$count}");
    $results = mysql_fetch_assoc($select);
    echo "Winner is {$results[first_name]}";
    }

但这完全是随机的,关于用户拥有多少点并不重要。

我相信我必须创建一个临时表,显示他们拥有的每个点的用户ID,然后使用类似的脚本来选择随机ID?

我不完全确定,只是一个猜测,我也不知道如何编码。

由于

3 个答案:

答案 0 :(得分:9)

你要问的是一个统计问题,而不是一个编程问题。

您希望每个用户都有机会赢得他们所做的参赛作品数量(“积分”)。在现实世界中,这相当于将每个用户的名字放入帽子中,每次获得一个点,然后随机绘制一个名称。单张图画为获胜者命名。

通过编程,您可以选择一个介于0和所有用户的总分数减去1之间的随机数(如果您愿意,可以从1开始。但计算机使用零,这通常更容易)。然后,您遍历用户,将每个点的总数添加到运行总和中。当运行计数超过您选择的随机数时,您当前所在的用户就赢了。

想象一下,你有三个参赛者,名叫乔,鲍勃和爱丽丝:

Name  Points
------------
Joe   3
Bob   8
Alice 2

名称的顺序无关紧要,概率无论如何都会起作用。

您可以选择0到12之间的随机数(12 = 3 + 8 + 2-1)。在0-2,乔获胜(2 = 3-1)。在3-10,鲍勃获胜(10 = 8 + 3-1)。在11-12,爱丽丝获胜(12 = 3 + 8 + 2-1)。请注意,每个范围中包含的值的数量等于点的数量 - 因此,选择给定个体的几率是(个人的点数/总点数),这是您想要的逻辑。

你检查获胜者的方式就像我上面所说的那样 - 在零开始一个总和,然后加3.如果3>随机值,乔赢了。然后添加8。如果新11大于随机值,则Bob获胜。然后添加2.现在该数字大于您的随机值(因为13高于您可以生成的最大值)。

理论上,这可以在一个数据库中完成 - 但它并不是一个真正适合的任务。这是应用程序逻辑,我建议在PHP中使用它(SQL只是所有用户的基本SELECT,他们的点,也许是总点数。)

答案 1 :(得分:2)

为每个点创建一个临时表,每个成员都有一行。然后选择一个随机行。

这是我刚为我网站上的抽奖创建的存储过程。代码是从网上的不同帖子和mysql引用中挑选出来的:

CREATE PROCEDURE  `getWinner` ()
  BEGIN


 -- Declare '_val' variables to read in each record from the cursor
DECLARE memberID_val INT DEFAULT 0;
DECLARE points_val INT DEFAULT 0;

-- Declare variables used just for cursor and loop control
DECLARE done INT DEFAULT 0;
DECLARE loop_cntr INT DEFAULT 0;
DECLARE num_rows INT DEFAULT 0;

-- Declare the cursor
DECLARE member_cur CURSOR FOR
      SELECT  id, points FROM member;

-- Declare 'handlers' for exceptions
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

DROP TEMPORARY TABLE IF EXISTS `raffle_table`;
CREATE TEMPORARY TABLE  `raffle_table` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT, `memberID` int(11) DEFAULT '0'  ) ENGINE=MyISAM DEFAULT CHARSET=latin1;

OPEN member_cur;

REPEAT

  FETCH  member_cur  INTO   memberID_val,  points_val;

  IF NOT done THEN

   WHILE points_val > 0 DO

      INSERT INTO raffle_table (memberID) values (memberID_val);
      SET points_val = points_val - 1;

   END WHILE;

  END IF;

UNTIL done END REPEAT;
CLOSE member_cur;


SELECT memberID FROM `raffle_table` WHERE id >= (SELECT FLOOR( MAX(id) * RAND()) FROM `raffle_table` ) ORDER BY id LIMIT 1;

END $$

答案 2 :(得分:1)

用户及其点可以在2D数组中显示,如下所示(按用户点排序):

    P %.......
    o %.......
    i %%......
    n %%%.....
    t %%%%%...
    s %%%%%%%%
Users 0123456789

您尝试通过创建随机2d坐标来选择随机获胜者:(随机用户ID,0和最大用户点之间的随机用户点),并检查您是否“点击”某个点。非常伪代码:

$maxpoint = SELECT MAX(points) FROM users;

do{
  $random_user = see for example http://www.greggdev.com/web/articles.php?id=6
  $random_point = rand( 0, $maxpoints );
}while( $random_user->point >= $random_point ); // beware users with 0 point