🐹 Go

Двумерные массивы в Go 1.21: подробное руководство

Двумерные массивы в Go

Что такое двумерный массив?

Представь себе шахматную доску. У неё есть строки (ряды) и столбцы (места в ряду). Каждая клетка на доске — это ячейка, у которой есть свой номер строки и номер столбца. В программировании такая «таблица» называется двумерным массивом.

Двумерный массив — это массив, каждый элемент которого сам является массивом. Проще говоря, это таблица, где данные хранятся в строках и столбцах.

Зачем это нужно? Например, чтобы хранить:

  • Схему кинозала: строки — ряды, столбцы — места.
  • Карту острова: строки — координаты по вертикали, столбцы — по горизонтали.
  • Таблицу товаров на складе: строки — полки, столбцы — типы товаров.

Как объявить двумерный массив в Go?

Синтаксис очень похож на обычный массив, только мы указываем два размера: сначала количество строк, потом количество столбцов.

// Объявление массива 3x3 (3 строки, 3 столбца)
var cinema [3][3]int

// Объявление и сразу заполнение
matrix := [2][3]int{
    {1, 2, 3},
    {4, 5, 6},
}

Обращаться к элементу нужно по двум индексам: имя_массива[номер_строки][номер_столбца]. Важно: нумерация начинается с 0!

package main

import "fmt"

func main() {
    // Создаём массив 2x2
    var data [2][2]int
    
    // Заполняем его вручную
    data[0][0] = 10
    data[0][1] = 20
    data[1][0] = 30
    data[1][1] = 40
    
    // Выводим элемент из первой строки, второго столбца
    fmt.Println("Элемент [0][1]:", data[0][1]) // Выведет: 20
}

Как работать с двумерным массивом?

Чаще всего нужно пройтись по всем элементам. Для этого используют вложенные циклы — один цикл перебирает строки, другой внутри перебирает столбцы.

package main

import "fmt"

func main() {
    // Создаём массив 3x4 и заполняем нулями
    var grid [3][4]int
    
    // Заполняем значениями: номер строки + номер столбца
    for row := 0; row < 3; row++ {
        for col := 0; col < 4; col++ {
            grid[row][col] = row + col
        }
    }
    
    // Выводим таблицу на экран
    for row := 0; row < 3; row++ {
        for col := 0; col < 4; col++ {
            fmt.Print(grid[row][col], " ")
        }
        fmt.Println() // Переход на новую строку
    }
}

Вывод программы:

0 1 2 3 
1 2 3 4 
2 3 4 5

Как заполнить массив с клавиатуры?

Часто в задачах нужно вводить данные от пользователя. Используем fmt.Scan внутри вложенных циклов.

package main

import "fmt"

func main() {
    var rows, cols int
    fmt.Print("Введите количество строк и столбцов: ")
    fmt.Scan(&rows, &cols)
    
    // Создаём массив нужного размера
    arr := make([][]int, rows)
    for i := 0; i < rows; i++ {
        arr[i] = make([]int, cols)
    }
    
    // Заполняем с клавиатуры
    fmt.Println("Введите элементы построчно:")
    for i := 0; i < rows; i++ {
        for j := 0; j < cols; j++ {
            fmt.Scan(&arr[i][j])
        }
    }
    
    // Выводим таблицу
    fmt.Println("Ваша таблица:")
    for i := 0; i < rows; i++ {
        for j := 0; j < cols; j++ {
            fmt.Print(arr[i][j], "\t")
        }
        fmt.Println()
    }
}

Разбор типичных задач

Задача «Кинозал»

Нужно создать схему зала. Пусть свободные места — 0, занятые — 1. Мы получаем размеры зала и заполняем его.

package main

import "fmt"

func main() {
    var rows, cols int
    fmt.Scan(&rows, &cols)
    
    // Создаём схему зала
    hall := make([][]int, rows)
    for i := 0; i < rows; i++ {
        hall[i] = make([]int, cols)
        // Заполняем ряд: если i % 2 == 0, то все места свободны, иначе заняты
        for j := 0; j < cols; j++ {
            if i%2 == 0 {
                hall[i][j] = 0 // Свободно
            } else {
                hall[i][j] = 1 // Занято
            }
        }
    }
    
    // Выводим схему
    for i := 0; i < rows; i++ {
        for j := 0; j < cols; j++ {
            fmt.Print(hall[i][j], " ")
        }
        fmt.Println()
    }
}

Задача «Популярность постов»

У нас есть блогеры и их посты. Нужно найти, у какого блогера больше всего лайков.

package main

import "fmt"

func main() {
    var bloggers, posts int
    fmt.Print("Количество блогеров и постов: ")
    fmt.Scan(&bloggers, &posts)
    
    // Создаём таблицу лайков
    likes := make([][]int, bloggers)
    for i := 0; i < bloggers; i++ {
        likes[i] = make([]int, posts)
        fmt.Printf("Введите лайки для блогера %d: ", i+1)
        for j := 0; j < posts; j++ {
            fmt.Scan(&likes[i][j])
        }
    }
    
    // Ищем блогера с максимальной суммой лайков
    maxSum := 0
    maxBlogger := 0
    for i := 0; i < bloggers; i++ {
        sum := 0
        for j := 0; j < posts; j++ {
            sum += likes[i][j]
        }
        if sum > maxSum {
            maxSum = sum
            maxBlogger = i + 1
        }
    }
    
    fmt.Printf("Самый популярный блогер: %d (всего лайков: %d)\n", maxBlogger, maxSum)
}

Частые ошибки новичков

  • Путают индексы: помните, что первый индекс — это строка, второй — столбец. arr[строка][столбец].
  • Выход за границы массива: если массив размером 3x3, то индексы могут быть только 0, 1, 2. Обращение к индексу 3 вызовет ошибку.
  • Забывают про вложенные циклы: чтобы пройтись по всем элементам, нужно два цикла. Один цикл не сможет перебрать все ячейки.
  • Неправильное создание через make: сначала нужно создать массив для строк (make([][]int, rows)), а потом для каждой строки создать свой массив (make([]int, cols)).

Итоговый пример: «Карта сокровищ»

Представь, что у нас есть карта острова 4x4. На карте цифрами обозначены высоты. Нужно найти самую высокую точку и вывести её координаты.

package main

import "fmt"

func main() {
    // Карта острова (задаём сразу)
    island := [4][4]int{
        {1, 3, 2, 4},
        {5, 7, 6, 8},
        {9, 2, 3, 1},
        {4, 5, 6, 0},
    }
    
    // Ищем максимальную высоту
    maxHeight := island[0][0]
    maxRow := 0
    maxCol := 0
    
    for row := 0; row < 4; row++ {
        for col := 0; col < 4; col++ {
            if island[row][col] > maxHeight {
                maxHeight = island[row][col]
                maxRow = row
                maxCol = col
            }
        }
    }
    
    fmt.Printf("Самая высокая точка находится в строке %d, столбце %d\n", maxRow, maxCol)
    fmt.Printf("Высота: %d метров\n", maxHeight)
}

Вывод программы:

Самая высокая точка находится в строке 2, столбце 0
Высота: 9 метров

Важно: строки и столбцы считаются с 0! Если хочешь показывать пользователю привычные номера (начиная с 1), просто добавь 1 при выводе: maxRow+1 и maxCol+1.

Двумерные массивы — это мощный инструмент для работы с табличными данными. Потренируйся создавать свои таблицы, заполнять их и обрабатывать, и ты быстро освоишь эту тему!