So I’m learning Zig and trying to write a Arkanoid game in Zig.
I have to iterate through 2D array of bricks, check collision and update each brick status. This is easy to do with high level languages. With C++ vector, we can use range-based for loop like this.

vector<vector<int>> items;
for (auto & row : items) {
        for (auto &item: row) {
                item += 1;
        }
}

With C, we have to do this old fashion way by accessing each brick by i and j indexes.

Zig does support range-based for loop, so I want to use that instead of traditional i and j.

From Zig reference, we can modify 1D array’s elements like this.

test "for reference" {
    var items = [_]i32{ 3, 4, 2 };

    // Iterate over the slice by reference by
    // specifying that the capture value is a pointer.
    for (&items) |*value| {
        value.* += 1;
    }

    try expect(items[0] == 4);
    try expect(items[1] == 5);
    try expect(items[2] == 3);
}

For 2D array, we also have that fancy utility. There’s a catch here is that we need to reference item at both outer and inner loop, like C++. And because item of outer loop has been referenced, we should not use & a gain in the inner loop.

test "for reference 2d" {
    var items = [_][3]i32{[_]i32{ 3, 4, 2 }};

    // Iterate over the slice by reference by
    // specifying that the capture value is a pointer.
    for (&items) |*row| {
        // value is pointer so we don't need to reference
        for (row) |*item| {
            item.* += 1;
        }
    }

    try expect(items[0][0] == 4);
    try expect(items[0][1] == 5);
    try expect(items[0][2] == 3);
}

Let’s put C++ and Zig code side by side to see the difference.

for (auto & row : items) {
    for (auto &item: row) {
            item += 1;
    }
}
for (&items) |*row| {
    for (row) |*item| {
        item.* += 1;
    }
}

Here’s a bonus, to modify struct elements in 2D array.

const Point = struct {
    x: f64,
    y: f64,
};
var items = [_][3]Point{[_]Point{ .{ .x = 3, .y = 3 }, .{ .x = 4, .y = 4 }, .{ .x = 2, .y = 2 } }};
for (&items) |*value| {
    for (value) |*item| {
        item.x += 1;
        item.y += 1;
    }
}