如何将包含图块编号的字符串转换为包含图块编号坐标的地图或矢量?
How to turn a string containing tile numbers into a map or vector that contains coordinates of the tilenumber?
我正在使用 tinyxml2 (https://leethomason.github.io/tinyxml2/index.html) 将 .tmx/.xml 文件解析为 C++。有一个名为data的ChildElement,它有文本内容。
<data encoding="csv">
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,
3,3,0,2,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,3,
3,3,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,3,
3,3,4,0,0,3,3,3,3,3,3,3,3,3,3,3,4,0,3,3,
3,3,3,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,
3,3,3,3,4,0,0,0,2,2,2,2,2,2,2,0,0,0,5,3,
3,3,3,3,3,4,0,6,6,6,0,0,0,0,0,0,0,5,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
</data>
我通过 tinyxml 函数 GetText() 获取文本。所以每个 ',' 等于一列 -> x 坐标,每个 '\n' 限制行 ->
y 坐标。我试图将坐标和瓷砖编号放入 std::map,它只包含整数值(x、y、瓷砖编号)。到目前为止,我的工作解决方案看起来像下面的代码。现在我正在寻找更好的解决方案。目前我只保存线,我会从向量中的位置得到 x。
XMLElement* pData = pLayer->FirstChildElement("data");
if (pData != NULL)
{
std::stringstream gidList;
gidList.str(pData->GetText());
std::vector<std::string> LineList;
std::map<int, std::vector<int>> gidDataList;
std::string gidLine;
while (std::getline(gidList, gidLine, '\n'))
{
LineList.push_back(gidLine);
}
for (int line = 0; line < LineList.size(); line++)
{
std::string tilenumber;
std::stringstream LineListStream(LineList.at(line));
while (std::getline(LineListStream, tilenumber, ','))
{
gidDataList[line].push_back(std::stoi(tilenumber));
}
}
}
我认为您混淆了 std::map
的目的,更有效的实现可能会使用 std::vector
之类的东西。当使用非整数键映射对时,映射会很有用,但对于像这样的应用程序,它们就有点过分了。
#include <string>
#include <vector>
std::vector<std::vector<unsigned int>> parse_tiles(const std::string &gid_list) {
std::vector<std::vector<unsigned int>> tiles;
std::string value;
unsigned int row = 0;
for(unsigned int index = 0; index < gid_list.length(); index += 1) {
if(gid_list[index] == ',') {
tiles[row].push_back(std::stoi(value));
value.clear();
}
else if(gid_list[index] == '\n') {
tiles[row].push_back(std::stoi(value));
value.clear();
tiles.push_back();
row += 1;
}
else if(gid_list[index] >= '0' && gid_list[index] <= '9')
value += gid_list[index];
}
return tiles;
}
通过这个示例,您应该能够以与之前大致相同的方式访问元素。例如,断章取义:
const auto tiles = parse_tiles(pData->GetText());
std::cout << "tile at (x = 2, y = 4) = " << tiles[4][2] << "\n";
我正在使用 tinyxml2 (https://leethomason.github.io/tinyxml2/index.html) 将 .tmx/.xml 文件解析为 C++。有一个名为data的ChildElement,它有文本内容。
<data encoding="csv">
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,
3,3,0,2,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,3,
3,3,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,3,
3,3,4,0,0,3,3,3,3,3,3,3,3,3,3,3,4,0,3,3,
3,3,3,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,
3,3,3,3,4,0,0,0,2,2,2,2,2,2,2,0,0,0,5,3,
3,3,3,3,3,4,0,6,6,6,0,0,0,0,0,0,0,5,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
</data>
我通过 tinyxml 函数 GetText() 获取文本。所以每个 ',' 等于一列 -> x 坐标,每个 '\n' 限制行 -> y 坐标。我试图将坐标和瓷砖编号放入 std::map,它只包含整数值(x、y、瓷砖编号)。到目前为止,我的工作解决方案看起来像下面的代码。现在我正在寻找更好的解决方案。目前我只保存线,我会从向量中的位置得到 x。
XMLElement* pData = pLayer->FirstChildElement("data");
if (pData != NULL)
{
std::stringstream gidList;
gidList.str(pData->GetText());
std::vector<std::string> LineList;
std::map<int, std::vector<int>> gidDataList;
std::string gidLine;
while (std::getline(gidList, gidLine, '\n'))
{
LineList.push_back(gidLine);
}
for (int line = 0; line < LineList.size(); line++)
{
std::string tilenumber;
std::stringstream LineListStream(LineList.at(line));
while (std::getline(LineListStream, tilenumber, ','))
{
gidDataList[line].push_back(std::stoi(tilenumber));
}
}
}
我认为您混淆了 std::map
的目的,更有效的实现可能会使用 std::vector
之类的东西。当使用非整数键映射对时,映射会很有用,但对于像这样的应用程序,它们就有点过分了。
#include <string>
#include <vector>
std::vector<std::vector<unsigned int>> parse_tiles(const std::string &gid_list) {
std::vector<std::vector<unsigned int>> tiles;
std::string value;
unsigned int row = 0;
for(unsigned int index = 0; index < gid_list.length(); index += 1) {
if(gid_list[index] == ',') {
tiles[row].push_back(std::stoi(value));
value.clear();
}
else if(gid_list[index] == '\n') {
tiles[row].push_back(std::stoi(value));
value.clear();
tiles.push_back();
row += 1;
}
else if(gid_list[index] >= '0' && gid_list[index] <= '9')
value += gid_list[index];
}
return tiles;
}
通过这个示例,您应该能够以与之前大致相同的方式访问元素。例如,断章取义:
const auto tiles = parse_tiles(pData->GetText());
std::cout << "tile at (x = 2, y = 4) = " << tiles[4][2] << "\n";