填字游戏网格的数据结构?
Data structure for a crossword puzzle grid?
我想用 C++ 设计一个填字游戏编辑器。它是一个方块网格,每个方块包含一个字母(或在两个单词之间是黑色的),可能是一个数字和一条粗或细的边框线。
因此,该块是他们的容器 class。网格是块的容器。但是我将如何构建网格?
- 原始二维数组:
Block grid[row][column]?
- 向量的向量:
vector<vector<Block>>?
- 两个向量,一个用于行,一个用于列:
vector<Block> row; vector<Block> column
?
- 一张地图,键是 row/column 对,值是块:
map<int[2], Block>
?
默认情况下,普通 static/dynamic 数组(或其包装器)是最可取的:它们对程序员(随机访问 API 等)和处理器(内存局部性)来说都是最舒适的等)。
array/a 向量中最容易实现的 Block
布局是 [first row Blocks..., second row Blocks..., etc]
- 充当二维数组的一维数组。它可以像 crossword[x + y * crossword.width()]
一样被索引,这并不漂亮,所以你可能想使用 library/self-written 包装器和 API 像 crossword(x, y)
来执行 xy
幕后-到-i
-索引转换。
可能是这样的:
class Crossword {
std::vector<Block> raw;
size_t length{}; // can't name it "width" because there's a "width()" member function below
public:
Crossword() {}
Crossword(size_t x, size_t y): raw(x * y), length{x} {}
Crossword(Crossword&& other) noexcept { *this = std::move(other); }
Crossword& operator=(Crossword&& other) noexcept {
std::swap(raw, other.raw);
std::swap(length, other.length);
return *this;
}
auto size() const { return raw.size(); }
auto width() const { return length; }
auto height() const { return size() / length; }
auto& operator()(size_t x, size_t y) const { return raw[x + y * length]; }
auto& operator()(size_t x, size_t y) { return raw[x + y * length]; }
};
我想用 C++ 设计一个填字游戏编辑器。它是一个方块网格,每个方块包含一个字母(或在两个单词之间是黑色的),可能是一个数字和一条粗或细的边框线。 因此,该块是他们的容器 class。网格是块的容器。但是我将如何构建网格?
- 原始二维数组:
Block grid[row][column]?
- 向量的向量:
vector<vector<Block>>?
- 两个向量,一个用于行,一个用于列:
vector<Block> row; vector<Block> column
? - 一张地图,键是 row/column 对,值是块:
map<int[2], Block>
?
默认情况下,普通 static/dynamic 数组(或其包装器)是最可取的:它们对程序员(随机访问 API 等)和处理器(内存局部性)来说都是最舒适的等)。
array/a 向量中最容易实现的 Block
布局是 [first row Blocks..., second row Blocks..., etc]
- 充当二维数组的一维数组。它可以像 crossword[x + y * crossword.width()]
一样被索引,这并不漂亮,所以你可能想使用 library/self-written 包装器和 API 像 crossword(x, y)
来执行 xy
幕后-到-i
-索引转换。
可能是这样的:
class Crossword {
std::vector<Block> raw;
size_t length{}; // can't name it "width" because there's a "width()" member function below
public:
Crossword() {}
Crossword(size_t x, size_t y): raw(x * y), length{x} {}
Crossword(Crossword&& other) noexcept { *this = std::move(other); }
Crossword& operator=(Crossword&& other) noexcept {
std::swap(raw, other.raw);
std::swap(length, other.length);
return *this;
}
auto size() const { return raw.size(); }
auto width() const { return length; }
auto height() const { return size() / length; }
auto& operator()(size_t x, size_t y) const { return raw[x + y * length]; }
auto& operator()(size_t x, size_t y) { return raw[x + y * length]; }
};