1

背景:我正在查询数据库以返回指定数量的怪物,这些怪物将在一个简单的基于网络的 RPG 中用于战斗。

问题:我有一个简单的 MYSQL 查询,其中包含一个 WHERE 子句来确定怪物的“级别”。在之前的函数中,我正在构建一个数组,其中包含应返回的相应怪物的级别;就像是:

$levels = Array( [0] => 3 [1] => 1 [2] => 1 ) 

所以在上面的数组中,Value对应的是level。所以我希望返回 3 个怪物——3 级、1 级和 1 级。

很简单。现在我想用以下内容查询 MYSQL 并大概使用循环进行 3 次查询以获得我的 3 个怪物;就像是:

$query = "SELECT *, CardHP as EncounterCardHP, CardAP as EncounterCardAP";
$query .= " FROM Cards";
$query .= " WHERE CardTypeId = 1 AND CardRarity = {$level}";
$query .= " ORDER BY RAND() LIMIT 1";

所以在上面的查询中,变量 {$level} 是前一个数组中的怪物等级。循环格式是我苦苦挣扎的地方。我正在尝试类似的东西:

while ($i = $levels) {
     $query = "SELECT *, CardHP as EncounterCardHP, CardAP as EncounterCardAP";
     $query .= " FROM Cards";
     $query .= " WHERE CardTypeId = 1 AND CardRarity = {$i}";
     $query .= " ORDER BY RAND() LIMIT 1";
 $result_set = mysql_query($query, $connection);
 confirm_query($result_set);
 return $result_set;    
}

我认为这很接近,但我不知道如何才能最终给我一个来自 MYSQL 的怪物数组。似乎在上面,我正在构建 3 个单独的数组?我需要使用 array_merge(),还是有更简单更优雅的方法来做到这一点?如果我得到所有相同级别的怪物,我可以简单地运行查询 1 次和 LIMIT 3,但我需要怪物与前面的数组显示的内容相对应。

有道理?帮助总是受到赞赏。

4

4 回答 4

2

我不完全理解你想要做什么,但这应该循环并让你得到你的数组:

foreach ($levels as $key => $value) {
    $query = "SELECT *, CardHP as EncounterCardHP, CardAP as EncounterCardAP FROM Cards WHERE WHERE CardTypeId = 1 AND CardRarity = {$value} ORDER BY RAND() LIMIT 1";
    $results = mysqli_query($connection, $query);
    while($row = $result->fetch_array(MYSQLI_BOTH)) {
        $monsters[$key]['HP'] = $row['CardHP'];
        //Add as needed
    }
}

它创建一个多维数组,其中第一个键与级别中的键相同,后续键是 SQL 查询的结果。

$monsters = array(
    [0] => array(
        ['HP'] => 10
        ['AP'] => 5
    )
    [1] => array(
        ['HP'] => 5
        ['AP'] => 7
    )
)

此外,mysqli 可能更适合您使用,因为它支持过程样式以及面向对象,并且大多数功能完全相同,尽管使用了 mysqli 前缀。

于 2013-01-14T07:23:04.247 回答
1

我想WHERE IN这就是你需要的。

$query = "SELECT *, CardHP as EncounterCardHP, CardAP as EncounterCardAP";
$query .= " FROM Cards";
$query .= " WHERE CardTypeId = 1 AND CardRarity IN (".implode(',', $levels).")";
$query .= " ORDER BY RAND() LIMIT 1";
于 2013-01-14T07:08:06.117 回答
0

实际上比我想象的要容易得多。也许我过度解释了这个问题。这就是我所做的。

1)一旦我返回了我的数组 $levels ,它看起来像这样:

$levels = Array( [0] => 3 [1] => 1 [2] => 2 ) 

2) 我创建了一个名为 $result_set 的空数组 2) 然后使用 foreach 循环遍历 $levels 数组,并使用 $levels 数组中的第一个 $level 运行查询。但是,我不是只返回 $result_set 并返回第一行,而是将第一行插入到我在步骤 2 中创建的空数组中。每次循环后,我将 MYSQL 中的新行插入到现在填充的 $result_set 数组中。

这是它最终的样子:

$result_set = array();
foreach ($levels as $level) {
    $query = "SELECT *, CardHP as EncounterCardHP, CardAP as EncounterCardAP";
    $query .= " FROM Cards";
    $query .= " WHERE CardTypeId = 1 AND CardRarity = {$level}";
    $query .= " ORDER BY RAND() LIMIT 1";
    $result = mysqli_query($query, $connection);
    $result_set[] = mysqli_fetch_array($result);    
    confirm_query($result_set);
}
return $result_set;     

我的 $result_set 现在有 3 个怪物,一个 3 级、1 级和 2 级,它们都是从数据库中为每个相应级别随机选择的。

感谢所有的帮助。

于 2013-01-16T05:22:39.543 回答
0

这是一种基于每个$levels元素生成随机绘制的怪物的单个结果集的安全方法。

这只需一次访问数据库,这是一种很好的做法。同时我应该提到它RAND()并不以其性能而闻名。如果您对随机性、加权随机化或同一结果集中没有重复的怪物有要求,您可能需要考虑替代策略。

$param_types = '';
foreach ($levels as $level) {
    $selects[] = "(SELECT CardName, CardHP, CardAP FROM Cards WHERE CardTypeId = 1 AND CardRarity = ? ORDER BY RAND() LIMIT 1)";
    $param_types .= 'i';
}

$conn = new mysqli('localhost', 'root', '', 'dbname');
$stmt = $conn->prepare(implode(' UNION ALL ', $selects));
$stmt->bind_param($param_types, ...$levels);
$stmt->execute();
$result = $stmt->get_result();
return $result->fetch_all(MYSQLI_ASSOC);

上面的片段与我的这个答案密切相关。

我准备了一个带有一些捏造数据的工作演示,以证明我的解决方案有效。

架构(MySQL v5.7):

CREATE TABLE `Cards` (
  id INT(11),
  CardName VARCHAR(255),
  CardTypeId INT(11),
  CardRarity INT(11),
  CardHP INT(11),
  CardAP INT(11)
);

INSERT INTO `Cards` VALUES
(1, 'Dracula',         2, 1,  500,  75),
(2, 'Gargamel',        1, 1,  200,  20),
(3, 'Rumplestiltskin', 1, 2,  175,  45),
(4, 'Megatron',        3, 3, 1000, 300),
(5, 'Smeagol',         1, 1,  225,  60),
(6, 'Cruella Deville', 4, 1,   95,  35),
(7, 'Thanos',          1, 3, 2575, 960),
(8, 'Stay Puft',       1, 3,  800, 255),
(9, 'Keyser Soze',     1, 3,  750, 300);

询问:

(SELECT CardName, CardHP, CardAP FROM Cards WHERE CardTypeId = 1 AND CardRarity = 3 ORDER BY RAND() LIMIT 1)
UNION ALL
(SELECT CardName, CardHP, CardAP FROM Cards WHERE CardTypeId = 1 AND CardRarity = 1 ORDER BY RAND() LIMIT 1)
UNION ALL
(SELECT CardName, CardHP, CardAP FROM Cards WHERE CardTypeId = 1 AND CardRarity = 1 ORDER BY RAND() LIMIT 1);

潜在结果集:

| CardName  | CardHP | CardAP |
| --------- | ------ | ------ |
| Stay Puft | 800    | 255    |
| Smeagol   | 225    | 60     |
| Gargamel  | 200    | 20     |

在 DB Fiddle 上查看

于 2019-06-22T14:17:11.140 回答