我一直在学习C ++,潜入一个简单的2D游戏项目。我试图实现一组作弊,但我是字符串操作的新手。我确信有一种更优雅的方式来实现我想要的,而不是我的代码。
根据要求,stringBuffer
只是一个包含最后12个按下字符的字符串。我在前面加了它,因为它在最后调整后调整大小,因此我的作弊必须向后。我非常喜欢字符串操作,我知道这里有些问题,我为什么要求它被查看并可能改进。
//The following code is in my keyPressed function
cheatBuffer = (char)key + cheatBuffer;
cheatBuffer.resize(12);
string tempBuffer;
string cheats[3] = {"1taehc","2taehc","3taehc"};
for(int i = 0;i < 3;i++){
tempBuffer = cheatBuffer;
tempBuffer.resize(cheats[i].size());
if(cheats[i] == tempBuffer){
switch(i){
case 1:
//activate cheat 1
break;
case 2:
//active cheat 2
break;
case 3:
//active cheat 3
break;
}
}
}
代码分别是“cheat1”,“cheat2”和“cheat3”。我不禁想到这可能会好得多。任何见解将不胜感激。
答案 0 :(得分:5)
您可能需要考虑使用:
std::map<std::string, std::function<void ()>>
(如果你可以使用C ++ 0x)
std::map<std::string, std::tr1::function<void ()>>
(如果你可以使用TR1)
std::map<std::string, boost::function<void ()>>
(如果你可以使用Boost)
(当然,功能的签名可以不同)
使用C ++ 0x的示例
#include <map>
#include <functional>
#include <string>
#include <iostream>
typedef std::map<std::string, std::function<void ()>> cheat_map;
inline void cheat1()
{
std::cout << "cheat 1 used!" << std::endl;
}
inline void cheat2()
{
std::cout << "cheat 2 used!" << std::endl;
}
int main()
{
cheat_map myCheats;
myCheats.insert(std::pair<std::string, std::function<void ()>>("cheat1", std::function<void ()>(cheat1)));
myCheats.insert(std::pair<std::string, std::function<void ()>>("cheat2", std::function<void ()>(cheat2)));
std::string buffer;
while (std::getline(std::cin, buffer)) {
if (!std::cin.good()) {
break;
}
cheat_map::iterator itr = myCheats.find(buffer);
if (itr != myCheats.end()) {
myCheats[buffer]();
}
}
}
输入:
notourcheat
cheat1
cheat2
cheat1
输出:
cheat 1 used!
cheat 2 used!
cheat 1 used!
答案 1 :(得分:2)
我会将字符串存储在trie中:
http://en.wikipedia.org/wiki/Trie
(在维基百科文章中也有链接到C ++实现)。
在特里的叶子中,您可以添加有关作弊的其他数据。
当您查找字符串时,您可以使用作弊码检查字符串是否包含在trie中。如果是,则获取附加数据(例如,指向执行您想要执行的操作的函数的函数指针;或更多面向对象:指向类实例的指针,当您调用其成员函数之一时,会执行“作弊”东西“)。
答案 2 :(得分:2)
可以通过多种方式改进此代码。
static const std::string const foo[] = { "1taehc", "2taehc", "3taehc" };
因此,不必每次都在“KeyPressed”处理程序中分配它们。
case
声明我认为促进switch
的所有额外逻辑都不是一个好主意。这样的事情怎么样:
const int CHEAT_ONE = 1;
const int CHEAT_TWO = 2;
const int CHEAT_THREE = 3;
static const std::pair<std::string, int> const foo[] = {
std::make_pair("1taehc", CHEAT_ONE),
std::make_pair("2taehc", CHEAT_TWO),
std::make_pair("3taehc", CHEAT_THREE),
};
通过这种方式,您可以获得一个整数,您可以将其用作每个作弊码的大小写标签。
您希望能够搜索已轻松激活的作弊码。让我们分解std::pair
个实例并改为使用std::map
。
const int CHEAT_ONE = 1;
const int CHEAT_TWO = 2;
const int CHEAT_THREE = 3;
std::pair<std::string, int> cheatcodes[] = {
std::make_pair("1taehc", CHEAT_ONE),
std::make_pair("2taehc", CHEAT_TWO),
std::make_pair("3taehc", CHEAT_THREE),
};
std::map<std::string, int> cheatmap(
cheatcodes, cheatcodes + sizeof (cheatcodes) / sizeof (cheatcodes[0]));
现在,假设candidate
是您的按键缓冲区,您可以执行
auto pair = cheatmap.find(candidate);
if (pair != cheatmap.end()) {
switch(pair->second) {
case CHEAT_ONE:
case CHEAT_TWO:
case CHEAT_THREE:
}
}
答案 3 :(得分:1)
我会这样做:当先按某个特定按钮时,例如输入,它会开始填充cheatBuffer,并且在缓冲区末尾填充一个字符后,它将使用该缓冲区来检查是否它的值存在于std :: map中。当该值存在时,它将执行一个函数,该指针存储在std :: map。
中答案 4 :(得分:1)
这可能是一种过度杀伤和太多工作,但您可以创建一个有限状态机来处理您的键输入,存储您当前的状态而不是存储密钥历史记录。您的起始状态0表示没有按下适用的键。 'c'会让你进入状态1,其中'h'会将你带到状态2,'c'会让你保持在状态1,而其他任何东西都会让你回到0.所以在给定的按键上你打开当前状态,并在其中打开提供的字符,以查看您转换到的状态。如果它是最终状态,则执行作弊并转换回0。