从4个表中随机挑选

时间:2014-10-05 07:40:39

标签: php mysql sql random

我想出一个好头衔有点问题,但我现在要解释一下。

我正在建立一个在线游戏。我试图建立销毁武器的选择。

我有4种武器 - 攻击,防御,巡逻和间谍。 巡逻和间谍武器有3级武器,攻击和防御有15级。

我有一个表格,每个类别都有col。命名为w1,w2,w3,w4 ......和用户的ID。

我给出了每个等级点,所以w15例如值15分,w2值2分,我建立了一个函数来计算攻击者摧毁了多少分给防守者。

我被困的地方是如何随机挑选武器?

让我们说攻击者摧毁了100点武器。所以它可以是100种巡逻等级1的武器,或者25种武器,每种类别1种,或10种武器,排名10。 我需要在类别(攻击,防御,巡逻和间谍)之间以及武器(w1,w2,w3 ..)之间随机进行。另外我需要它在防守者拥有的武器数量的极限,他不能失去更多的武器。

非常感谢!!我知道我写了一个很长的问题

6 个答案:

答案 0 :(得分:2)

首先UNION这样你的四张桌子

SELECT * FROM (
  SELECT * FROM w1
  UNION
  SELECT * FROM w2
  UNION
  SELECT * FROM w3
  UNION
  SELECT * FROM w4
)

然后计算你的体重 - 并随机选择

... ORDER BY RAND() LIMIT 5;

答案 1 :(得分:2)

// randomly picks a number between 1 and 4
$randomWeapon = rand(1,4);

