Лекции.Орг


Поиск:




Категории:

Астрономия
Биология
География
Другие языки
Интернет
Информатика
История
Культура
Литература
Логика
Математика
Медицина
Механика
Охрана труда
Педагогика
Политика
Право
Психология
Религия
Риторика
Социология
Спорт
Строительство
Технология
Транспорт
Физика
Философия
Финансы
Химия
Экология
Экономика
Электроника

 

 

 

 


Задача 221.221. (завдання обласної олімпіади 1993 року) Скласти програму для гри з комп’ютером в морський бій.




Розв’язання: Одразу ж домовимось про певні обмеження, які ми накладаємо на варіант розв’язування, що приведемо ми: на полі бою розташовуються тільки однопалубні кораблі, причому вони не можуть дотикатись до інших кораблів, вводити значення місцезнаходження кораблів будемо з клавіатури. Вивід будемо здійснювати в графічному режимі для більшої наочності. Розібравшись з текстом програми ви зможете модифікувати дану програму для більш загального випадку.

Всі роздуми щодо логічної побудови програми будуть приведені в тексті програми у вигляді коментарів.

Як нам організувати робоче поле? Всім відомо, що при грі в морський бій використовують ігрове поле розміром 10 на 10 клітинок. Ми також будемо грати на полі 10 на 10, але для зручності програмування гри в пам’яті комп’ютера будемо зберігати поле 12 на 12, тобто ми з усіх сторін ігрового поля добавимо же по рядку. Зроблено це для того, щоб спростити перевірки виходу за межі ігрового поля. Отже, замість масиву mypole[1..10,1..10] ми використаємо масив mypole[0..11,0..11]. Домовимось, що при створенні математичної моделі гри будемо дотримуватись таких правил:

– якщо клітинка ігрового поля пуста і в неї не стріляли, то в ній буде міститися 0;

– якщо в даній клітинці розташовано корабель, то в ній міститься 1;

– якщо в клітинку стріляли, то в ній міститься 2.

Всі бокові клітинки, які є ніби «зайвими» і на екрані не відображаються заповними одразу двійками. Стріляти по ігровим полям будемо з комп’ютером по черзі, право першого пострілу залишимо за гравцем. Перед початком бойових дій кількості кораблів суперників прирівняємо до 10, після попадання в корабель зменшуємо відповідну кількість кораблів на 1. Бойові дії закінчується, якщо потоплено всі кораблі одного з противників.

Власне кажучи, після цього вже можна приступити до написання програми, яку ми вам і пропонуємо. Одразу зауважимо, що ми не переслідували за мету написати красиво оформлену програму, адже не це є нашою метою, нам просто потрібно показати, наскільки просто і красиво працює програма ц використанням масивів. Втім, судіть самі.

program morboj;

uses dos, crt,graph;

label mmm;

var gd,gm,i,j,l,i1,j1: integer;

ch: char;

bul: boolean;

mypole, ibmpole: array[0..11,0..11] of byte; { для поля гри 12 на 12 }

mykor, ibmkor: integer;

k, kk: integer;

st: string;

xod: integer;

{ Очистка буферу клавiатури }

procedure och;

begin

repeat ch:=readkey until not keypressed;

end;

procedure wokrug;

var i: integer;

begin

for i:=0 to 11 do

begin

mypole[i,0]:=2; ibmpole[i,0]:=2;

mypole[i,11]:=2; ibmpole[i,11]:=2;

mypole[0,i]:=2; ibmpole[0,i]:=2;

mypole[11,i]:=2; ibmpole[11,i]:=2;

end;

end;

procedure ibmkorabel; { комп’ютер розставляє свої кораблі }

var

flag1: boolean;

begin

kk:= 10;

while kk <> 0 do

begin

flag1:= true;

i:= 1 + round(random(10));

j:= 1 + round(random(10));

for i1:= i-1 to i+1 do

for j1:= j-1 to j+1 do

if ibmpole[i1,j1] <> 0 then flag1:= false;

if flag1 = true then

begin

ibmpole[i,j]:= 1;

dec(kk);

end;

