gpt4 book ai didi

C++ - 如何提取字符串中的有效字符串?

转载 作者:太空狗 更新时间:2023-10-29 21:09:15 24 4
gpt4 key购买 nike

问题:我正在尝试使用 C++ 从游戏名称中提取古代防御 (DotA) 的有效游戏模式。

详细信息:

  • 游戏名称最长不能超过 31 个字符
  • 共有三种游戏模式类别:主要、次要和其他
    • 只能选择一种主要游戏模式
    • 某些主要游戏模式与某些次要游戏模式不兼容
    • 某些次要游戏模式与其他次要游戏模式不兼容
    • 杂项游戏模式可以与所有其他游戏模式相结合

这里是各种游戏模式的列表,图表显示了每种模式与哪些次要模式兼容(X 表示不兼容):

// Only 1 primary allowed
static char *Primary[] = {
// Compatible with > | dm | rv | mm | du | sh | aa | ai | as | id | em | np | sc | om | nt | nm | nb | ro | mo | sp |
"ap", // All Pick | | | | | | | | | | | | | | | | | | | |
"ar", // All Random | | X | | | | | | | | | | | | | | | | | |
"tr", // Team Random | X | X | | | | | | | | | | | | | | | | | |
"mr", // Mode Random | X | X | | | X | X | X | X | | | | | | | | | X | X | |
"lm", // League Mode | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X | |
"rd", // Random Draft | X | X | X | | X | X | X | X | | | | | | | | | X | X | |
"vr", // Vote Random | X | X | X | | X | X | X | X | | | | | | | | | X | X | |
"el", // Extended League | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X | |
"sd", // Single Draft | X | X | X | | X | X | X | X | | | | | | | | | X | X | |
"cm", // Captains Mode | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X |
"cd" // Captains Draft | X | X | X | | X | X | X | X | | | | | | | | | X | X | |
};

static char *Secondary[] = {
// Compatible with > | dm | rv | mm | du | sh | aa | ai | as | id | em | np | sc | om | nt | nm | nb | ro | mo | sp |
"dm", // Death Match | | X | X | | X | X | X | X | | | | | | | | | X | X | |
"rv", // Reverse Mode | X | | | | X | | | | | | | | | | | | | | |
"mm", // Mirror Match | X | | | | X | | | | | | | | | | | | | | |
"du", // Duplicate Mode | | | | | | | | | | | | | | | | | | | |
"sh", // Same Hero | X | X | X | | | | | | | | | | | | | | | | |
"aa", // All Agility | X | | | | | | X | X | | | | | | | | | | | |
"ai", // All Intelligence | X | | | | | X | | X | | | | | | | | | | | |
"as", // All Strength | X | | | | | X | X | | | | | | | | | | | | |
"id", // Item Drop | | | | | | | | | | | | | | | | | | | |
"em", // Easy Mode | | | | | | | | | | | | | | | | | | | |
"np", // No Powerups | | | | | | | | | | | | | | | | | | | |
"sc", // Super Creeps | | | | | | | | | | | | | | | | | | | |
"om", // Only Mid | | | | | | | | | | | | | | | | | | | |
"nt", // No Top | | | | | | | | | | | | | | | | | | | |
"nm", // No Middle | | | | | | | | | | | | | | | | | | | |
"nb", // No Bottom | | | | | | | | | | | | | | | | | | | |
"ro", // Range Only | X | | | | | | | | | | | | | | | | | X | |
"mo", // Melee Only | X | | | | | | | | | | | | | | | | X | | |
"sp" // Shuffle Players | | | | | | | | | | | | | | | | | | | |
};

// These options are always available
static char *Misc[] = {
"ns", // No Swap
"nr", // No Repick
"ts", // Terrain Snow
"pm", // Pooling Mode
"oi", // Observer Info
"mi", // Mini Heroes
"fr", // Fast Respawn
"so" // Switch On
};

示例:这是一些示例输入,具有所需的输出:

“DotA v6.60 -RDSOSP USA/CA LC!” -> “rdsosp”

“DOTA AREMDM 美国 LC”->“aremdm”

“DotA v6.60 -ApEmDuSpId USA BL”->“apemduspid”

注意:解决方案不一定必须提供实际代码、伪代码,甚至只是对您将如何处理它的解释也是可以接受和首选的。此外,该解决方案需要足够灵活,以便我可以相当轻松地添加另一种游戏模式。还可以安全地假设在游戏名称中,游戏模式将始终以主要游戏模式开头。


