Помощь - Поиск - Пользователи - Календарь
Полная версия: Кольцо в коробке((
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
yakudza_m

program pr3;
Uses Graph,Crt;

const MaxShar=10;
type shar = object
{ переменные }
x,y:integer; { текущие координаты шара }
r:word; { радиус }
color:byte; { цвет шара }
dx,dy:shortint; { скорость. задается значениями
перемещения на каждом шаге (в точках) }
hits:set of byte; { множество шаров с которыми данный шар уже
столкнулся и с которыми не надо обсчитывать столкновение еще раз }
{ методы }
constructor initShar(x0,y0:integer; r0:word; color0:byte; dx0,dy0:shortint);
procedure Move; { двигаем }
procedure Show; { показываем }
procedure Hide; { прячем }
procedure CheckBorder; { проверяем на выход за границы экрана }
procedure CheckHit(k:byte); { проверяем на столкновение с другим шаром }
procedure revertXDirection; { поменять Х/Y-составляющую скорости }
procedure revertYDirection; { на противоположную }
procedure TurnAfterHit(k:byte); { вычислить новые значения
скорости двух шаров после удара. Первый шар - шар
данного объекта, второй - с индексом k в массиве }
function Value:real; { вычислить объем шара. Нужно для вычисления
скорости. Вообще-то там масса нужна, но учитывая, что плотность
все-равно сократиться при делении, используем объем }
{procedure PrintState;} { отладочные печати }
end;
var bgColor,i:byte;
x,y,dx,dy,ErrCode:integer;
r:word;
shars: array[1..MaxShar] of shar; { массив шаров }
sh:shar;
f:text; { файл для отладочных печатей }
Procedure shar.Move;
begin
x:=x+dx;
y:=y+dy;
end;
Procedure shar.Show;
begin
setColor(color);
circle(x, y, r);
PutPixel(x,y,color); { уберите комментарий чтобы увидеть траекторию }
end;
Procedure shar.Hide;
begin
setColor(bgColor);
circle(x, y, r);
end;
procedure shar.revertXDirection;
begin
dx:=-dx;
x:=x+dx;
end;
procedure shar.revertYDirection;
begin
dy:=-dy;
y:=y+dy;
end;
Constructor shar.initShar(x0, y0 :integer; r0 :word; color0 :byte; dx0, dy0 :shortint);
begin
x:=x0;
y:=y0;
r:=r0;
color:=color0;
dx:=dx0;
dy:=dy0;
hits:=[];
end;
procedure shar.CheckBorder;
begin
if (r+x>=GetMaxX-1) or (x-r<=1) then revertXDirection;
if (y+r>=GetMaxY-1) or (y-r<=1) then revertYDirection
end;
{procedure shar.PrintState;
begin
writeln(f,'x=',x:3,' y=',y:3,' r=',r:3,' dx=',dx:3,' dy=',dy:3);
end;}
procedure shar.TurnAfterHit(k:byte);
{ формулы для движения шаров взяты здесь:
_http://ferro.phys.msu.ru/prak/PDF/01-mechanics/07.pdf }
var m1, m2 :real;
vx10,vy10,vx20,vy20:integer;
begin
m1 := Value; { массы }
m2 := shars[k].Value;
vx10 := dx; { начальные значения скоростей }
vy10 := dy;
vx20 := shars[k].dx;
vy20 := shars[k].dy;
{ скорость первого шара после удара }
dx := round((2*m2*vx20 + (m1-m2)*vx10)/(m1+m2));
dy := round((2*m2*vy20 + (m1-m2)*vy10)/(m1+m2));
{ скорость второго шара после удара }
shars[k].dx := round((2*m1*vx10 + (m2-m1)*vx20)/(m1+m2));
shars[k].dy := round((2*m1*vy10 + (m2-m1)*vy20)/(m1+m2));
end;
function shar.Value:real;
begin { возвращает объем шара }
Value:=4*Pi*r*r*r/3;
end;
procedure shar.CheckHit(k:byte);
var i1:byte;
dist:longint;
begin
for i1:=1 to MaxShar do if ((i1<>k) and not(k in hits)) then
begin
shars[i1].hits:=shars[i1].hits+[k];
dist:=round(sqrt(sqr(1.0*x-shars[i1].x)+sqr(1.0*y-shars[i1].y)));
if (dist<r+shars[i1].r) then
begin
TurnAfterHit(i1);

CheckBorder;
Move;
shars[i1].CheckBorder;
shars[i1].Move;

{ скорость задается значениеми dx и dy - шагами движения. Таким
образом она дискретна. Момент столкновения определяется по
расстоянию между шарами. Но запросто может случиться, что шары
на каком-то шаге пересекутся и в этом случае необходимо их
развести в разные стороны перед тем как высчитывать расстояние на
следуещем шаге, иначе они могут пребывать в состоянии постоянного
столкновения }
dist:=round(sqrt(sqr(1.0*x-shars[i1].x)+sqr(1.0*y-shars[i1].y)));
while (dist<r+shars[i1].r) do
begin
CheckBorder;
Move;
shars[i1].CheckBorder;
shars[i1].Move;
dist:=round(sqrt(sqr(1.0*x-shars[i1].x)+sqr(1.0*y-shars[i1].y)));
end;
end;
end;
end;

function initializeGraph:integer;
var grDriver : Integer;
grMode : Integer;
begin
grDriver:=Detect;
InitGraph(grDriver, grMode, '');
initializeGraph:=GraphResult;
end;

begin
ErrCode:=initializeGraph;
if ErrCode <> grOk then
WriteLn('Ошибка инициализации графики:', GraphErrorMsg(ErrCode))
else
begin
assign(f,'log.txt');
rewrite(f);
bgColor:=0;
rectangle(1,1,GetMaxX-1,GetMaxY-1);

{shars[1].initShar(100,100,50,3,6,-3);
shars[2].initShar(100,200,40,4,5,3);
shars[3].initShar(200,200,20,5,-7,-4);
shars[4].initShar(400,300,25,2,-9,-1);
shars[5].initShar(500,200,35,14,-5,-8);
if (MaxShar>5) then}

{ инициализация шаров случайным образом }
for i:=1 to MaxShar do
begin
r:=20+random(10);
shars[i].initShar(1+r+random(GetMaxX-2*r),
1+r+random(GetMaxY-2*r),r,1+random(GetMaxColor-1),
random(15)-7,random(12)-6);
end;
{ обсчитываем движение пока не нажата какая-либо клавиша }
repeat
{ показываем все шары }
for i:=1 to MaxShar do
shars[i].Show;
{ временная задержка - установите свое значение для вашего компьютера }
Delay(50);
{ убираем с экрана все шары }
for i:=1 to MaxShar do
shars[i].Hide;
{ просчитываем следующий шаг }
for i:=1 to MaxShar do
begin
shars[i].Move;
shars[i].CheckBorder;
shars[i].CheckHit(i);
end;
for i:=1 to MaxShar do
shars[i].hits:=[];
until keyPressed;
CloseGraph;
close(f);
end
end.



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

Добавлено через 3 мин.
я немного нарушил правила форума в предыдущей теме (в которой админы очень помогли), за што дико извиняюсь(((
volvo
Да это проще заново написать, чем что-то переделывать... В частности, озвученная тобой задача решается в 70 строк:
uses crt,graph;

const
width = 280;
Rmax = 40;
Rmin = 17;

dx: integer = 2;

var
posX: integer;
angle: integer;


procedure draw;
const
lines = 6;
var
i: integer;
begin
line((getmaxx div 2) - (width div 2), getmaxy - 20,
(getmaxx div 2) - (width div 2), getmaxy - 100);

line((getmaxx div 2) - (width div 2), getmaxy - 20,
(getmaxx div 2) + (width div 2), getmaxy - 20);

line((getmaxx div 2) + (width div 2), getmaxy - 20,
(getmaxx div 2) + (width div 2), getmaxy - 100);

circle(posX, getmaxy - 21 - Rmax, Rmax);
for i := 1 to lines do begin
line(posX + trunc(Rmin * cos(pred(i) * 2*pi/lines + angle)),
getmaxy - 21 - Rmax - trunc(Rmin * sin(pred(i) * 2*pi/lines + angle)),

posX + trunc(Rmax * cos(pred(i) * 2*pi/lines + angle)),
getmaxy - 21 - Rmax - trunc(Rmax * sin(pred(i) * 2*pi/lines + angle)));

end;
circle(posX, getmaxy - 21 - Rmax, Rmin);
end;

var
driver,mode:integer;

begin
driver:=detect;
initgraph(driver, mode, '');
posX := getmaxx div 2;
angle := 0;

while not keypressed do begin
setfillstyle(solidfill, getbkcolor);
bar((getmaxx div 2) - (width div 2), getmaxy - 120,
(getmaxx div 2) + (width div 2), getmaxy - 20);

if (posX + Rmax + dx > (getmaxx div 2) + (width div 2))
or
(posX - Rmax + dx < (getmaxx div 2) - (width div 2))
then dx := -dx;
posX := posX + dx;
angle := angle + dx;
draw;
delay(30);
end;

readln;
closegraph
end.
Вот и все... При желании можно еще и оптимизировать, чтобы меньше вычислений выполнялось.
yakudza_m
ВОЛЬВО!!!
вот это умище!!!!
мне б такое...
всё...с меня ПИВО...ЕЩЕ РАЗ СПАСИБО!!!
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.