首页 > 解决方案 > 有没有一种简单的方法来操作 PHP 中的按位枚举?

问题描述

我正在为游戏(osu!)创建自定义用户配置文件,并且我正在尝试获取哪些“mods”已在“顶级游戏”中使用。API 提供了一个十进制数字,其中包含玩家在游戏中使用的每个模组。

例如:DoubleTime+Hidden 模组为 72,因为 DoubleTime 为 64 且隐藏为 8

$hidden = 8;
$doubletime = 64;
$hiddendoubletime = ($hidden|$doubletime);

例如,我想从 72 知道它的 8 和 64。甚至从 88 知道它是 8 和 16 和 64。

我正在考虑转换 88,例如二进制(01011000),然后检测所有“1”位置,因为每个“1”都给出一个 mod。

这里: 01011000 - 位置 4 的第一个“1”是隐藏模组,位置 5 的第二个“1”是 Hardrock 模组,最后,位置 7 的“1”是 DoubleTime 模组。

然后枚举如下:

enum Mods
{
    None           = 0,
    NoFail         = 1,
    Easy           = 2,
    TouchDevice    = 4,
    Hidden         = 8,
    HardRock       = 16,
    SuddenDeath    = 32,
    DoubleTime     = 64,
    Relax          = 128,
    HalfTime       = 256,
    Nightcore      = 512, // Only set along with DoubleTime. i.e: NC only gives 576
    Flashlight     = 1024,
    Autoplay       = 2048,
    SpunOut        = 4096,
    Relax2         = 8192,  // Autopilot
    Perfect        = 16384, // Only set along with SuddenDeath. i.e: PF only gives 16416  
    Key4           = 32768,
    Key5           = 65536,
    Key6           = 131072,
    Key7           = 262144,
    Key8           = 524288,
    FadeIn         = 1048576,
    Random         = 2097152,
    Cinema         = 4194304,
    Target         = 8388608,
    Key9           = 16777216,
    KeyCoop        = 33554432,
    Key1           = 67108864,
    Key3           = 134217728,
    Key2           = 268435456,
    ScoreV2        = 536870912,
    LastMod        = 1073741824,
}

如您所见,列表非常大,所以我不能只在 if() 条件下尝试每个 mods 组合。

标签: phpbit-manipulation

解决方案


我会做这样的事情......

<?php

$user_options = 88;

$no_options = array ( 'None' => 0 );

$game_options = array (
'NoFail' => 1, 
'Easy' => 2, 
'TouchDevice'=> 4, 
'Hidden' => 8, 
'HardRock' => 16, 
'SuddenDeath' => 32, 
'DoubleTime' => 64, 
'Relax' => 128, 
'HalfTime' => 256, 
'Nightcore' => 512, 
'Flashlight' => 1024, 
'Autoplay' => 2048, 
'SpunOut' => 4096, 
'Relax2' => 8192, 
'Perfect' => 16384,  
'Key4' => 32768, 
'Key5' => 65536, 
'Key6' => 131072, 
'Key7' => 262144, 
'Key8' => 524288, 
'FadeIn' => 1048576, 
'Random' => 2097152, 
'Cinema' => 4194304, 
'Target' => 8388608, 
'Key9' => 16777216, 
'KeyCoop' => 33554432, 
'Key1' => 67108864, 
'Key3' => 134217728, 
'Key2' => 268435456, 
'ScoreV2' => 536870912, 
'LastMod' => 1073741824
);

$filtered = array_filter ( $game_options, function ( $value ) use ( $user_options )
{
    return ( $value & $user_options ) == $value ? $value : NULL;
});

if ( empty ( $filtered ) )
{
    print_r ( $no_options );
}
else
{
    print_r ( $filtered );
}

?>

推荐阅读