end;

wokrug;

end;

procedure korabel; { ставимо один свій корабель }

var i1,j1: integer;

flag1: boolean;

begin

flag1:= true;

for i1:= i-1 to i+1 do

for j1:= j-1 to j+1 do

if getpixel(15+i1*10,15+j1*10)<>0 then flag1:= false;

if flag1 = true then

begin

Setcolor(5);

Setfillstyle(1,5);

bar(10+10*i,10+10*j,20+10*i,20+10*j);

mypole[i,j]:=1; { заповнюємо масив розташування своїх кораблів }

dec(k);

end;

end;

procedure wistrel; { наш постріл }

var i1,j1: integer;

begin

if ibmpole[i,j] = 1 then

begin

ibmpole[i,j]:=2;

line(190+10*i,10+10*j,200+10*i,20+10*j);

line(190+10*i,20+10*j,200+10*i,10+10*j);

for i1:=i-1 to i+1 do

for j1:=j-1 to j+1 do

if ibmpole[i1,j1] = 0 then putpixel(195+10*i1,15+10*j1,1);

dec(ibmkor);

end

else

begin

putpixel(195+10*i,15+10*j,1);

xod:= 0;

end

end;

procedure myxod;

begin

repeat

Setcolor(2);Rectangle(190+10*i,10+10*j,200+10*i,20+10*j);

ch:= readkey;

Setcolor(1);Rectangle(190+10*i,10+10*j,200+10*i,20+10*j);

case ch of

{ вліво } #75: dec(i);

{ вправо } #77: inc(i);

{ вверх } #72: dec(j);

{ вниз } #80: inc(j);

{ пропуск } #32: wistrel;

end; { case }

if i<1 then i:= 10;

if i>10 then i:= 1;

if j<1 then j:= 10;

if j>10 then j:= 1;

if ibmkor=0 then xod:= 0;

until xod = 0;

end;

procedure ibmxod;

begin

repeat

i:= round(random(10))+1;

j:= round(random(10))+1;

until mypole[i,j]<>2;

putpixel(15+i*10,15+j*10,1);

if mypole[i,j]=1 then

begin

for i1:=i-1 to i+1 do

for j1:=j-1 to j+1 do

begin

mypole[i1,j1]:=2;

if (i1>0) and (i1<11) and (j1>0) and (j1<11) then

putpixel(15+i1*10,15+j1*10,1);

end;

line(10+i*10,10+j*10,20+i*10,20+j*10);

line(20+i*10,10+j*10,10+i*10,20+j*10);

dec(mykor);

end else begin mypole[i,j]:=2; xod:=1 end;

end;

{ Головна програма }

begin

gd:=CGA; gm:=0; {- 640 x 480}

mmm:

for i:= 0 to 11 do

for j:= 0 to 11 do

begin

mypole[i,j]:= 0; { обнуляємо масив своїх кораблів }

ibmpole[i,j]:= 0; { і кораблів комп’ютера }

end;

initgraph(gd,gm,'egavga.bgi');

{ малюємо поле для своїх кораблів }

setcolor(1);

mykor:= 10; k:= 10; { кількість моїх кораблів}

for i:= 0 to 10 do line(20+10*i,20,20+10*i,120); { моє ігрове поле }

for i:= 0 to 10 do line(20,20+10*i,120,20+10*i);

{ і для кораблів противника - комп’ютера }

ibmkor:= 10; kk:= 10; { кількість кораблів ПЕОМ}

for i:= 0 to 10 do line(200+10*i,20,200+10*i,120); { ігрове поле ПЕОМ}

for i:= 0 to 10 do line(200,20+10*i,300,20+10*i);

ibmkorabel;

i:= 1; j:= 1;

repeat

Setcolor(2);Rectangle(10+10*i,10+10*j,20+10*i,20+10*j);

ch:= readkey;

Setcolor(1);Rectangle(10+10*i,10+10*j,20+10*i,20+10*j);

case ch of

{ left } #75: dec(i);

{ right} #77: inc(i);

{ up } #72: dec(j);

{ down } #80: inc(j);

