Заполнение двухмерного массива
По правилу
Пример
Составить программу, запрашивающую координаты ферзя на шахматной доске и показывающую поля доски, находящиеся под боем (на доске нет других фигур).
Решение
Заметим, что шахматную доску удобно представить в виде двумерного массива размером 8х8. Координаты ферзя можно задать двумя числами (номером строки и номером столбца), но в шахматах принято указывать букву и число. Буква указывает номер строки, а число − номер столбца. Поэтому не будем отступать от традиций и введем координаты именно таким образом. В программе сделаем проверку правильности ввода, и если все правильно, то переведем букву в соответствующее ей число (a-1, b-2, c-3, d-4, е-5, f-6, g-7, h-8), тогда будет удобнее работать.
Для решения задачи полезно знать следующие свойства шахматной доски. Все диагонали делятся на восходящие и нисходящие:
Каждая диагональ обладает следующими свойствами:
· для элементов любой восходящей диагонали сумма номеров строки и столбца постоянна, причем для разных диагоналей − разная, то есть i+j=const1;
· для элементов нисходящих диагоналей разность номеров строки и столбца тоже постоянна и для разных диагоналей разная, то есть i-j=const2.
Это необходимо знать для того, чтобы определить номера диагоналей, на которых находится ферзь. Вся программа будет такой:
Program Example_120;
Const n=8;
Type dmyarray=Array[1..n,1..n] Of Integer;
Var A: dmyarray;
c: Char;
str, stl: Integer;
{str - номер строки, stl - номер столбца}
Function Place(ch: Char): Integer;
Var k: Integer;
Begin
Case ch Of
'a': k:=1; 'b': k:=2; 'c': k:=3;
'd': k:=4; 'e': k:=5; 'f: k:=6;
'g': k:=7; 'h': k:=8;
Place:=k;
End;
Procedure Init(k, l: Integer;
Var x: dmyarray);
{k - номер строки, l - номер столбца, где стоит ферзь}
Var i, j: Integer;
Begin
For i:=1 To n Do
For j:=1 To n Do {Под боем клетки,
находящиеся с клеткой, на которой стоит
ферзь, на одной вертикали, горизонтали,
восходящей или нисходящей диагонали.
Клетки, находящиеся под боем, мы
помечаем 1, остальные помечаем 0.}
If (i=k) Or (j=1) Or (i+j=k+1)
Or (i-j=k-l)
Then x[i, j]:=1 Else x[i, j]:=0;
x[k, l]:=2;
{На этой клетке стоит ферзь}
End;
Procedure Print(x: dmyarray);
Var i, j: Integer;
Begin
For i:=1 To n Do
Begin
For j:=1 To n Do
Case x[i, j] Of
0: Write (' ':3);
1: Write ('*':3);
2: Write ('F':3);
End;
Writeln;
End;
Begin
Writeln('Введите координаты ферзя');
Readln(с, stl);
If (c<'a') Or (c>'h') Or (stl<1)
Or (stl>n) Then
Writeln('Некорректный ввод')
Else
Begin
str:=Place(с);
Init(str, stl, A);
Print(A);
End;
Readln;
End.
Можно функцию Place составить иначе:
Function Place(ch: Char): Integer;
Var k: Integer;
Begin
Place:=0rd(ch)-Ord('a')+1;
End;
В этом случае она будет более рациональна.
Пример 2
Заполнить массив А размером n×m следующим образом (по "змейке");
Например, при n=6 и m=8:
1 2 3 4 5 6 7 8
16 15 14 13 12 11 10 9
17 18 19 20 21 22 23 24
32 31 30 29 28 27 26 25
33 34 35 36 37 38 39 40
48 47 46 45 44 43 42 41
Решение
Для того чтобы заполнить массив указанным образом, надо вывести правило заполнения. В данном случае правило будет таким: если ряд нечетный (то есть когда номер строки − нечетное число), то А[i, j]=(i-1)*m+j, иначе (то есть когда строка четная) A[i, j]=i*m-j+1. В соответствии с этим правилом составляем процедуру заполнения массива:
Program Example_121;
Procedure Fill (Varx: dmyarray);
Var i, j: Integer;
Begin
For i:=1 To n Do
For j:=1 To m Do
If i Mod 2=1 Then x[i, j]:=(i-1)*m+j
Else x[i, j]:=i*m-j+1;
End;
Вставка и удаление элементов
Вставка строки
Мы уже рассматривали операции вставки для одномерных массивов. Обобщим их для двухмерных.
Пример
Вставить строку из нулей после строки с номером k.
Решение
Для решения этой задачи необходимо:
1. Первые k строк оставить без изменения.
2. Все строки после k−й сдвинуть на одну вниз, это лучше начать с последней строки и идти до (k+1)−й.
3. Присвоить значения элементам (k+1) строки.
Кроме того, необходимо обратить внимание на размерность массива. Так как мы вставляем строку, то необходимо иметь одну строку "в запасе".
Program Example_122;
Const n=5; m:=7;
Type dmyarray=Array[1..n+1,1..m]
Of Integer;
Var A: dmyarray; k:Integer;
Теперь опишем процедуру вставки:
Procedure Insert(k1: Integer;
Var x: dmyarray);
Var i, j: Integer;
Begin
For i:=n Downto k1+1 Do
For j:=1 To m Do x[i+1, j]:=x[i, j];
{Элементу столбца с номером j присваиваем
элемент этого же столбца, но из
предыдущей строки}
For j:=1 То m Do x[k1+1, j]:=0;
End;
Так как число строк меняется, то процедуру Print надо изменить. Она должна выводить указанное количество строк, начиная с первой:
Procedure Print1 (n1: Integer;
x: dmyarray);
Var i, j: Integer;
Begin
For i:=1 To n1 Do
Begin
For j:=1 To m Do Write(x[i, j]: 4);
Writeln;
End;
End;
Часть основной программы будет такой:
Begin
Init(A);
Print(n, A);
Writeln ('Введите номер строки, после
которой надо вставить новую строку');
Readln(k);
Insert(k, A);
Print1(n+1, A);
Readln;
End.
Примечания
1. Если необходимо вставить новую строку после строки, удовлетворяющей некоторому условию, то надо лишь найти номер этой строки и задача сведется к решению уже рассмотренной.
2. Если надо вставлять новые строки после всех строк с заданным условием, то надо учесть это при описании массива. Заметим, что удобнее просматривать строки с последней и ввести счетчик вставленных строк.
3. Вставка новой строки перед строкой с номером k изменится только тем, что сдвигать назад надо не с (k+1)−й строки, а с k−й.
4. Если надо вставлять столбцы, то размерность массива увеличивается по столбцам, а все остальное практически не меняется: надо сдвинуть столбцы вправо и на данное место записать новый столбец.
Удаление строки
Пример
Удалить строку с номером k.
Решение
Дли того чтобы удалить строку с номером k, необходимо:
· Сдвинуть все строки, начиная с данной на одну вверх.
· Последнюю строку "обнулить", то есть всем элементам последней строки присвоить значение 0.
Описание массивов оставим прежним (размером nxm). Также в программе будем использовать процедуру вывода Print1 из предыдущего параграфа. Будем выводить на экран сначала все строки, а второй раз, после удаления, на одну меньше. Теперь опишем процедуру удаления строки с данным номером:
Program Example_123;
Procedure Delete (k1: Integer;
Var x: dmyarray);
Var i, j: Integer;
Begin
For i:=k1 To n-1 Do
For j:=1 To m Do
x [i, j]:=x[i+1, j];
For j:=1 To m Do x[n, j]:=0;
End;
Примечания
1. Задачу удаления строки, удовлетворяющей заданному условию, можно решить этим же способом, достаточно только найти ее номер.
2. Используя данную процедуру, можно решить еще одну задачу − удаление всех строк, которые обладают некоторым свойством.