[英]C++ Removing vector elements with find_first_not_of(char*)
我正在做一个国际象棋游戏,试图向向量添加有效位置。 我正在处理的特定部分是骑士,而我已经硬编码的某些位置不在板上,这取决于骑士在板上的位置。 我的坐标系将AH用于行,将0-8用于列。
我已经定义了一个有效字符(AH和0-8)的字符数组,并且正在使用find_first_not_of进行标识,并删除无效的坐标对。 例如:
有效:A1
无效:?3-删除此
问题:为什么我的函数会删除一些无效且不适合该模式的坐标对,而不会删除其他坐标对? 例如,使用位置A2作为输入,可以成功删除@ 4和@ 0。 然而,剩余的可用位置是C3,C1,B4,θ3,B0,θ1。
如果输入为H2,则F3,F1,G0,G4是可用位置,并且J3,J1,I4,I0被成功删除,仅给出了有效位置的期望结果。
问题:给定相同的删除无效头寸的方法,我的输出有时是正确的,而其他时候是不正确的。
父类Piece.cpp:
char Piece::valids[16] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'0', '1', '2', '3', '4', '5', '6', '7'
};
void Piece::removeInvalids(vector<string>& v)
{
for (short i = 0; i < v.size(); i++)
{
string s = v.at(i);
size_t found = s.find_first_not_of(valids);
if (found != string::npos)
{
cout << v.at(i) << endl;
swap(v.at(i), v.back());
v.pop_back();
}
}
}
子类别Knight.h:
vector<string> getAvailPositions(Piece **all)
{
vector<string> v;
stringstream ss;
ss << static_cast<char>(position[0] + 2)
<< static_cast<char>(position[1] + 1);
v.push_back(ss.str());
stringstream ss2;
ss2 << static_cast<char>(position[0] + 2)
<< static_cast<char>(position[1] - 1);
v.push_back(ss2.str());
stringstream ss3;
ss3 << static_cast<char>(position[0] + 1)
<< static_cast<char>(position[1] + 2);
v.push_back(ss3.str());
stringstream ss4;
ss4 << static_cast<char>(position[0] - 1)
<< static_cast<char>(position[1] + 2);
v.push_back(ss4.str());
stringstream ss5;
ss5 << static_cast<char>(position[0] + 1)
<< static_cast<char>(position[1] - 2);
v.push_back(ss5.str());
stringstream ss6;
ss6 << static_cast<char>(position[0] - 1)
<< static_cast<char>(position[1] - 2);
v.push_back(ss6.str());
stringstream ss7;
ss7 << static_cast<char>(position[0] - 2)
<< static_cast<char>(position[1] - 1);
v.push_back(ss7.str());
stringstream ss8;
ss8 << static_cast<char>(position[0] - 2)
<< static_cast<char>(position[1] + 1);
v.push_back(ss8.str());
removeInvalids(v);
return v;
}
请让我知道是否需要对此职位进行任何更改,以便更好地为我提供帮助,谢谢。
您应该重新考虑您的设计-它是复杂且低效的。 这个怎么样:
typedef std::array<char, 2> Position;
vector<Position> Knight::getAvailPositions() const
{
vector<Position> v;
v.reserve(8);
for (char a : {2, -2}) {
for (char b : {1, -1}) {
v.emplace_back(position[0] + a, position[1] + b);
v.emplace_back(position[0] + b, position[1] + a);
}
}
removeInvalids(v);
return v;
}
bool invalid(Position p)
{
return p[0] < 'A' || p[0] > 'H' || p[1] < '0' || p[1] > '7';
}
void Piece::removeInvalids(vector<Position>& v)
{
v.erase(std::remove_if(v.begin(), v.end(), invalid), v.end());
}
这避免了隐藏在所有这些字符串和字符串流内部的绝对大量的动态内存分配。 现在,每个getAvailPositions()
调用只有一个。 加上更少的代码。
有时它只是正确的原因是因为您将当前向量元素与结尾的元素交换,然后继续进行下一个元素。 如果向量结尾处的元素无效,则只是将一个无效值滑入向量的中间并跳过它。
在您的示例中,当它删除@ 4时,它将?3拉到向量的中间,然后继续看b0,甚至都没有质疑过?3。 如果您想继续使用现在的代码,则需要重新设计从向量中间删除元素的逻辑。
尽管,正如其他答案所指出的那样,还有更有效的方式编写此代码。
DR,您对我的代码是正确的,这似乎可以通过添加以下这一行来解决问题:
void Piece::removeInvalids(vector<string>& v)
{
for (short i = 0; i < v.size(); i++)
{
string s = v.at(i);
size_t found = s.find_first_not_of(valids);
if (found != string::npos)
{
cout << v.at(i) << endl;
swap(v.at(i), v.back());
v.pop_back();
i = 0;
}
}
}
使它重新启动循环。 我将暂时保留这种方式,因为我必须在6月2日之前完成该项目并将其记录下来。 我确定我的老师会向全班解释作为学习经历,这是多么的糟糕,但是我们还没有深入讨论性能问题,这将是我学习C ++下一门课程的重点。 当我使用CSC-17C并调整性能时,可以修改此程序。
谢谢大家的快速回复!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.