#32: korabel;

end; { case }

if i<1 then i:= 10;

if i>10 then i:= 1;

if j<1 then j:= 10;

if j>10 then j:= 1;

until k = 0;

{ А тепер можна і в бій }

xod:=1;

repeat

if (ibmkor<>0) and (mykor<>0) then if xod=1 then myxod else ibmxod;

until (ibmkor=0) or (mykor=0);

if ibmkor = 0 then outtextxy(30,150,'Ви перемогли! ')

else if mykor=0 then outtextxy(30,150,'Ви програли! ');

outtextxy(30,180,'Ще раз? (Y/N)');

ch:= readkey;

st:=ch;

if (st = 'Y') or (st = 'y') then goto mmm;

closegraph;

end.

Перед розглядом наступної задачі рекомендуємо спочатку звернутись до §11.3, де описано роботу з файлами, і після ознайомлення зі згадуваними операціями повернутись до даного розділу. Ми вже з вами підійшли до того рівня, коли без операцій з файлами важко обійтись.

Задача 222. 222. (ХІІІ обласна олімпіада з інформатики – м. Житомир, 1999 р.)

Шаховий кінь. У файлi CHESS.DAT задано через пропуск координати стартової А(наприклад, А5) та кiнцевої В (наприклад, С7) клiтин маршруту коня. Вивести у перший рядок файлу CHESS.SOL мiнiмальну кiлькiсть ходiв N для переходу з клiтини А на клiтину В. Наступнi N рядкiв повиннi мiстити один з можливих маршрутiв по мiнiмальному маршруту з клiтини А у клiтину В. Програма повинна мати iм'я CHESS.*

Примiтка: Клiтини шахової дошки нумеруються по горизонталi великими лiтерами латинського алфавiту: A,B,C,D,E,F,G,H, а по вертикалi цифрами 1–8.

Приклад вхiдних та вихiдних даних:

CHESS.DAT CHESS.SOL

A5 C7 4

B3

D4

B5

C7

Розв’язання: Дана задача допоможе нам познайомитись з одним цікавим методом програмування, який відноситься до методів динамічного програмування.

Рис. 1

Для початку розглянемо довільне положення шахового коня на шаховій дошці. Припустимо, що кінь знаходиться у клітинці Е6. На рисунку точками відмічено клітини, у які кінь може піти при черговому ході. Таких клітин може бути від двох (у випадку, коли кінь знаходиться у кутку дошки) до восьми (як у наведеному прикладі). Ідея розв’язання полягає у відшуканні найкоротшого шляху від точки старту (Xstart, YStart) до точки фінішу (Xfine, YFine), тобто задача зводиться до відшукання найкоротшого шляху виходу з лабіринту з заданим положенням коня і точкою виходу з лабіринту (точка фінішу). Відомо багато способів відшукання такого шляху. Ми ж будемо одночасно працювати з двома шаховими дошками: одну використаємо для підрахунку кількості кроків до виходу, а іншу – для позначення номерів клітин, з яких ми потрапляємо в чергову клітину.

Обидва масиви спочатку заповнюємо нулями. Потім помічаємо клітину, у якій знаходиться кінь, як пройдену – заносимо в неї 1, причому одночасно на обох дошках.

На кожному з наступних кроків, доки не досягли клітини фінішу робимо так:

Рис. 2.
                   
                   
                   
                   
                   
                   
                   
                   
                   
          Рис. 3      
                                   

n переглядаємо всі клітини шахової дошки і, якщо в них міститься номер ходу, то відшукуємо всі клітини, у які може піти кінь, і заносимо в них значення номера ходу, який на 1 більше розглядуваного, а на іншій дошці вказуємо координати клітини, з якої ми в неї прийшли;

n координати клітини обраховуємо за формулою: k = X·10+Y;

n якщо досягли потрібної клітини, то встановлюємо прапорець виходу з подальшого перегляду клітин дошки, у противному випадку збільшуємо номер ходу на одиницю і повторюємо все спочатку.

