8

I'm trying to create a three-dimensional array which contains blocks (like a rubiks-cube).

I tried many things but I can't get it to work.

func generateTiles(x int, y int, z int) [][][]*tile{
  var tiles [][][]*tile

  // Something here
  // resulting in a x by y by z array
  // filled with *tile

  return tiles
}

Any suggestions?

2
  • I think I've solved it, see below. Commented Nov 25, 2015 at 21:31
  • 4
    That's a slice not an array. Commented Nov 25, 2015 at 21:32

4 Answers 4

17

You have to initialize each layer on its own. Example (on play):

tiles = make([][][]*tile, x)

for i := range tiles {
    tiles[i] = make([][]*tile, y)
    for j := range tiles[i] {
        tiles[i][j] = make([]*tile, z)
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, this makes more sense.
9

I'd personally use a 1D slice for performance reasons, I'm adding this as an alternative:

type Tile struct {
    x, y, z int
}

type Tiles struct {
    t       []*Tile
    w, h, d int
}

func New(w, h, d int) *Tiles {
    return &Tiles{
        t: make([]*Tile, w*h*d),
        w: w,
        h: h,
        d: d,
    }
}

// indexing based on http://stackoverflow.com/a/20266350/145587
func (t *Tiles) At(x, y, z int) *Tile {
    idx := t.h*t.w*z + t.w*y
    return t.t[idx+x]
}

func (t *Tiles) Set(x, y, z int, val *Tile) {
    idx := t.h*t.w*z + t.w*y
    t.t[idx+x] = val
}

func fillTiles(w int, h int, d int) *Tiles {
    tiles := New(w, h, d)

    for x := 0; x < w; x++ {
        for y := 0; y < h; y++ {
            for z := 0; z < d; z++ {
                tiles.Set(x, y, z, &Tile{x, y, z})
            }
        }
    }

    return tiles
}

playground

2 Comments

I haven't though of this approach before. Thanks! I'll try this one too. Can you explain how exactly it will save on the performance?
@Patrick well for a few reasons, 1. It's a one big block of contiguous memory instead of multiple fragmented blocks. 2. Only one bounds check per access instead of three (slice[xyz] vs slice[x][y][z]), which can add up if you're looking for high performance.
0

There is an example for creating a two dimensional array on GoByExample: https://gobyexample.com/arrays. You should be able to expand that into a three dimensional case.

Here is what I came up with.

CODE

package main

import (
    "fmt"
)

type Tile struct {
    value int
}

func create3D( x, y, z int) [][][]*Tile {
    result := make([][][]*Tile,x)
    for i := 0 ; i < x ; i++ {
        result[i] = make([][]*Tile,y);
        for j := 0; j < y; j++ {
            result[i][j] = make([]*Tile,z);
            for k := 0 ; k < z; k++ {
                result[i][j][k] = new(Tile)
                result[i][j][k].value = i + j + k;
            }
        }
    }
    return result
}

func main() {
    X := 3
    Y := 4
    Z := 5

    mat := create3D( X , Y , Z);
    for i := 0; i < X; i++ {
        for j := 0 ; j < Y; j++ {
            for k := 0 ; k < Z; k++ {
                fmt.Printf("%d ",mat[i][j][k].value)
            }
            fmt.Println();
        }
        fmt.Println();
    }

}

Comments

-1

It works like this, but to me this feels very inefficient. Using the append-operation this many times. And it feels bloated, this should be possible in a simpler way.

func generateTiles(x int, y int, z int) [][][]*tile {
    var tiles [][][]*tile

    for i := 0; i < z; i++ {
        var layer [][]*tile
        for j := 0; j < y; j++ {
            var row []*tile
            for k := 0; k < x; k++ {
                var t *tile
                t = &tile{}
                row = append(row, t)
                count++
            }
            layer = append(layer, row)
        }
        tiles = append(tiles, layer)
    }

    return tiles
}

2 Comments

3d arrays are ugly, they have three dimensions. @nemo has a cleaner algorithm above though.
If you would use an array (your code uses slices which are not arrays) it would be easier.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.