结果:

#include <cstdarg>
#include <algorithm>
#include <iostream>
#include <string>
#include <sstream>
#include <map>
#include <vector>

std::map<std::string, std::vector<std::string> > ModeCompatibilityMap;

static const unsigned int PrimaryModesCount = 11;
static char *PrimaryModes[] = {
"ap", "ar", "tr", "mr", "lm", "rd", "vr", "el", "sd", "cm", "cd"
};

static const unsigned int SecondaryModesCounts = 19;
static char *SecondaryModes[] = {
"dm", "rv", "mm", "du", "sh", "aa", "ai", "as", "id", "em", "np",
"sc", "om", "nt", "nm", "nb", "ro", "mo", "sp"
};

static const unsigned int MiscModesCount = 8;
static char *MiscModes[] = {
"ns", "nr", "ts", "pm", "oi", "mi", "fr", "so"
};

std::vector<std::string> Vectorize( int count, ... ) {
std::vector<std::string> result;

va_list vl;
va_start( vl, count );

for ( int i = 0; i < count; ++i ) {
char *buffer = va_arg( vl, char * );
result.push_back( buffer );
}

va_end( vl );

return result;
}

void InitializeModeCompatibilityMap() {
// Primary
ModeCompatibilityMap["ar"] = Vectorize( 1, "rv" );
ModeCompatibilityMap["tr"] = Vectorize( 2, "dm", "rv" );
ModeCompatibilityMap["mr"] = Vectorize( 8, "dm", "rv", "sh", "aa", "ai", "as", "ro", "mo" );
ModeCompatibilityMap["lm"] = Vectorize( 18, "dm", "rv", "mm", "du", "sh", "aa", "ai", "as", "id", "em", "np", "sc", "om", "nt", "nm", "nb", "ro", "mo" );
ModeCompatibilityMap["rd"] = Vectorize( 9, "dm", "rv", "mm", "sh", "aa", "ai", "as", "ro", "mo" );
ModeCompatibilityMap["vr"] = Vectorize( 9, "dm", "rv", "mm", "sh", "aa", "ai", "as", "ro", "mo" );
ModeCompatibilityMap["el"] = Vectorize( 18, "dm", "rv", "mm", "du", "sh", "aa", "ai", "as", "id", "em", "np", "sc", "om", "nt", "nm", "nb", "ro", "mo" );
ModeCompatibilityMap["sd"] = Vectorize( 9, "dm", "rv", "mm", "sh", "aa", "ai", "as", "ro", "mo" );
ModeCompatibilityMap["cm"] = Vectorize( 19, "dm", "rv", "mm", "du", "sh", "aa", "ai", "as", "id", "em", "np", "sc", "om", "nt", "nm", "nb", "ro", "mo", "sp" );
ModeCompatibilityMap["cd"] = Vectorize( 9, "dm", "rv", "mm", "sh", "aa", "ai", "as", "ro", "mo" );
// Secondary
ModeCompatibilityMap["dm"] = Vectorize( 8, "rv", "mm", "sh", "aa", "ai", "as", "ro", "mo" );
ModeCompatibilityMap["rv"] = Vectorize( 2, "dm", "sh" );
ModeCompatibilityMap["mm"] = Vectorize( 2, "dm", "sh" );
ModeCompatibilityMap["sh"] = Vectorize( 3, "dm", "rv", "mm" );
ModeCompatibilityMap["aa"] = Vectorize( 3, "dm", "ai", "as" );
ModeCompatibilityMap["ai"] = Vectorize( 3, "dm", "aa", "as" );
ModeCompatibilityMap["as"] = Vectorize( 3, "dm", "aa", "ai" );
ModeCompatibilityMap["ro"] = Vectorize( 2, "dm", "mo" );
ModeCompatibilityMap["mo"] = Vectorize( 2, "dm", "ro" );
}

std::vector<std::string> Tokenize( const std::string &string ) {
std::vector<std::string> tokens;
std::string token;
std::stringstream ss( string );

while ( ss >> token ) {
tokens.push_back( token );
}

return tokens;
}

void SanitizeString( std::string &in ) {
std::transform( in.begin(), in.end(), in.begin(), tolower );

for ( size_t i = 0; i < in.size(); ++i ) {
if ( in[i] < 'a' || in[i] > 'z' ) {
in.erase( i--, 1 );
}
}
}