Так, для наведеного в умові прикладу значення масивів для клітин обох дощок будуть мати такий вигляд, як зображено на рис. 2, 3. Стартову і кінцеву клітину маршруту виділено більш товстими лініями.

Якщо досягли потрібної клітини, то по другій дошці відшукуємо номери клітин, починаючи з кінцевої, маршруту до стартової клітини, доки значення клітини не стане рівним 1 – це означає, що ми досягли стартової клітини. На кожному кроці координати наступної клітини дошки визначаються за формулами: x = k div 10, y = k mod 10, де k – число, занесене у відповідну клітину дошки. Власне кажучи, це є використання вказівників, але без їх прямого опису. Отримані координати перетворюємо у назви клітин шахової дошки і у зворотному порядку виводимо на екран.

Описаний алгоритм розв’язання реалізовано у приведеній нижче програмі. Звертаємо увагу на необхідність акуратного оформлення перевірки можливості чергового ходу коня (процедура hod). Все інше зрозуміло з тексту програми.

program chess;

const inname = 'chess.dat';

outname = 'chess.sol';

var area, point: array[1..8,1..8] of byte;

namex: array[1..8] of char;

i, j, XStart, YStart, XFine, YFine, X, Y, step: byte;

f: text;

kod: integer;

c: char; st, st1: string;

flag: boolean;

procedure hod(x, y, step: byte);

begin

if (x - 2 > 0) and (y - 1 > 0) and (area[x-2,y-1] = 0) then

begin

area[x-2,y-1]:= step + 1;

point[x-2,y-1]:= 10*x + y;

end;

if (x-2 > 0) and (y+1 < 9) and (area[x-2,y+1] = 0) then

begin

area[x-2,y+1]:= step + 1;

point[x-2,y+1]:= 10*x + y;

end;

if (x+2 < 9) and (y-1 > 0) and (area[x+2,y-1] = 0) then

begin

area[x+2,y-1]:= step + 1;

point[x+2,y-1]:= 10*x + y;

end;

if (x+2 < 9) and (y+1 < 9) and (area[x+2,y+1] = 0) then

begin

area[x+2,y+1]:= step + 1;

point[x+2,y+1]:= 10*x + y;

end;

if (x-1 > 0) and (y-2 > 0) and (area[x-1,y-2] = 0) then

begin

area[x-1,y-2]:= step + 1;

point[x-1,y-2]:= 10*x + y;

end;

if (x-1 > 0) and (y+2 < 9) and (area[x-1,y+2] = 0) then

begin

area[x-1,y+2]:= step + 1;

point[x-1,y+2]:= 10*x + y;

end;

if (x+1 < 9) and (y-2 > 0) and (area[x+1,y-2] = 0) then

begin

area[x+1,y-2]:= step + 1;

point[x+1,y-2]:= 10*x + y;

end;

if (x+1 < 9) and (y+2 < 9) and (area[x+1,y+2] = 0) then

begin

area[x+1,y+2]:= step + 1;

point[x+1,y+2]:= 10*x + y;

end;

end;

procedure back_and_print;

begin

assign(f, outname); rewrite(f);

st:= '';

X:= XFine; Y:= YFine;

repeat

st1:= namex[X]; st:= st + st1;

str(Y,st1); St:= st + st1;

XFine:= point[x,y] div 10;

YFine:= point[x,y] mod 10;

x:= xfine; Y:= Yfine;

until point[x, y] = 1;

writeln(f, step); writeln(step);

kod:= length(st) - 1;

while kod >= 1 do

begin

writeln(f,copy(st,kod,2));

writeln(copy(st,kod,2));

dec(kod,2);

end;

close(f);

end;

begin

fillchar(area, sizeof(area), 0);

fillchar(point, sizeof(point), 0);

namex[1]:='A';

for i:=2 to 8 do namex[i]:= succ(namex[i-1]);

assign(f, inname); reset(f); readln(f,st); close(f);

c:= st[1];

for i:=1 to 8 do if c=namex[i] then XStart:= i;

c:= st[2]; val(c,YStart,kod);

c:= st[4];

for i:=1 to 8 do if c=namex[i] then XFine:= i;

