2015-11-25 3 views
3

Я пытаюсь создать трехмерный массив, содержащий блоки (например, rubiks-куб).Как создать трехмерный массив в Golang

Я пробовал много вещей, но я не могу заставить его работать.

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 
} 

Любые предложения?

+0

Я думаю, что я ve решил это, см. ниже. – Patrick

+4

Это фрагмент, а не массив. – tobyodavies

ответ

10

Вы должны инициализировать каждый слой самостоятельно. Пример (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) 
    } 
} 
+0

Спасибо, это имеет больше смысла. – Patrick

-1

как это работает, но мне это кажется очень неэффективно. Использование append-operation это много раз. И он чувствует себя раздутым, это должно быть возможно более простым способом.

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 
} 
+0

3D-массивы уродливые, они имеют три измерения. Однако @nemo имеет более чистый алгоритм. – evanmcdonnal

+0

Если вы будете использовать массив (ваш код использует срезы, которые не являются массивами), было бы проще. – Volker

+0

Ломтики являются указателями на куски массива. Верный? – Patrick

0

Существует пример для создания двумерного массива на GoByExample: https://gobyexample.com/arrays. Вы должны иметь возможность расширить это в трехмерном случае.

Вот что я придумал.

КОД

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(); 
    } 

} 
1

Я лично использую 1D срез соображений производительности, я добавляю это в качестве альтернативы:

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

+0

У меня пока не было такого подхода. Благодаря! Я тоже попробую. Можете ли вы объяснить, как именно это сэкономит на производительности? – Patrick

+0

@Patrick хорошо по нескольким причинам, 1. Это один большой блок смежной памяти вместо нескольких фрагментированных блоков. 2. Только одна проверка границ на доступ вместо трех (slice [xyz] vs slice [x] [y] [z]), которая может складываться, если вы ищете высокую производительность. – OneOfOne

Смежные вопросы