std::vector<std::string> SplitString( const std::string &in, int count ) {
std::vector<std::string> result;

if ( in.length() % count != 0 ) {
return result;
}

for ( std::string::const_iterator i = in.begin(); i != in.end(); i += count ) {
result.push_back( std::string( i, i + count ) );
}

return result;
}

bool IsPrimaryGameMode( const std::string &in ) {
for ( int i = 0; i < PrimaryModesCount; ++i ) {
if ( strcmp( PrimaryModes[i], in.c_str() ) == 0 ) {
return true;
}
}

return false;
}

bool IsSecondaryGameMode( const std::string &in ) {
for ( int i = 0; i < SecondaryModesCounts; ++i ) {
if ( strcmp( SecondaryModes[i], in.c_str() ) == 0 ) {
return true;
}
}

return false;
}

bool IsMiscGameMode( const std::string &in ) {
for ( int i = 0; i < MiscModesCount; ++i ) {
if ( strcmp( MiscModes[i], in.c_str() ) == 0 ) {
return true;
}
}

return false;
}

bool IsValidGameMode( std::string in, std::string &out ) {
// 1. Strip all non-letters from the string and convert it to lower-case
SanitizeString( in );

// 2. Confirm that it is a multiple of 2
if ( in.length() == 0 || in.length() % 2 != 0 ) {
return false;
}

// 3. Split the string further into strings of 2 characters
std::vector<std::string> modes = SplitString( in, 2 );

// 4. Verify that each game mode is a valid game mode and is compatible with the others
bool primaryModeSet = false;

for ( size_t i = 0; i < modes.size(); ++i ) {
if ( IsPrimaryGameMode( modes[i] ) || IsSecondaryGameMode( modes[i] ) ) {
if ( IsPrimaryGameMode( modes[i] ) ) {
if ( primaryModeSet ) {
return false;
}

primaryModeSet = true;
}

if ( ModeCompatibilityMap.count( modes[i] ) > 0 ) {
std::vector<std::string> badModes = ModeCompatibilityMap[modes[i]];

for ( size_t j = 0; j < badModes.size(); ++j ) {
for ( size_t k = 0; k < modes.size(); ++k ) {
if ( badModes[j] == modes[k] ) {
return false;
}
}
}
}
} else if ( !IsMiscGameMode( modes[i] ) ) {
return false;
}
}

// 5. Assign the output variable with the game mode and return true
out = in;

return true;
}

std::string ExtractGameMode( const std::string &gameName ) {
std::vector<std::string> tokens = Tokenize( gameName );

std::string gameMode;

for ( size_t i = 0; i < tokens.size(); ++i ) {
if ( IsValidGameMode( tokens[i], gameMode ) ) {
return gameMode;
}
}

return "";
}

int main( int argc, char *argv[] ) {
InitializeModeCompatibilityMap();

std::string gameName = "DotA v6.60 -RDEM USA/CA LC";
std::string gameMode = ExtractGameMode( gameName );

std::cout << "Name: " << gameName << std::endl;
std::cout << "Mode: " << gameMode << std::endl;

return 0;
}

输出:

Name: DotA v6.60 -RDEM USA/CA LC

Mode: rdem


如果有人想查看此代码并让我知道他们会更改什么,我们将不胜感激。

谢谢。

最佳答案

创建 bool 数组来复制您放入注释中的表格。除了用“true”或“false”代替“X”或空白(所以“true”表示模式组合有效,“false”表示无效)。

使用此表查找组合是否有效:

 bool IsSecondaryValidWithPrimary(unsigned int primaryIndex, unsigned int secondaryIndex)
{
static bool secondaryValidWithPrimary[numPrimaryModes][numSecondaryModes] = {...}

if (primaryIndex < numPrimaryModes && secondaryIndex < numSecondaryModes)
{
return secondaryValidWithPrimary[primaryIndex][secondaryIndex]
}
else
{
//... this should never happen, throw your favorite exception
}
}

当然,这需要您将每个 2 个字符的字符串转换为要测试的正确数组索引。遍历所有可能的组合并检查其是否有效。我怀疑您是否真的关心此设置中的性能,所以这应该能很好地工作。

对其他有效性检查(次要与另一个次要)或您具有兼容性规则的任何其他模式组合执行相同的操作。

关于C++ - 如何提取字符串中的有效字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/986400/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com