在 V 形 (ADA) 中绘制带有对角十字的旗帜

Drawing a flag with diagonal crosses in a V-Shape (ADA)

我又求助于 Whosebug。以前在这里得到过帮助,我希望能再次得到同样友好的帮助。我有一个任务,我需要在 ADA 中绘制一面旗帜(包括它周围的盒子状形状和中间的 V 形十字)。我设法制作了盒子和大约一半的十字架。谁能告诉我如何最简单地填写其余的十字架?

应该是V型的,像这样:

+   +
 + +
  + 

等等

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;

procedure exercise2 is
   subtype Cross_Rows is Integer range 2..80;
   Rows       : Cross_Rows;
   Flag_Width : Cross_Rows;
   Left       : Positive;
   Right      : Positive;

   procedure Row_Get (Rows: out Cross_Rows) is

      begin

      Put("Enter the number of cross rows (min is 3): ");
      Get(Rows);
      Skip_Line;
      end Row_Get;

      procedure Print_Top (Rows: in Cross_Rows) is

      begin

     Flag_Width := (Rows  * 2) + 4;

     Put("+");
     for Col in 1..Flag_Width-3 loop
        Put("-");
     end loop;
     Put("+");
     New_Line;

      end Print_Top;

      procedure Print_Middle (Rows: in Cross_Rows) is

      begin

     Left := 1;
     Right := Flag_Width - 5;
     for R in 1..Rows loop
        Put("! ");
        for C in 1..Flag_Width - 4 loop
           if C = Left or else C = Right then
          Put("+");
           else
          Put(" ");
           end if;
        end loop;
        Left := Left + 1;
        Right := Right - 1;

        Put_Line("!");
     end loop;

      end Print_Middle;

      procedure Print_Bottom (Rows: in Cross_Rows) is

      begin

     Flag_Width := (Rows  * 2) + 4;

     Put("+");
     for C in 1..Flag_Width-3 loop
        Put("-");
     end loop;
     Put_Line("+");

      end Print_Bottom;

begin
   Row_Get(Rows);
   Print_Top(Rows);
   Print_Middle(Rows);
   Print_Bottom(Rows);
end exercise2;

编辑:感谢吉姆罗杰斯,我设法编辑了我的程序来绘制旗帜。不幸的是,它并不完全是它的本意,因为顶部十字架应该接触两侧而不是像现在这样间隔开。另外,主程序和子程序不能超过 15 行,所以我把它们分开了。

最小的旗帜应该是这样的。我将尝试使用他的代码来实现这一目标。但任何帮助都是有价值的! :)

n=1
+---+
!+ +!
! + !
+---+

n=2
+-----+
!+   +!
! + + !
!  +  !
+-----+

您需要跟踪“+”字符的左列和右列,在每次循环迭代中增加左列位置并减少右列位置以打印十字。 以下程序适用于从 3 到 80 的任意行数的十字。

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;

procedure Main is
   subtype Cross_Rows is Integer range 3..80;
   Rows       : Cross_Rows;
   Flag_Width : Cross_Rows;
   Left       : Positive;
   Right      : Positive;

begin
   Put("Enter the number of cross rows (minimum is 3): ");
   Get(Rows);
   Skip_Line;
   Flag_Width := (Rows  * 2) + 4;
   -- Print top row of flag boundary
   for Col in 1..Flag_Width loop
      Put("-");
   end loop;
   Put("-");
   New_Line;
   -- Print empty row below top flag boundary
   Put("-  ");
   for C in 3..Flag_Width - 2 loop
      Put(" ");
   end loop;
   Put_Line(" -");

   -- Print crosses
   Left := 1;
   Right := Flag_Width - 5;
   for R in 1..Rows loop
      Put("-  ");
      for C in 1..Flag_Width - 4 loop
         if C = Left or else C = Right then
            Put("+");
         else
            Put(" ");
         end if;
      end loop;
         Left := Left + 1;
         Right := Right - 1;

      Put_Line(" -");
   end loop;
   -- Print bottom flag rows
   Put("-  ");
   for C in 3..Flag_Width - 2 loop
      Put(" ");
   end loop;
   Put_Line(" -");
   for C in 1..Flag_Width loop
      Put("-");
   end loop;
   Put_Line("-");
end Main;

示例输出为:

Enter the number of cross rows (minimum is 3): 7
-------------------
-                 -
-  +           +  -
-   +         +   -
-    +       +    -
-     +     +     -
-      +   +      -
-       + +       -
-        +        -
-                 -
-------------------

您还可以选择一种模式定义(此处:标志)和输出机制几乎完全分离的方法。这种方法还允许您并行化标志渲染,以防您需要渲染非常非常大的标志 ;-):

main.adb

with Ada.Text_IO; use Ada.Text_IO;

procedure Main is

   N : constant := 2;

   Width  : constant := 3 + 2 * N;
   Height : constant := 3 + 1 * N;

   type Screen_X is new Natural range 0 .. Width  - 1;
   type Screen_Y is new Natural range 0 .. Height - 1;

   -------------
   -- Pattern --
   -------------

   function Pattern (X : Screen_X; Y : Screen_Y) return Character is

      Is_Border_LR : constant Boolean :=
        X = Screen_X'First or else X = Screen_X'Last;

      Is_Border_TB : constant Boolean :=
        Y = Screen_Y'First or else Y = Screen_Y'Last;

      --  The V-Shape is based on the implicit function:
      --
      --    abs (X - X0) + (Y - Y0) = 0

      X0 : constant := (Screen_X'Last + Screen_X'First) / 2;
      Y0 : constant :=  Screen_Y'Last - 1;     

      Is_V_Shape : constant Boolean :=
        Integer (abs (X - X0)) + Integer (Y - Y0) = 0;

   begin

      if Is_Border_LR and Is_Border_TB then
         return '+';
      elsif Is_Border_LR then
         return '!';
      elsif Is_Border_TB then
         return '-';
      elsif Is_V_Shape then
         return '+';
      else
         return ' ';
      end if;

   end Pattern;

begin

   --  The Render loop.

   for Y in Screen_Y loop
      for X in Screen_X loop
         Put (Pattern (X, Y));
      end loop;
      New_Line;
   end loop;

end Main;

输出 (N = 1)

$ ./main
+---+
!+ +!
! + !
+---+

输出 (N = 2)

$ ./main
+-----+
!+   +!
! + + !
!  +  !
+-----+

另一种方法使用 Ada.Text_Io 中的 Set_Col 过程。 Set_Col 将光标设置到当前输出行中的指定列号。例如,如果光标从位置 1 开始并且您调用 Set_Col(10),该过程将输出 9 个空白字符并将列号设置为 10。然后您可以在第 10 列开始写入非空白输出。

with Ada.Text_Io; use Ada.Text_IO;
with Ada.Integer_Text_Io; use Ada.Integer_Text_IO;

procedure V_columns is
   subtype Cross_Rows is Integer range 3..80;

   Rows       : Cross_Rows;
   Flag_Width : Positive;
   Left       : Positive;
   Right      : Positive;
begin
   Put("Enter the number of cross rows (minimum is 3): ");
   Get(Rows);
   Skip_Line;
   Flag_Width := (Rows  * 2) + 4;
   -- Print top row of flag boundary
   for Col in 1..Flag_Width loop
      Put("-");
   end loop;
   New_Line;
   -- Print empty row below top flag boundary
   Set_Col(1);
   Put("|");
   Set_Col(Positive_Count(Flag_Width));
   Put_Line("|");

   -- Print crosses
   Left := 3;
   Right := Flag_Width - 3;
   for R in 1..Rows loop
      Set_Col(1);
      Put("|");
      if Left < Right then
         Set_Col(Positive_Count(Left));
         Put("+");
         Set_Col(Positive_Count(Right));
         Put("+");
      else
         Set_Col(Positive_Count(Right));
         Put("+");
      end if;
      Set_Col(Positive_Count(Flag_Width));
      Put("|");
      New_Line;
      Left := Left + 1;
      Right := Right - 1;
   end loop;
   -- Print bottom flag rows
   Set_Col(1);
   Put("|");
   Set_Col(Positive_Count(Flag_Width));
   Put_Line("|");
   for C in 1..Flag_Width loop
      Put("-");
   end loop;
   New_Line;
end V_Columns;

程序的输出是:

Enter the number of cross rows (minimum is 3): 7
------------------
|                |
| +           +  |
|  +         +   |
|   +       +    |
|    +     +     |
|     +   +      |
|      + +       |
|       +        |
|                |
------------------