LINUX.ORG.RU

Free Pascal программа в терминале

 ,


0

1

Упражняюсь в задачах, ранее написал програмку, которая отображает сетку звездочек 10x10 в центре экрана консоли. Символ # перемещается по периметру сетки по часовой стрелке с задержкой в 100 миллисекунд между каждым шагом. Пользователь может приостановить и возобновить анимацию, нажав пробел. Анимация продолжается до тех пор, пока пользователь не нажмет какую-либо клавишу. Программа использует модули SysUtils и Crt для различных функций, включая сон и clrscr. Процедура DrawGrid рисует сетку в заданной позиции x, y, а процедура MoveGrid анимирует движение символа # по периметру сетки.

Вот полный код:

program clrsrceen;
uses Crt, SysUtils;

const
  Width = 12;
  Height = 12;
  Delay = 100;
  GridWidth = 10;
  GridHeight = 10;
  GridBack = '*';
  GridRunner = '#';

procedure DrawGrid(x, y: Integer);
var
  i, j: Integer;
begin
  for i := 0 to GridHeight - 1 do begin
    GotoXY(x, y + i);
    for j := 0 to GridWidth - 1 do
      Write(GridBack);
  end;
end;

procedure MoveGrid(x, y: Integer);

  procedure Animate;
  var
    i: Integer;
  begin
    for i := 0 to GridWidth - 1 do begin
      GotoXY(x + i, y);
      Write(GridRunner);
      GotoXY(x + i, y);
      Sleep(Delay);
      Write(GridBack);
      if KeyPressed then Exit;
    end;
    for i := 0 to GridHeight - 1 do begin
      GotoXY(x + GridWidth - 1, y + i);
      Write(GridRunner);
      GotoXY(x + GridWidth - 1, y + i);
      Sleep(Delay);
      Write(GridBack);
      if KeyPressed then Exit;
    end;
    for i := GridWidth - 1 downto 0 do begin
      GotoXY(x + i, y + GridHeight - 1);
      Write(GridRunner);
      GotoXY(x + i, y + GridHeight - 1);
      Sleep(Delay);
      Write(GridBack);
      if KeyPressed then Exit;
    end;
    for i := GridHeight - 1 downto 0 do begin
      GotoXY(x, y + i);
      Write(GridRunner);
      GotoXY(x, y + i);
      Sleep(Delay);
      Write(GridBack);
      if KeyPressed then Exit;
    end;
  end;

begin
  while not KeyPressed do begin
    GotoXY(1, 1);
    Animate;
  end;
  if ReadKey = #0 then ReadKey;
end;

var
  x, y: Integer;
begin
  ClrScr;
  x := (ScreenWidth - GridWidth) div 2;
  y := (ScreenHeight - GridHeight) div 2;
  DrawGrid(x, y);
  MoveGrid(x, y);
  ClrScr;
end.

Потом возникла необходимость изменить так, чтобы программа закрывалась только нажатием Esc, на стрелки влево и вправо менялась скорость задержки и нажатием пробел менять направление движения решетки. вот что я сам попытался сделать. Но вот это не работает, хотя и компилируется, но теперь кнопки вообще безразличны программе. Подскажите как правильно сделать, и как переписать процедуру Animate без такого количества почти одинаковых блоков.

program clrscreenmode;
uses SysUtils, Crt;

const
   width      = 12;
   height     = 12;
   delay      = 100;
   gridWidth  = 10;
   gridHeight = 10;
   gridBack   = '*';
   gridRunner = '#';

var
  EscPressed: Boolean;

function IsEscPressed(): Boolean;
begin
  if (not EscPressed) and KeyPressed() then
    EscPressed := ReadKey() = #27;

  IsEscPressed := EscPressed;
end;

procedure DrawGrid(x, y	: integer);
var
   i, j	: integer;
begin
   for i := 0 to gridHeight - 1 do begin
      gotoXY(x, y + i);
      for j := 0 to gridWidth - 1 do
	 write(gridBack);
   end;
end;

