Unity项目中字符过滤

射击游戏项目开发笔记 (五)

字符屏蔽似乎是在我朝才有的东西.这屏蔽那屏蔽的,干脆彻底把Internet变成Local Area Network得了(虽然现在对大部分人来说已经是Local Area Network了).如果说我有什么职业梦想的话,The Great Wall崩塌估计是我唯一的梦想了.

在目前国内游戏的字符屏蔽中,主要是分为:聊天屏蔽(过滤词语) 和 命名屏蔽(过滤词语+过滤特殊标点符号)

过滤词语

首先看以下趣图:

图的出处无法考量,但是之所以引发这种笑话 就是字符过滤做得不够严谨导致的.程序员把所有带 的字符都替换成了其他字符,这里是星号.所以过滤词语需要引入列表分级的方式.由于汉语的特殊性,使得其中一部分词语,会成为另外一部分词语中的组成部分。例如:“西藏”、属于屏蔽列表范围;但“东躲西藏”这些成语里虽然里面包含了“西藏”字符,却是完全不同的含义。针对这种状况,屏蔽列表分为两级。

列表分级:

第一层为屏蔽字列表。当玩家输入的文字中,不属于第一层不过滤列表,又属于过滤列表时,则判定为非法字符,需重新输入。
第二层为不过滤列表。当玩家输入的文字中,出现不过滤列表中的字符,则,该列表中对应的文字将不属于屏蔽字。
例如上图 属于屏蔽字列表,但粮草先行的意思于单字完全是两种意思(汉字真博大精深),所以粮草先行需要加入不过滤列表.

词语过滤的主要代码如下

// C#
m_DictSensitiveWord.add("西藏","东躲西藏;西藏东躲");
string str = "我在西藏东躲西藏";
bool done = true;
int nSize = str.Length;
foreach (KeyValuePair p in m_DictSensitiveWord)
{
    int nIndex1 = str.IndexOf(p.Key);
    int nKeySize = p.Key.Length;
    int nNextIndex = 0;
    string[] sArray = null;
    while (-1 != nIndex1 && nIndex1 < nSize && true == done)
    {
        done = false;

        if (null == p.Value)
        {
            break;
        }

        if (null == sArray)
        {
            sArray = p.Value.Split(';');
        }

        for (int i = 0; i < sArray.Length; ++i )
        {
            int nIndex2 = str.IndexOf(sArray[i], nNextIndex);
            if (-1 == nIndex2)
            {
                continue;
            }
            int nValueSize = sArray[i].Length;
            if (nIndex2 <= nIndex1 && (nIndex1 + nKeySize <= nIndex2 + nValueSize))
            {
                nNextIndex = nValueSize - sArray[i].IndexOf(p.Key);
                done = true;
                break;
            }
        }
        nNextIndex += nIndex1;
        nIndex1 = str.IndexOf(p.Key, nIndex1 + nKeySize);
    }

    if (!done)
    {
        break;
    }
}

if(done)
{
    // 有敏感字符...
}

测试一下效果:

过滤标点

在游戏中玩家命名,各种工会命名是不允许出现标点符号的,所以在这种情况下需要进行标点符号过滤.标点过滤就非常简单了.这里不详细描述.

1 评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注