c:= st[5]; val(c, YFine, kod);

X:= XStart; Y: = YStart;

flag:= false; step:= 1;

area[xStart, yStart]:= step;

point[Xstart, yStart]:= 1;

while flag = false do

begin

for i:= 1 to 8 do

for j:= 1 to 8 do

if area[i,j] = step then hod(i, j, step);

if area[XFine,YFine] > 0

then flag:= true

else inc(step);

end;

back_and_print;

end.

 

 

Вправи та завдання

223. 223. Складіть програму, яка повертає квадратний масив розмірністю n на 90, 180 і 270 градусів за годинниковою стрілкою або проти годинникової стрілки, в залежності від вказівки.

224. 224. У масиві розмірністю n х 12 у кожному рядку міститься заробітна плата за відповідний місяць. Складіть програму, яка:

а) підраховує сумарний заробіток кожного робітника на протязі року;

б) знаходить найменшу і найбільшу місячну заробітну плату.

225. 225. Виясніть, скільки в двомірному масиві “різних чисел”. Додатковий масив не заводьте.

226. 226. В заданому масиві розмірністю m на n:

а) поміняти місцями рядки з номерами k i p;

а) поміняти місцями стовпчики з номерами k i p.

227. 227. В заданій квадратній матриці розміром n знайти найменший елемент, що знаходиться у відповідній заштрихованій області:

228. 228. Слідом квадратної матриці називається сума елементів, розміщених на головній діагоналі. Задано квадратну матрицю порядку M і натуральне число N. Визначити сліди матриць А, А2,..., Аn.

229. 229. В заданому двомірному масиві замінити нулями елементи, що стоять в рядках або стовпчиках, де є нулі. Додаткового двомірного масиву не використовувати.

230. 230. Таблиця MxN заповнена числами 0 і 1 і в таблиці контур, заповнений тільки одиницями. Всередині контуру задано клітину з нульовим значенням. Складіть програму, яка заповнює контур одиницями.

231. 231. Двомірний масив заповнено невід’ємними цілими числами. Над масивом можна виконувати наступні дії: подвоєння всіх елементів в довільному стовпцю або віднімання 1 з кожного елемента довільного стовпця. Обнулити масив.

232. 232. Для розв’язування систем лінійних рівнянь використовують також алгоритм Жордана, який полягає в тому, що при допомогою і–го рівняння невідоме хі вилучається не тільки з рівнянь і + 1, і + 2,..., n, але й з рівнянь 1, 2,..., і–1. В результаті цього прямий хід приводить до системи виду

х1 = с1

х2 = с2

...

xn = cn

і зворотний хід, який є обов’язковим в алгоритмі Гауса, виявляється не потрібним. Напишіть програму, що реалізує алгоритм Жордана.

233. 233. Напишіть програму, яка виводить на екран таблицю множення у вигляді таблиці, яку іноді зображають на останній сторінці обкладинки учнівського зошита.

234. 234. Для масиву розмірністю M на N, елементами якого є цілі числа у одномірний масив А вивести середнє арифметичне:

а) стовпців заданого масиву;

б) рядків заданого масиву.

235. 235. Розмістити на шаховій дошці 8 ферзів так, щоб вони не загрожували один одному. Знайти всі можливі розміщення.

236. 236. Розв’язати попередню задачу для випадку, коли замість ферзів у нашому розпорядженні тури.

237. 237. Дано шахову дошку розміром М на N. Шахова фігура “міні–тура” може переміщуватись лише на одну клітину вліво, вправо, вверх та вниз. Двічі стати на одну й ту ж клітину фігурі заборонено. У клітинах шахової дошки розміщено деякі числа. Знайти такий шлях з клітини (1,1) в клітину (А,В), щоб сума чисел, що знаходяться у клітинах, якими пройшла фігура, дорівнювала заданому числу К, а кількість пройдених клітин – мінімальною.

238. 238. Складіть програму обходу шаховим конем шахової дошки по всім клітинам, не побувавши на кожній клітині двічі.

239. 239. Складіть програму, яка у прямокутному лабіринті шукає найкоротший шлях з заданої точки до виходу.

