我有一个正方形网格。每个方格都是黑色或白色。网格范围从X:-10到10和Y:-10到10.我想用二维数组bool表示网格 - 黑色为真,白色为假。数组索引只是正数 - 所以如果我想用数组创建网格,它将是bool array [21][21]
。这样做可以,但是当我尝试访问元素时会让人感到困惑。例如,如果我想访问网格上的坐标“0,3”,我的数组索引将是[11] [14]。这很有效,但它真的很乱。
有没有“更干净”的方式我可以让索引与坐标对应?
答案 0 :(得分:6)
您可以将逻辑封装到提供所需接口的类中。为了使它有点通用,您可以考虑要存储的类型和尺寸可能会有所不同:
template <typename T, int DimX, int DimY>
class offset_array2d
{
T data[ DimX*DimY ];
static const int offset_x = DimX / 2;
static const int offset_y = DimY / 2;
public:
offset_array2d() : data() {}
T& operator()( int x, int y ) {
return data[ (x+offset_x) + (y+offset_y)*DimY ];
}
T const & operator()( int x, int y ) const {
return data[ (x+offset_x) + (y+offset_y)*DimY ];
}
};
实施可能需要一些细节,但总体思路是存在的。应该有错误报告和更多的东西......维度可以成为运行时属性(而不是模板参数)但需要动态分配,正确的析构函数和复制构造函数......我真的不想进入这一切只是为了这个想法。
频谱的另一端是用户代码,现在非常简单:
int main() {
offset_array2d<bool,21,21> board;
for ( int i = -10; i < 11; ++i )
board( i, i ) = true; // write the diagonal
}
答案 1 :(得分:3)
您可以通过函数简单地访问您的数组,该函数将计算数组中的正确偏移量(向x和y添加10):
bool grid[21][21];
bool getSquareColour(size_t x, size_t y)
{
// add bounds checking here
return grid[x+10][y+10];
}
设置方块也是如此。我会把所有这些都包装成一个Grid类。
您可能还想使用std::vector<bool>
而不是bool[]
,它会将每个bool
存储为单独的位,并为您提供{{1}的额外(可能不需要的)功能}。class。
答案 2 :(得分:2)
你应该做一个辅助功能
#define OFFSET 10
void place_elem(int x, int y, bool color){
//put bounds checks here
a[OFFSET+x][OFFSET+y] = color;
}
所以
place_elem(0, -3, true)
== (a[10][7] = true)
如果您担心为数组的每次更改调用函数的开销,那么您可以使用宏来代替:
#define PLACE_ELEM(x, y, c) (a[OFFSET+x][OFFSET+y] = c)
但是,除非您完全理解使用宏的安全问题,否则请勿这样做。此外,如果您使用的是C99或C ++,则可以使用内联方法/函数。这将做同样的事情,但没有危险。
此外,enum可能比bool更好
想:
enum Color {BLACK, WHITE};
答案 3 :(得分:2)
我很确定这会调用未定义的行为。我也很确定这适用于我关心的每个架构。
#include <cassert>
int main () {
bool grid_[21][21];
bool (*grid)[21];
grid = (bool (*)[21])(&grid_[10][10]);
assert(&grid_[0][0] == &grid[-10][-10]);
assert(&grid_[0][20] == &grid[-10][10]);
assert(&grid_[20][20] == &grid[10][10]);
}
答案 4 :(得分:1)
只是提供一个易于使用的替代答案(但有点难以实现和维护),创建一个C ++类,用getter和setter隐藏复杂性。您还可以考虑重载运算符。由于该字段是二进制的,我选择使用按位运算打包数据:
class SimpleArray
{
public:
SimpleArray()
{
memset(data, 0, sizeof(data));
}
void set(int x, int y, bool value)
{
if (x >= -10 && x <= 10 && y >= -10 && y <= 10)
{
if (value)
{
data[y + 10] |= (1 << (x + 10));
}
else
{
data[y + 10] &= ~(1 << (x + 10));
}
}
}
bool get(int x, int y)
{
if (x >= -10 && x <= 10 && y >= -10 && y <= 10)
{
return (data[y + 10] & (1 << (x + 10))) != 0;
}
return false;
}
private:
unsigned int data[21];
};
答案 5 :(得分:0)
不是递增/递减索引,而是创建一个int(map)映射,您可以在其中为特定值指定特定索引。
然后,您将传递地图的值作为平方值(例如,您将方形表中的地图结果传递给键值-10 =&gt; 0(索引))。
这里有一个地图示例: http://www.yolinux.com/TUTORIALS/CppStlMultiMap.html
确定地图比简单功能使用更多内存,但它更适合重复使用。