Введение 
Очень часто при работе с какой-либо информацией приходится иметь дело с табличными данными. Современные программы очень часто работают именно с такими данными. Самый простой пример - это программирование игр на клетчатой доске: крестики-нолики, шахматы, шашки и т.п.

В математике такие структуры называются матрицами.
 
Матрица - это прямоугольная таблица составленная из элементов одного типа (чисел, строк и т.д)

Такие данные на языке Pascal можно хранить и обрабатывать в виде двумерных массивов - "массивов массивов".
Чтобы обработать данные в таблице, надо запоминать состояние каждой ячейки (клетки). Каждая ячейка имеет два номера: номер строки и номер столбца.
В матрице каждый элемент имеет два индекса: сначала указывается номер строки, затем номер столбца. Нумерация строк и столбцов начинается с нуля.
Например, элемент A[1][2] - это элемент расположенный во второй строке и третьем столбце.

Так же как и с обычными массивами (списками), для того, чтобы работать с матрицами, необходимо научиться их создавать, вводить, обрабатывать и выводить на экран.
 
Создание матрицы
Задача
Создать в памяти матрицу заданного размера, заполненной нулями.

Чтобы создать правильно матрицу, необходимо заставить компилятор создать все строки в памяти как разные объекты.
Для этого необходимо сначала создать пустой массив, затем указать количество строк в матрице, а потом в цикле указывать количество элементов в каждой строке с помощью метода setLength():
N := 3
M := 2
setLength(A, N);
for i := 0 to N - 1 do
    setLength(A[i], M);

 

Заполнение матрицы произвольными значениями
После создания матрицы можно заполнить ее произвольными значениями. Так как каждый элемент имеет два индекса, то необходимо использовать вложенные циклы
for i := 0 to N do begin
    for j := 0 to M do begin
        A[i][j] := ...
    end;
end;
 
Вывод матрицы на экран

Для обработки и вывода списка, как правило, используется два вложенных цикла. Первый цикл по номеру строки, второй цикл - по элементам внутри строки.
Для того, чтобы вывести матрицу на экран построчно, разделяя числа пробелами внутри одной строки, необходимо написать такой фрагмент:

for i := 0 to length(A) - 1 do begin // length(A) - возвращает количество строк в матрице А
    for j := 0 to length(A[i]) - 1 do // length(A[i]) - возвращает количество элементов в строке i
        write(a[i][j], ' ');
    writeln(); // делаем переход на новую строку после вывода на экран строки
end;

То же самое, но циклы не по индексу, а по значениям списка (цикл for умеет делать перебор всех элементов в списке (массиве), строке):

for row in a do begin // делаем перебор всех строк матрицы a
    for elem in row do // перебираем все элементы в строке row
        write(elem, ' ');
    writeln();
end;

Заполнение матрицы значениями с клавиатуры

Пусть программа получает на вход двумерный массив, в виде n строк, каждая из которых содержит m чисел, разделенных пробелами. Сохранить такие данные в двумерный массив можно следующим образом:

read(n, m);
setlength(a, n);
for i:= 0 to n - 1 do begin
    setlength(a[i], m);
    for j := 0 to m - 1 do read(a[i][j]);
end;

Каждый элемент матрицы имеет два индекса, поэтому для перебора всех элементов нужно использовать вложенный цикл.
Обычно матрицу перебирают по строкам: внешний цикл перебирает индексы строк, а внутренний - индексы столбцов.
Но при необходимости можно перебирать матрицу и по столбцам, тогда циклы меняются местами.