240. 240. Є N населених пунктів і відома вартість проїзду між ними, якщо між ними є дорога, у противному випадку у таблиці стоїть 0. Знайти найдешевший замкнутий маршрут, що проходить через всі населені пункти.

241. 241. Дано матрицю, що складається з нулів і одиниць. Знайти найбільший за площею прямокутник, що складається з одних одиниць.

242. 242. Є N предметів з відомою вагою і вартістю. Знайти такий набір предметів, щоб їх сумарна вага не перевищувала вантажність автомобіля М, а вартість, була найбільшою.

 

 

Множини, записи, файли

Множини

 

Поняття множини є одним із основних, фундаментальних понять математики. Існує і окремий розділ математики, який так і називається – теорія множин. У звичайному шкільному курсі математики цей розділ окремо не вивчається, але знання основ теорії множин допомагають практично вирішувати велику кількість проблем, що постають у повсякденному житті.

Що ж таке множина? Не слід шукати точне визначення даного поняття, адже це можливо лише при зведенні його до чогось більш простого, а оскільки поняття множини є найпростішим, або як кажуть первинним, то і означення його давати не має смислу, так само як давати в геометрії означення поняття точки. Звичайно термін “множина” лише пояснюють на прикладах, що зробимо і ми. Сучасна людина легко розуміє поняття множини, оскільки вона звикла оперувати з множинами з дитинства. Вже на сторінках підручника математики для 1-го класу дитина бачить зображення різних множин: множину різних тварин, множину м’ячиків, множину книг, множину учнів свого класу і інших об’єктів. Людина рахує, порівнює: в одній множині більше об’єктів, в іншій – менше, і що таке множина, їй стає ясно і без всякого визначення.

У мові Паскаль множина – це довільна сукупність значень перерахованого типу. Тип множини описується наступним чином:

type < ім’я типу > = set of < тип елементів >;

Але одразу відмітимо, що кількість елементів множини у мові Паскаль не може бути більшою, ніж 256. Це пов’язано з тим, що розробники компіляторів мови Паскаль наклали саме таке обмеження на дане поняття. Проте, навіть не зважаючи на це обмеження, основні властивості множин і операції над ними можна зручно використовувати при розв’язуванні багатьох задач.

Вкажемо, що при виконанні операцій над множинами у Паскалі діють наступні операції:

n in – належність елементу множині. Звичайно використовують при перевірці умови належності множині, наприклад, нехай задано множину цифр:

cifra: set of char;

а в самій програмі на початку цю множину конкретно визначено:

cifra:= [‘0’..‘9’];

Тоді перевірку належності введеного символу ch типу char на предмет належності множині цифр можна оформити як:

...

ch:= readkey;

if ch in cifra then write(‘ Належить цифрам ’);

...

n + – об’єднання множин. Якщо, наприклад множина А={1,2,3,4,5}, a B={4,5,6,7}, то в результаті виконання операції С=А+В ми отримаємо С={1,2,3,4,5,6,7}.

n – різниця множин. Якщо, наприклад множина А={1,2,3,4,5}, a B={4,5,6,7}, то в результаті виконання операції С=А–В ми отримаємо С={1,2,3}.

n * – переріз множин. Якщо, наприклад множина А={1,2,3,4,5}, a B={4,5,6,7}, то в результаті виконання операції С=А*В ми отримаємо С={4,5}.

Кого цікавить теорія множин, ми рекомендуємо звернутись до відповідної літератури, нам же цікаво як можна використати операції з множинами у програмуванні. Спочатку зовсім проста задача.





Поделиться с друзьями:


Дата добавления: 2016-11-18; Мы поможем в написании ваших работ!; просмотров: 384 | Нарушение авторских прав


Поиск на сайте:

Лучшие изречения:

Своим успехом я обязана тому, что никогда не оправдывалась и не принимала оправданий от других. © Флоренс Найтингейл
==> читать все изречения...

2378 - | 2186 -


© 2015-2024 lektsii.org - Контакты - Последнее добавление

Ген: 0.011 с.