procedure MoveGrid(x, y	: integer);

  procedure Animate(x, y: integer; forward: Boolean);
  var
   i	: integer;
  begin
   if forward then begin
      for i := 0 to gridWidth - 1 do begin
	 gotoXY(x + i, y);
	 write(gridRunner);
	 gotoXY(x + i, y);
	 sleep(delay);
	 write(gridBack);
	 if KeyPressed and (ReadKey = ' ') then forward := not forward;
	 if IsEscPressed then exit;
      end;
      for i := 0 to gridHeight - 1 do begin
	 gotoXY(x + gridWidth - 1, y + i);
	 write(gridRunner);
	 gotoXY(x + gridWidth - 1, y + i);
	 sleep(delay);
	 write(gridBack);
	 if KeyPressed and (ReadKey = ' ') then forward := not forward;
         if IsEscPressed then exit;
      end;
         for i := gridWidth - 1 downto 0 do begin
	 gotoXY(x + i, y + gridHeight - 1);
	 write(gridRunner);
	 gotoXY(x + i, y + gridHeight - 1);
	 sleep(delay);
	 write(gridBack);
	 if KeyPressed and (ReadKey = ' ') then forward := not forward;
	 if IsEscPressed then exit;
      end;
      for i := gridHeight - 1 downto 0 do begin
	 gotoXY(x, y + i);
	 write(gridRunner);
	 gotoXY(x, y + i);
	 sleep(delay);
	 write(gridBack);
	 if KeyPressed and (ReadKey = ' ') then forward := not forward;
	 if IsEscPressed then exit;
      end;
   end
   else begin
      for i := gridWidth - 1 downto 0 do begin
	 gotoXY(x + i, y);
	 write(gridRunner);
	 gotoXY(x + i, y);
	 sleep(delay);
	 write(gridBack);
	 if KeyPressed and (ReadKey = ' ') then forward := not forward;
	 if IsEscPressed then exit;
      end;
      for i := gridHeight - 1 downto 0 do begin
	 gotoXY(x, y + i);
	 write(gridRunner);
	 gotoXY(x, y + i);
	 sleep(delay);
	 write(gridBack);
	 if KeyPressed and (ReadKey = ' ') then forward := not forward;
         if IsEscPressed then exit;
      end;
      for i := 0 to gridWidth - 1 do begin
	 gotoXY(x + i, y + gridHeight - 1);
	 write(gridRunner);
	 gotoXY(x + i, y + gridHeight - 1);
	 sleep(delay);
	 write(gridBack);
	 if KeyPressed and (ReadKey = ' ') then forward := not forward;
	 if IsEscPressed then exit;
      end;
      for i := 0 to gridHeight - 1 do begin
	 gotoXY(x + gridWidth - 1, y + i);
	 write(gridRunner);
	 gotoXY(x + gridWidth - 1, y + i);
	 sleep(delay);
	 write(gridBack);
	 if KeyPressed and (ReadKey = ' ') then forward := not forward;
	 if IsEscPressed then exit;
      end;
   end;
end;

var
   forward: Boolean;
begin
   forward := True;
   repeat
      gotoXY(1, 1);
      Animate(x, y, forward);
      if KeyPressed and (ReadKey = ' ') then forward := not forward;
   until IsEscPressed();
end;

var
   x, y	: integer;
begin
   clrscr;
   x := (screenWidth - gridWidth) div 2;
   y := (screenHeight - gridHeight) div 2;
   DrawGrid(x, y);
   MoveGrid(x, y);
   clrscr;
end.


Последнее исправление: ilyaGor (всего исправлений: 1)

  1. Лучше спросить на форуме паскаля

  2. Если у тебя есть одинаковые блоки в программе, то ты их можешь вынести в отдельные функции. Код сократиться и мест где ты можешь накосячить станет меньше. Даже если в твоей функции 3 строчки, это лучше чем вот такая твоя портянка, которую ни кто читать не хочет. Вникать и тратить время всем тупо лень, а у тебя может зачет горит.

  3. Так же там все сильно зависит от версии паскаля, что там у тебя, турбо паскаль, lazarus, borland pascal, ABC или еще черт знает что. Но грубо говоря должен помочь код приведенный ниже или гугли про hook key in pascal.

Function КакТыТамНазватьЭтуФункциюХочешь;
var
    esc_pressed: Boolean;
    c: Char;
begin
    esc_pressed = false;
    while not esc_pressed do
    begin 
       { Если клавиша не нажата, то }
       while not KeyPressed do
           UpdateScreen; { Тут можешь свою анимацию рисовать}
       { Иначе узнай что там там за код кнопки }
       c:=ReadKey;
       { Переменную с можешь сравнивать уже с чем хочешь, с кодами стрелок или с esc, а потом прыгай в начало функции }
       if c = #27 then esc_pressed = true;
    end;
end;
AntonyRF ★★★★
()
Последнее исправление: AntonyRF (всего исправлений: 2)