Массивы (двумерные)

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

Двумерный массив можно представлять как таблицу или сетку:

int[][] a = new int[3][4];  // 3 строки, 4 столбца

У такого массива есть элементы a[0][0], a[0][1], …, a[2][3].


Основное

Двумерный массив целых чисел:

int[][] a = new int[n][m];   // n строк, m столбцов

a[i][j] = 10;                 // записать значение в ячейку (i, j)
int x = a[i][j];              // прочитать значение

int rows = a.length;          // количество строк
int cols = a[0].length;       // количество столбцов в первой строке

Важно:

  • индексы по строкам: от 0 до a.length - 1;
  • индексы по столбцам: от 0 до a[i].length - 1;
  • новый int[][] по умолчанию заполнен нулями.

Идея двумерного массива

Один массив — это «линейка» значений:

int[] line = new int[5];  // 5 чисел подряд

Двумерный массив — это «таблица» или «поле»:

int[][] a = new int[3][4]; // 3 строки, 4 столбца

Можно думать о нём как об «массиве массивов»:

  • a[0] — первая строка (массив int[]);
  • a[1] — вторая строка;
  • a[i][j] — элемент в i‑й строке и j‑м столбце.

Объявление и создание двумерного массива

Общий шаблон:

тип[][] имя = new тип[числоСтрок][числоСтолбцов];

Примеры:

int n = 3;
int m = 4;

int[][] a = new int[n][m];         // таблица n × m из целых
double[][] d = new double[5][5];   // 5 × 5 вещественных
boolean[][] used = new boolean[n][m]; // поле посещённых клеток

Можно создать и заполнить массив сразу литералами:

int[][] table = {
    {1, 2, 3},
    {4, 5, 6}
};
// 2 строки, 3 столбца

Чтение двумерного массива из ввода

Часто во входе сначала даны размеры n и m, затем n × m чисел.

import java.util.Scanner;

public class Read2DArrayExample {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);

        int n = in.nextInt();          // число строк
        int m = in.nextInt();          // число столбцов

        int[][] a = new int[n][m];

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                a[i][j] = in.nextInt();
            }
        }

        // вывод массива в виде таблицы
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                System.out.print(a[i][j] + " ");
            }
            System.out.println();
        }
    }
}

Здесь внешний цикл идёт по строкам (индекс i), внутренний — по столбцам (индекс j).


Сумма всех элементов

int n = in.nextInt();
int m = in.nextInt();
int[][] a = new int[n][m];

for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
        a[i][j] = in.nextInt();
    }
}

int sum = 0;

for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
        sum = sum + a[i][j];
    }
}

System.out.println(sum);

Суммы по строкам и столбцам

Суммы по строкам

int n = in.nextInt();
int m = in.nextInt();
int[][] a = new int[n][m];

for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
        a[i][j] = in.nextInt();
    }
}

for (int i = 0; i < n; i++) {
    int rowSum = 0;
    for (int j = 0; j < m; j++) {
        rowSum = rowSum + a[i][j];
    }
    System.out.println(rowSum);
}

Суммы по столбцам

int n = in.nextInt();
int m = in.nextInt();
int[][] a = new int[n][m];

for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
        a[i][j] = in.nextInt();
    }
}

for (int j = 0; j < m; j++) {
    int colSum = 0;
    for (int i = 0; i < n; i++) {
        colSum = colSum + a[i][j];
    }
    System.out.println(colSum);
}

Двумерный массив как игровое поле

Двумерный массив удобно использовать для представления игрового поля:
0 — пустая клетка, 1 — стена, 2 — персонаж и т.п.

int n = in.nextInt();
int m = in.nextInt();
int[][] field = new int[n][m];

for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
        field[i][j] = in.nextInt();
    }
}

Пример проверки соседних клеток (аккуратно с границами):

int i = in.nextInt();
int j = in.nextInt();

// проверяем, есть ли клетка сверху
if (i > 0) {
    int up = field[i - 1][j];
}

// снизу
if (i + 1 < n) {
    int down = field[i + 1][j];
}

Что нужно запомнить

Двумерный массив можно представлять как таблицу n × m:

int[][] a = new int[n][m];

Первый индекс — номер строки, второй — номер столбца: a[i][j].

Размеры: a.length — количество строк, a[i].length — количество столбцов в строке i.
Типичный приём — вложенные циклы for по строкам и столбцам для чтения, обработки и вывода таблицы.

Двумерный массив – это таблица \(n \times m\). В C++ чаще всего используют vector<vector<int>> – это «вектор строк», где каждая строка – отдельный vector<int>.

Основное

int n = 3, m = 4;
vector<vector<int>> a(n, vector<int>(m, 0));

a[0][0] = 10;
int x = a[0][0];

int rows = (int)a.size();
int cols = (int)a[0].size();

Создание

int n, m;
cin >> n >> m;
vector<vector<int>> a(n, vector<int>(m));

Чтение таблицы из ввода

int n, m;
cin >> n >> m;

vector<vector<int>> a(n, vector<int>(m));

for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
        cin >> a[i][j];
    }
}

Вывод таблицы

for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
        cout << a[i][j] << " ";
    }
    cout << "\n";
}

Двумерный массив – это список списков (таблица \(n \times m\)). Важно правильно создавать такую таблицу.

Основное

n = 3
m = 4

a = [[0] * m for _ in range(n)]

a[0][0] = 10
x = a[0][0]

rows = len(a)
cols = len(a[0])

Если написать a = [[0] * m] * n, все строки будут ссылаться на один и тот же список, и изменения будут «размножаться» по всем строкам.

Чтение таблицы из ввода

n, m = map(int, input().split())

a = []
for _ in range(n):
    row = list(map(int, input().split()))
    a.append(row)

Вывод таблицы

for i in range(n):
    for j in range(m):
        print(a[i][j], end=' ')
    print()

В Java int[][] – это «массив массивов»: строки могут быть разной длины. В C++ и Python идея такая же: это тоже «таблица из строк», и строки тоже могут быть разной длины.

В Java новый int[][] сразу заполнен нулями. В C++ и Python это зависит от того, как создаёшь: если создать таблицу с начальными нулями – будут нули, если просто объявить и потом заполнять – значения появятся только после ввода.

В Java размеры удобно брать через a.length и a[i].length. В C++ – через a.size() и a[i].size(). В Python – через len(a) и len(a[i]).

Ошибка выхода за границы в Java и C++ обычно приводит к аварийному завершению (или странному поведению в C++). В Python при неверном индексе будет IndexError.

В Python важно правильно создавать таблицу, чтобы строки были независимыми: [[0] * m for _ in range(n)].