// Creates for ex. SELECT * FROM w1
$selectWeapon = mysqli($con, "SELECT * FROM w$randomWeapon"

答案 2 :(得分:1)

根据我的其他提示,这是一个应该可以解决问题的解决方案。

基本上你首先用他们的用户权重随机化所有的waepons。如果您在此处有NULL个值,则应取消选择它们。 LIMIT之后的巨大ORDER BY RAND()是必要的,因为我发现如果你没有在这里指定LIMIT,MySQL Optimizer将删除随机化。只要把它变得比整个桌子都要大。

其次,你用一个运行变量连续计算武器重量。

第三,你从整个连续列表中选择造成的伤害量。如果所需的伤害不完全匹配,您应该将其调整到一系列生命值。

-- 3. limit your sum to hitpoints
SELECT * FROM (
    -- 2. now sum weaponWeight
    SELECT weaponWeight, @prevWeight, @prevWeight:= weaponWeight + @prevWeight as cumulSum 
    FROM (
        -- 1. shuffle all waepons of a user to do the random pick
        SELECT weaponWeight FROM
        (
            -- attack
            SELECT w1 as weaponWeight FROM attack WHERE ID = 'myUserID'
            UNION
            SELECT w2 as weaponWeight FROM attack WHERE ID = 'myUserID'
            UNION
            ...
            UNION
            SELECT w15 as weaponWeight FROM attack WHERE ID = 'myUserID'

            -- defence
            UNION
            SELECT w1 as weaponWeight FROM defence WHERE ID = 'myUserID'
            UNION
            ...
            UNION
            SELECT w15 as weaponWeight FROM defence WHERE ID = 'myUserID'

            -- patrol
            UNION
            SELECT w1 as weaponWeight FROM patrol WHERE ID = 'myUserID'
            UNION
            SELECT w2 as weaponWeight FROM patrol WHERE ID = 'myUserID'
            UNION
            SELECT w3 as weaponWeight FROM patrol WHERE ID = 'myUserID'

            -- spy
            UNION
            SELECT w1 as weaponWeight FROM spy WHERE ID = 'myUserID'
            UNION
            SELECT w2 as weaponWeight FROM spy WHERE ID = 'myUserID'
            UNION
            SELECT w3 as weaponWeight FROM spy WHERE ID = 'myUserID'
        )
        ORDER BY RAND() 
        LIMIT 1000000000000 -- huge number here because Optimizer will remove random order otherwise
    ) as randomizedData,
    (SELECT @prevWeight := 0) as a 
) as sums
WHERE round(sums.cumulSum) = 100

答案 3 :(得分:1)

我认为这更像是一个逻辑问题而不是处理表格的技术问题。如果您先处理逻辑,那么您可以轻松地在桌面上执行所需的操作。我们只需要知道随机选择将使用(销毁)每个项目的数量。这是一个随机选择方法部分sudo-code / part php:

1. Query database for available items and their relative values.
2. Store information as a multi-dimensional Array
3. Shuffle the Array
 //in php 
    bool shuffle ( array $itemsArray() )
4. Iterate through each item in the array and add 1
   to a variable for that item if, we have not reached our
   limiting factors (amount available and cost vs remaining points).
   Do this until all available points are allotted to a variable.
 //in php
    $i = 0;   
    do {

      if ($itemsArray[$i][numAvail] > 0 &&         
         ($availiblePoints - $itemsArray[$i][cost] >= $itemsArray[$i][cost]){   
            $$itemsArray[$i]++
            //use of '$$' for variable variable  
            $availiblePoints-=$itemsArray[$i][cost];
      }
      else {
      countSkips++ 
     //need to keep track of how many items we skip
     //if $availiblePoints is not zero yet but skips is size of array then 
     //we are done and have leftover points that cant be used.
      }  
         $i++;
      if ($i > count($itemsArray)) { $i=0; };
      //start over if we have gone past the end of our Array

   } while ($availiblePoints > 0 && $countSkips < count($itemsArray) );
5.  Logic Done. Now use the new variables to perform action on tables

因为数组是随机洗牌的,所以无论我们有多少分数,我们的结果都是随机的。如果我们有100分,我们的随机数组中的第一项花费100分,或前4分需要25分;随机性无论如何都会完成它的工作。

这只是概念。代码可以改进一堆,例如我们保存的变量实际上应该在一个数组中,这样我们就可以在它对表执行操作时循环遍历它们。

答案 4 :(得分:0)

好的......我测试了一个表逻辑表。只需要组合(联合)你想要包含的所有东西。 (问题用php标记,所以这是一个php解决方案....)

<?php

$weapons = array(
      array('name'=>'knife',        'type'=>'A', 'weight'=>5),
      array('name'=>'sword',        'type'=>'A', 'weight'=>6),
      array('name'=>'axe',          'type'=>'A', 'weight'=>3),
      array('name'=>'handgun',      'type'=>'B', 'weight'=>7),
      array('name'=>'rifle',        'type'=>'B', 'weight'=>5),
      array('name'=>'cannon',       'type'=>'B', 'weight'=>2),
      array('name'=>'mustard gas',  'type'=>'C', 'weight'=>7),
      array('name'=>'agent orange', 'type'=>'C', 'weight'=>10),
      array('name'=>'lewisite',     'type'=>'C', 'weight'=>5),
      array('name'=>'mind',         'type'=>'D', 'weight'=>8),

      // must have at least one thing with one... for this to work. 
      // i can definitely work on a solution that doesn't require this 
      // but it would take me a minute to think about it... 

      array('name'=>'words',        'type'=>'D', 'weight'=>1),  
      array('name'=>'hands',        'type'=>'D', 'weight'=>2),
      array('name'=>'silent treatment','type'=>'D', 'weight'=>5),
   ); 

$total_destroyed = 100;

$return = get_weapons($weapons, $weapons, $total_destroyed);

print_r($return);


function get_weapons($orig_weapons, $in_weapons, $n) {
   // filter for only weapons w/ weight less than $n
   $in_weapons = array_filter($in_weapons, 
                             array(new LowerThanFilter($n), 
                             'isLowerOrEq'));

   $return = array(); 

   if ($n > 0) {
      if (empty($in_weapons)) { 
         $return = get_weapons($orig_weapons, $orig_weapons, $n); 
      }
      else { 
         $found_it = array();  
         for ($i = 0; $i < count($in_weapons); $i++) {
            $rand_index  = array_rand($in_weapons);
            $rand_weapon = $in_weapons[$rand_index];
            if ($rand_weapon['weight'] <= $n) { 
               break;
            }
         }    
         $max_ct = floor($n/$rand_weapon['weight']);

         $weapon_ct = rand(1,$max_ct);
         $amount    = $weapon_ct * $rand_weapon['weight'];

         unset($in_weapons[$rand_index]);

         $get_more = get_weapons($orig_weapons, $in_weapons, $n-$amount); 

         $return   = $get_more;
         $return[] = array_merge($rand_weapon, array(
                                 'count' =>$count, 
                                 'amount'=>$amount));  
      }  
   }  
   return $return;
} 

class LowerThanFilter {
   // http://stackoverflow.com/a/5483168/623952
   private $num; 
   function __construct($num) {
      $this->num = $num;
   } 
   function isLowerOrEq($i) {
      return $i['weight'] <= $this->num;
   }
}

?>

样本输出,可以轻松重新排列。索引值是指原始的$weapons数组索引。

Array
(
    [0] => Array
        (
            [name] => words
            [type] => D
            [weight] => 1
            [count] => 1
            [amount] => 1
        )

    [1] => Array
        (
            [name] => knife
            [type] => A
            [weight] => 5
            [count] => 2
            [amount] => 10
        )

    [2] => Array
        (
            [name] => sword
            [type] => A
            [weight] => 6
            [count] => 1
            [amount] => 6
        )

    [3] => Array
        (
            [name] => agent orange
            [type] => C
            [weight] => 10
            [count] => 2
            [amount] => 20
        )

    [4] => Array
        (
            [name] => mustard gas
            [type] => C
            [weight] => 7
            [count] => 9
            [amount] => 63
        )

)

答案 5 :(得分:0)

尝试类似:

    $attackWeapon = array( /* weapon info comes here  */   );
    $defenseWeapon = array( /* weapon info comes here  */);
    $patrolWeapon = array( /* weapon info comes here  */);
    $spyWeapon = array( /* weapon info comes here  */);


    $rdmWeapon = mt_rand(1,4);

    $attackLenght = count($attackWeapon);
    $rdmAttackWeapon = mt_rand(0, $attackLenght-1);

    $defenseLenght = count($defenseWeapon);
    $rdmDefenseWeapon = mt_rand(0, $defenseLenght-1);

    $patrolLenght = count($patrolWeapon);
    $rdmPatrolWeapon = mt_rand(0, $patrolLenght-1);

    $spyLenght = count($spyWeapon);
    $rdmSpyLenght = mt_rand(0, $spyLenght-1);


    If($rdmWeapon=1){
    $dropWeapon = "attack";
    echo  $rdmAttackWeapon;
    }
    else if($rdmWeapon=2){
      $dropWeapon = "defense";
    echo $rdmDefenseWeapon;
    }
    else if($rdmWeapon=3){
      $dropWeapon = "patrol";
      echo $rdmPatrolWeapon
    }
    else($rdmWeapon=4){
      $dropWeapon = "spy";
      echo $rdmSpyWeapon;
    }

这很简单,很傻,但适合我。