php项目统计地面对抗谁胜出?

wen PHP项目 4

本文目录导读:

php项目统计地面对抗谁胜出?

  1. 第一步:数据库设计(假设使用 MySQL)
  2. 第二步:PHP 统计业务逻辑(核心代码)
  3. 第三步:进阶场景(联盟/军团之间的对抗)
  4. 第四步:优化与扩展建议

在PHP项目中做“地面对抗”(通常指地面战斗/地面战)的胜负统计,并没有一个固定模板,因为“谁胜出”取决于你的业务逻辑(是PVE打怪、PVP玩家对战,还是模拟战争策略)。

但如果你是想实现一个“统计某一方(如玩家阵营 vs 敌方阵营)在地面战斗中的胜率”的功能,核心在于数据记录聚合查询

以下给你提供一套完整的实现思路和代码示例,覆盖从数据库设计到PHP输出统计结果的完整流程。


第一步:数据库设计(假设使用 MySQL)

你至少需要一张战斗记录表,记录每次地面战斗的结果。

CREATE TABLE `ground_battles` (
  `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  `battle_time` DATETIME NOT NULL COMMENT '战斗发生时间',
  `map_name` VARCHAR(50) DEFAULT NULL COMMENT '地图名称(可选)',
  -- 攻击方
  `attacker_type` TINYINT NOT NULL COMMENT '类型:1=玩家, 2=NPC/怪物, 3=联盟A, 4=联盟B',
  `attacker_id` INT UNSIGNED NOT NULL COMMENT '攻击方ID(玩家ID或军团ID)',
  `attacker_name` VARCHAR(100) DEFAULT NULL COMMENT '攻击方名称(冗余存储)',
  -- 防守方
  `defender_type` TINYINT NOT NULL,
  `defender_id` INT UNSIGNED NOT NULL,
  `defender_name` VARCHAR(100) DEFAULT NULL,
  -- 结果
  `winner` TINYINT NOT NULL COMMENT '胜者:1=攻击方, 2=防守方, 3=平局',
  `damage_dealt` INT UNSIGNED DEFAULT 0 COMMENT '攻击方输出伤害',
  `damage_taken` INT UNSIGNED DEFAULT 0 COMMENT '攻击方承受伤害',
  INDEX idx_attacker (attacker_type, attacker_id),
  INDEX idx_defender (defender_type, defender_id),
  INDEX idx_time (battle_time)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

第二步:PHP 统计业务逻辑(核心代码)

假设你需要统计“玩家阵营”作为攻击方时,在地面对抗中的胜率。

<?php
/**
 * 统计地面对抗胜负
 * 场景:统计指定玩家(或阵营)作为攻击方时的胜率
 *
 * @param PDO $pdo       数据库连接
 * @param int $playerId  玩家ID
 * @return array
 */
function getGroundBattleStats(PDO $pdo, int $playerId): array
{
    // 1. 基础统计:总场次、胜场、负场、平局
    $sql = "
        SELECT 
            COUNT(*) AS total_battles,
            SUM(CASE WHEN winner = 1 THEN 1 ELSE 0 END) AS wins,
            SUM(CASE WHEN winner = 2 THEN 1 ELSE 0 END) AS losses,
            SUM(CASE WHEN winner = 3 THEN 1 ELSE 0 END) AS draws
        FROM ground_battles
        WHERE attacker_type = 1  -- 1代表玩家
          AND attacker_id = :playerId
    ";
    $stmt = $pdo->prepare($sql);
    $stmt->execute([':playerId' => $playerId]);
    $stats = $stmt->fetch(PDO::FETCH_ASSOC);
    // 2. 防止除以零,计算胜率(平局通常不计入胜率,或单独统计)
    $totalBattles = (int)($stats['total_battles'] ?? 0);
    $wins = (int)($stats['wins'] ?? 0);
    $losses = (int)($stats['losses'] ?? 0);
    $draws = (int)($stats['draws'] ?? 0);
    // 胜率计算方式:胜场 / (胜场+负场) * 100%(平局不算胜率分母)
    $decisiveBattles = $wins + $losses;
    $winRate = $decisiveBattles > 0 
        ? round(($wins / $decisiveBattles) * 100, 2) 
        : 0.0;
    // 3. 如果你想看“最近7天”的趋势,可以加时间筛选
    // WHERE battle_time >= DATE_SUB(NOW(), INTERVAL 7 DAY)
    return [
        'player_id'        => $playerId,
        'total_battles'    => $totalBattles,
        'wins'             => $wins,
        'losses'           => $losses,
        'draws'            => $draws,
        'win_rate'         => $winRate,   // 百分比,如 66.67
        'lose_rate'        => $decisiveBattles > 0 ? round(($losses / $decisiveBattles) * 100, 2) : 0.0,
        'last_updated'     => date('Y-m-d H:i:s'),
    ];
}
// 使用示例
// $pdo = new PDO(...);
// $result = getGroundBattleStats($pdo, 1001);
// echo json_encode($result);

第三步:进阶场景(联盟/军团之间的对抗)

如果你的项目是联盟战争(联盟A vs 联盟B),你需要统计的是对抗胜率(A赢了B几次,B赢了A几次)。

/**
 * 统计两个阵营(联盟)之间的地面对抗胜负
 *
 * @param PDO $pdo
 * @param int $allianceAId
 * @param int $allianceBId
 * @return array
 */
function getAllianceVsAllianceStats(PDO $pdo, int $allianceAId, int $allianceBId): array
{
    // 情况1:A攻击B,且A胜
    $a_win = 0;
    $b_win = 0;
    $sql = "
        SELECT 
            SUM(CASE 
                WHEN attacker_id = :aId AND defender_id = :bId AND winner = 1 THEN 1 
                WHEN attacker_id = :bId AND defender_id = :aId AND winner = 2 THEN 1 
                ELSE 0 END
            ) AS a_wins,
            SUM(CASE 
                WHEN attacker_id = :bId AND defender_id = :aId AND winner = 1 THEN 1 
                WHEN attacker_id = :aId AND defender_id = :bId AND winner = 2 THEN 1 
                ELSE 0 END
            ) AS b_wins
        FROM ground_battles
        WHERE (attacker_id = :aId AND defender_id = :bId)
           OR (attacker_id = :bId AND defender_id = :aId)
    ";
    $stmt = $pdo->prepare($sql);
    $stmt->execute([
        ':aId' => $allianceAId,
        ':bId' => $allianceBId,
    ]);
    $result = $stmt->fetch(PDO::FETCH_ASSOC);
    $a_wins = (int)$result['a_wins'];
    $b_wins = (int)$result['b_wins'];
    $total = $a_wins + $b_wins;
    return [
        'alliance_a_id' => $allianceAId,
        'alliance_b_id' => $allianceBId,
        'a_wins'        => $a_wins,
        'b_wins'        => $b_wins,
        'total_battles' => $total,
        'a_win_rate'    => $total > 0 ? round(($a_wins / $total) * 100, 2) : 0,
        'b_win_rate'    => $total > 0 ? round(($b_wins / $total) * 100, 2) : 0,
    ];
}

第四步:优化与扩展建议

  1. 缓存(Redis/Memcached):胜率统计如果实时计算且数据量大,会很消耗DB,建议把统计结果缓存起来,比如每5分钟刷新一次。

    $cacheKey = "ground_battle_stats:" . $playerId;
    $stats = $redis->get($cacheKey);
    if (!$stats) {
        $stats = getGroundBattleStats($pdo, $playerId);
        $redis->setex($cacheKey, 300, json_encode($stats)); // 5分钟过期
    }
  2. 分页与历史追踪:如果要做“历史战绩”页面,需要分页查询ground_battles表,并展示时间、对手、胜负图标。

  3. 存储过程或事件调度:如果项目很大,可以用MySQL的EVENT每天凌晨跑一次统计,存入player_battle_summary表,避免实时计算。

  4. “地面对抗”的判定:如果你的项目有“空中战”和“地面战”之分,记得在查询条件里加上battle_type = 'ground'字段,否则统计会包含其他类型的战斗。


  • 核心表:建一张ground_battles表,用winner字段(1=攻胜,2=守胜)来判定胜负。
  • 核心统计:用COUNTSUM(CASE WHEN...)聚合统计,避免使用GROUP BY导致全表扫描。
  • 输出:返回JSON给前端,展示胜率、总场次、胜负场数等。

如果你的业务是实时榜单(比如全服对战胜率排名),可以在此基础上用GROUP BY attacker_id ORDER BY win_rate DESC LIMIT 10来实现。

如果你需要更具体的场景(比如按兵种、按地图),告诉我,我再细化!

抱歉,评论功能暂时关闭!