Advertisement
dmilicev

lets_drive_rectangle_v1.c

Oct 26th, 2019
289
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 19.67 KB | None | 0 0
  1. /*
  2.  
  3.     lets_drive_rectangle_v1.c
  4.  
  5. It drives a rectangle in eight directions.
  6.  
  7. Author Dragan Milicev
  8. https://web.facebook.com/dmilicev
  9.  
  10. Tested on Windows 7.
  11. Let me know of any errors (bugs) in the code you encountered, please.
  12.  
  13. To see Ascii codes for keyboard keys try
  14.  key_codes_with_getch()_v1.c
  15. https://pastebin.com/CTb71BSc
  16.  
  17. To see demonstrations of print speed in console window try
  18.  hollow rectangle pattern v2.c
  19. https://pastebin.com/c0jWaxas
  20.  
  21. You can find all my C programs at Dragan Milicev's pastebin:
  22.     https://pastebin.com/u/dmilicev
  23.  
  24.  
  25. The solid rectangle can be driven in 8 directions:
  26.  
  27. UP          up arrow
  28. DOWN        down arrow
  29. LEFT        left arrow
  30. RIGHT       right arrow
  31.  
  32. UP_LEFT     Home        or  Q, q
  33. DOWN_LEFT   End         or  A, a
  34. UP_RIGHT    Page Up     or  W, w
  35. DOWN_RIGHT  Page Down   or  S, s
  36.  
  37. Key Escape ESC for quit.
  38.  
  39.  
  40. Example of keyboard control.
  41. Also numeric keypad can be used.
  42.  
  43. Example of work with pointers.
  44.  
  45. Example of passing a variable to the function by reference,
  46. so the function can change the value of that variable because
  47. it has address (pointer) of variable in memory.
  48.  
  49.     The beginning of the coordinate system is in the upper left UL corner
  50.     of the window and there is a point ( x, y ) = ( column, row ) = ( 0, 0 )
  51.     x is column, y is row.
  52.     Columns increase to the right and rows increase downwards,
  53.     starting with TL top left point of the console window (0, 0).
  54.  
  55.     Characteristic points of console window and rectangle are:
  56.     TL top left     (x, y) = ( 0, 0) = ( 0          ,           0 )
  57.     TR top right    (x, y) = (80, 0) = ( MAX_COLUMNS,           0 )
  58.     BL bottom left  (x, y) = (0, 25) = ( 0          ,    MAX_ROWS )
  59.     BR bottom right (x, y) = (80,25) = ( MAX_COLUMNS,    MAX_ROWS )
  60.  
  61.     If MAX_COLUMNS 80 and MAX_ROWS 25 exceed the your console window box,
  62.     try reducing them a little by changing the lines of code
  63.  
  64.     #define MAX_COLUMNS 80
  65.     #define MAX_ROWS    25
  66.  
  67.     Rectangle is defined with 4 arguments,
  68.     by top left TL point ( xTL, yTL ) and width and height (from TL point)
  69.  
  70.     rectangle ( xTL , yTL, width , height )
  71.  
  72.     width  is from xTL to the right
  73.     height is from yTL to the down
  74.  
  75. */
  76.  
  77.  
  78.  
  79. // ----------BEGIN OF PROGRAM--------------------------------------------------
  80.  
  81. #include <stdio.h>
  82. #include <conio.h>          // for _getch() and _getche()
  83. #include <string.h>         // for puts()
  84. #include <time.h>           // for clock()
  85. #include <windows.h>
  86. // tracking cursor all the time, for cursor position functions
  87. // gotoxy(x,y) , wherex() , wherey(), showcursor(), hidecursor()
  88.  
  89. #define SECOND 1000         // time for delay() in milliseconds
  90. #define MAX_COLUMNS 80      // of the console window
  91. #define MAX_ROWS    25      // of the console window
  92. #define T           0       // for delay(T), waiting for better view, T=1000 for 1 second
  93.  
  94. #define UP          72      // up arrow
  95. #define DOWN        80      // down arrow
  96. #define LEFT        75      // left arrow
  97. #define RIGHT       77      // right arrow
  98.  
  99. #define UP_LEFT     71      // Home
  100. #define UP_RIGHT    73      // Page Up
  101. #define DOWN_LEFT   79      // End
  102. #define DOWN_RIGHT  81      // Page Down
  103. #define ESC         27
  104.  
  105.  
  106.  
  107. // ----------CURSOR CONTROL FUNCTIONS------------------------------------------
  108.  
  109. // make console cursor invisible
  110. void hidecursor()
  111. {
  112.    HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
  113.    CONSOLE_CURSOR_INFO info;
  114.    info.dwSize = 20;
  115.    info.bVisible = FALSE;
  116.    SetConsoleCursorInfo(consoleHandle, &info);
  117. }
  118.  
  119. // make console cursor invisible
  120. void showcursor()
  121. {
  122.    HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
  123.    CONSOLE_CURSOR_INFO info;
  124.    info.dwSize = 20;
  125.    info.bVisible = TRUE;
  126.    SetConsoleCursorInfo(consoleHandle, &info);
  127. }
  128.  
  129. // place cursor at position ( x, y ) = ( column, row )
  130. void gotoxy( int column, int row )
  131. {
  132.     COORD coord;
  133.  
  134.     coord.X = column;
  135.     coord.Y = row;
  136.  
  137.     SetConsoleCursorPosition( GetStdHandle(STD_OUTPUT_HANDLE), coord );
  138. }
  139.  
  140. // return x coordinate (column) of current cursor position
  141. // on failure return -1
  142. int wherex()
  143. {
  144.     CONSOLE_SCREEN_BUFFER_INFO csbi;
  145.  
  146.     if (!GetConsoleScreenBufferInfo( GetStdHandle(STD_OUTPUT_HANDLE), &csbi ) )
  147.         return -1;
  148.  
  149.     return csbi.dwCursorPosition.X;
  150. }
  151.  
  152. // return y coordinate (row) of current cursor position
  153. // on failure return -1
  154. int wherey()
  155. {
  156.     CONSOLE_SCREEN_BUFFER_INFO csbi;
  157.  
  158.     if (!GetConsoleScreenBufferInfo( GetStdHandle( STD_OUTPUT_HANDLE ), &csbi ) )
  159.         return -1;
  160.  
  161.     return csbi.dwCursorPosition.Y;
  162. }
  163.  
  164. // END OF-----CURSOR CONTROL FUNCTIONS------------------------------------------
  165.  
  166.  
  167. // ----------FUNCTIONS TO PRINT HOLLOW AND SOLID RECTANGLE----------------------
  168.  
  169. // Function to print hollow rectangle with char ch, with puts(), 10 times faster than printf()
  170. // from cursor position row, column
  171. // rows     must be between 2 and MAX_ROWS-2    (the smallest rectangle has no interior space, only the sides of the frame)
  172. // columns  must be between 2 and MAX_COLUMNS-2 (the smallest rectangle has no interior space, only the sides of the frame)
  173. void print_hollow_rectangle(char ch, int column, int row, int howMuchColumns, int howMuchRows)
  174. {
  175.     int i;
  176.     char str1[MAX_COLUMNS+1];                   // str1 is string for first and last line of rectangle
  177.     char str2[MAX_COLUMNS+1];                   // str2 is string for middle lines of rectangle
  178.  
  179.     if( column + howMuchColumns < 1 )           // 2 for two vertical edges of the rectangle
  180.         howMuchColumns = 2;
  181.  
  182.     if( row + howMuchRows < 2 )                 // 2 for two horizontal edges of the rectangle
  183.         howMuchRows = 2;
  184.  
  185.     if( column + howMuchColumns > MAX_COLUMNS ) // if right side od rectangle greather then
  186.         howMuchColumns = MAX_COLUMNS - column;  // MAX_COLUMNS, then trunc it
  187.  
  188.     if( row + howMuchRows > MAX_ROWS - 1 )      // if bottom side od rectangle greather then
  189.         howMuchRows = MAX_ROWS - row;           // MAX_ROWS, then trunc it
  190.  
  191.  
  192.     for (i = 0; i < howMuchColumns; i++)        // creating string for first and last line of rectangle
  193.         str1[i] = ch;
  194.  
  195.     str1[i+1] = '\0';                           // end of first and last line string
  196.  
  197.                                                 // creating string for middle lines of rectangle
  198.     str2[0] = ch;                               // first left character of middle lines string
  199.     for (i = 1; i < howMuchColumns-1; i++)      // middle characters of middle lines are blanko (space, ' ')
  200.         str2[i] = ' ';
  201.     str2[i] = ch;                               // last right character of middle lines string
  202.     str2[i+1] = '\0';                           // end of middle lines string
  203.  
  204.                                                 // print rectangle
  205.     gotoxy( column, row );                      // move cursor to (column, row)
  206.     fputs(str1, stdout);                        // print string for first line of rectangle without '\n'
  207.  
  208.     for (i = 0; i < howMuchRows-2; i++)
  209.     {
  210.         gotoxy( column, row+i+1 );              // move cursor to (column, row+i+1)
  211.         fputs(str2, stdout);                    // print string for middle lines of rectangle without '\n'
  212.     }
  213.  
  214.     gotoxy( column, row+i+1 );                  // move cursor to (column, row+i+1)
  215.     fputs(str1, stdout);                        // print string for last line of rectangle without '\n'
  216. }
  217.  
  218.  
  219. // Function to print solid rectangle with char ch, with puts(), 10 times faster than printf()
  220. // from cursor position column, row
  221. // rows     must be between 2 and MAX_ROWS-2    (the smallest rectangle has no interior space, only the sides of the frame)
  222. // columns  must be between 2 and MAX_COLUMNS-2 (the smallest rectangle has no interior space, only the sides of the frame)
  223. void print_solid_rectangle(char ch, int column, int row, int howMuchColumns, int howMuchRows)
  224. {
  225.     int i;
  226.     char str[MAX_COLUMNS+1];                    // str is string for one line of rectangle
  227.  
  228.     if( column + howMuchColumns < 1 )
  229.         howMuchColumns = 2;                     // 2 for two vertical edges of the rectangle
  230.  
  231.     if( row + howMuchRows < 2 )
  232.         howMuchRows = 2;                        // 2 for two horizontal edges of the rectangle
  233.  
  234.     if( column + howMuchColumns > MAX_COLUMNS ) // if right side od rectangle greather then
  235.         howMuchColumns = MAX_COLUMNS - column;  // MAX_COLUMNS, then reduce it
  236.  
  237.     if( row + howMuchRows > MAX_ROWS - 1 )      // if bottom side od rectangle greather then
  238.         howMuchRows = MAX_ROWS - row;           // MAX_ROWS, then reduce it
  239.  
  240.     for (i = 0; i < howMuchColumns; i++)        // fill string str with characters of one rectangle line
  241.         str[i] = ch;
  242.  
  243.     str[i] = '\0';                              // end string str
  244.  
  245.     for (i = 0; i < howMuchRows; i++)           // print solid rectangle
  246.     {
  247.         gotoxy( column, row+i );                // move cursor to (column, row+i+1)
  248.         fputs(str, stdout);                     // print solid rectangle string  without '\n'
  249.     }
  250. }
  251.  
  252. // END OF---FUNCTIONS TO PRINT HOLLOW AND SOLID RECTANGLE----------------------
  253.  
  254.  
  255. // ----------FUNCTIONS TO MOVE SOLID RECTANGLE---------------------------------
  256.  
  257. // erase current solid rectangle on that place by overwritting it with char ' '
  258. // print new     solid rectangle one row up
  259. void move_solid_rectangle_up( char ch, int *column, int *row, int *howMuchColumns, int *howMuchRows )
  260. {
  261.     if( *row > 1 )  // if rectangle is below top line of console window frame
  262.     {               // erase current solid rectangle on that place by overwritting it with char ' '
  263.         print_solid_rectangle( ' ', *column, (*row)--, *howMuchColumns, *howMuchRows );
  264.                     // print new solid rectangle one row up
  265.         print_solid_rectangle(  ch, *column, *row, *howMuchColumns, *howMuchRows );
  266.     }
  267. }
  268.  
  269. // erase current solid rectangle on that place by overwritting it with char ' '
  270. // print new     solid rectangle one row down
  271. void move_solid_rectangle_down( char ch, int *column, int *row, int *howMuchColumns, int *howMuchRows )
  272. {                   // if rectangle is above the penultimate bottom line of the console window frame
  273.     if( *row < MAX_ROWS-(*howMuchRows)-1 )
  274.     {               // erase current solid rectangle on that place by overwritting it with char ' '
  275.         print_solid_rectangle( ' ', *column, (*row)++, *howMuchColumns, *howMuchRows );
  276.                     // print new solid rectangle one row down
  277.         print_solid_rectangle(  ch, *column, *row, *howMuchColumns, *howMuchRows );
  278.     }
  279. }
  280.  
  281. // erase current solid rectangle on that place by overwritting it with char ' '
  282. // print new     solid rectangle one column left
  283. void move_solid_rectangle_left( char ch, int *column, int *row, int *howMuchColumns, int *howMuchRows )
  284. {
  285.     if( *column > 1 )  // if rectangle is right from second column of console window frame
  286.     {               // erase current solid rectangle on that place by overwritting it with char ' '
  287.         print_solid_rectangle( ' ', (*column)--, *row, *howMuchColumns, *howMuchRows );
  288.                     // print new solid rectangle one column left
  289.         print_solid_rectangle(  ch, *column, *row, *howMuchColumns, *howMuchRows );
  290.     }
  291. }
  292.  
  293. // erase current solid rectangle on that place by overwritting it with char ' '
  294. // print new     solid rectangle one column right
  295. void move_solid_rectangle_right( char ch, int *column, int *row, int *howMuchColumns, int *howMuchRows )
  296. {                   // if rectangle is left from the penultimate right line of the console window frame
  297.     if( *column < MAX_COLUMNS-(*howMuchColumns)-1 )
  298.     {               // erase current solid rectangle on that place by overwritting it with char ' '
  299.         print_solid_rectangle( ' ', (*column)++, *row, *howMuchColumns, *howMuchRows );
  300.                     // print new solid rectangle one column right
  301.         print_solid_rectangle(  ch, *column, *row, *howMuchColumns, *howMuchRows );
  302.     }
  303. }
  304.  
  305.  
  306.  
  307. // erase current solid rectangle on that place by overwritting it with char ' '
  308. // print new     solid rectangle one row up and one column left
  309. void move_solid_rectangle_up_left( char ch, int *column, int *row, int *howMuchColumns, int *howMuchRows )
  310. {                                   // if rectangle is below top line of console window frame
  311.     if( *row > 1 && *column > 1)    // if rectangle is right from second column of console window frame
  312.     {               // erase current solid rectangle on that place by overwritting it with char ' '
  313.         print_solid_rectangle( ' ', (*column)--, (*row)--, *howMuchColumns, *howMuchRows );
  314.                     // print new solid rectangle one row up and one column left
  315.         print_solid_rectangle(  ch, *column, *row, *howMuchColumns, *howMuchRows );
  316.     }
  317. }
  318.  
  319. // erase current solid rectangle on that place by overwritting it with char ' '
  320. // print new     solid rectangle one row down and one column left
  321. void move_solid_rectangle_down_left( char ch, int *column, int *row, int *howMuchColumns, int *howMuchRows )
  322. {                   // if rectangle is above the penultimate bottom line of the console window frame
  323.                     // if rectangle is right from second column of console window frame
  324.     if( *row < MAX_ROWS-(*howMuchRows)-1 && *column > 1 )
  325.     {               // erase current solid rectangle on that place by overwritting it with char ' '
  326.         print_solid_rectangle( ' ', (*column)--, (*row)++, *howMuchColumns, *howMuchRows );
  327.                     // print new solid rectangle one row down and one column left
  328.         print_solid_rectangle(  ch, *column, *row, *howMuchColumns, *howMuchRows );
  329.     }
  330. }
  331.  
  332. // erase current solid rectangle on that place by overwritting it with char ' '
  333. // print new     solid rectangle one row down and one column right
  334. void move_solid_rectangle_down_right( char ch, int *column, int *row, int *howMuchColumns, int *howMuchRows )
  335. {                   // if rectangle is above the penultimate bottom line of the console window frame
  336.                     // if rectangle is left from the penultimate right line of the console window frame
  337.     if( *row < MAX_ROWS-(*howMuchRows)-1 && *column < MAX_COLUMNS-(*howMuchColumns)-1 )
  338.     {               // erase current solid rectangle on that place by overwritting it with char ' '
  339.         print_solid_rectangle( ' ', (*column)++, (*row)++, *howMuchColumns, *howMuchRows );
  340.                     // print new solid rectangle one row down and one column right
  341.         print_solid_rectangle(  ch, *column, *row, *howMuchColumns, *howMuchRows );
  342.     }
  343. }
  344.  
  345. // erase current solid rectangle on that place by overwritting it with char ' '
  346. // print new     solid rectangle one row up and one column right
  347. void move_solid_rectangle_up_right( char ch, int *column, int *row, int *howMuchColumns, int *howMuchRows )
  348. {                   // if rectangle is below top line of console window frame
  349.                     // if rectangle is left from the penultimate right line of the console window frame
  350.     if( *row > 1 && *column < MAX_COLUMNS-(*howMuchColumns)-1)
  351.     {               // erase current solid rectangle on that place by overwritting it with char ' '
  352.         print_solid_rectangle( ' ', (*column)++, (*row)--, *howMuchColumns, *howMuchRows );
  353.                     // print new solid rectangle one row up and one column right
  354.         print_solid_rectangle(  ch, *column, *row, *howMuchColumns, *howMuchRows );
  355.     }
  356. }
  357.  
  358. // END OF----FUNCTIONS TO MOVE SOLID RECTANGLE---------------------------------
  359.  
  360.  
  361. // ----------KEYBOARD CONTROL--------------------------------------------------
  362.  
  363. /*
  364.     Keyboard control:
  365.  
  366. The solid rectangle can be driven in 8 directions:
  367.  
  368. UP          up arrow
  369. DOWN        down arrow
  370. LEFT        left arrow
  371. RIGHT       right arrow
  372.  
  373. UP_LEFT     Home        or  Q, q
  374. DOWN_LEFT   End         or  A, a
  375. UP_RIGHT    Page Up     or  W, w
  376. DOWN_RIGHT  Page Down   or  S, s
  377.  
  378. Key Escape, ESC (27) for quit.
  379. */
  380. int keyboard_control()
  381. {
  382.     int column=35, row=10, howMuchColumns=6, howMuchRows=5;     // solid rectangle coordinates
  383.     char ch = '*';                                              // char to print rectangle
  384.     int choice;                                                 // for pressed key
  385.  
  386.     hidecursor();
  387.  
  388.     print_hollow_rectangle( ch, 0, 0, MAX_COLUMNS, MAX_ROWS ); // print console window frame
  389.  
  390.     print_solid_rectangle( ch, column, row, howMuchColumns, howMuchRows );
  391.  
  392.     while( 1 ) {                    // an infinite loop that exits with choice Ecsape, ESC (27)
  393.  
  394.         choice = _getch();                      // read the keyboard
  395.  
  396.         if( choice == 0 || choice == 224 )      // if is pressed function key with leading 0 or 224
  397.         {
  398.             choice = _getch();                  // let's empty that 0 or 224
  399.  
  400.             if( choice == UP )                  // if pressed up arrow
  401.             {
  402.                 move_solid_rectangle_up( ch, &column, &row, &howMuchColumns, &howMuchRows );
  403.             }
  404.  
  405.             if( choice == DOWN )                // if pressed down arrow
  406.             {
  407.                 move_solid_rectangle_down( ch, &column, &row, &howMuchColumns, &howMuchRows );
  408.             }
  409.  
  410.             if( choice == LEFT )                // if pressed left arrow
  411.             {
  412.                 move_solid_rectangle_left( ch, &column, &row, &howMuchColumns, &howMuchRows );
  413.             }
  414.  
  415.             if( choice == RIGHT )               // if pressed right arrow
  416.             {
  417.                 move_solid_rectangle_right( ch, &column, &row, &howMuchColumns, &howMuchRows );
  418.             }
  419.  
  420.             if( choice == UP_LEFT )             // if pressed Home
  421.             {
  422.                 move_solid_rectangle_up_left( ch, &column, &row, &howMuchColumns, &howMuchRows );
  423.             }
  424.  
  425.  
  426.             if( choice == DOWN_LEFT )           // if pressed End
  427.             {
  428.                 move_solid_rectangle_down_left( ch, &column, &row, &howMuchColumns, &howMuchRows );
  429.             }
  430.  
  431.             if( choice == UP_RIGHT )            // if pressed Page Up
  432.             {
  433.                 move_solid_rectangle_up_right( ch, &column, &row, &howMuchColumns, &howMuchRows );
  434.             }
  435.  
  436.             if( choice == DOWN_RIGHT )          // if pressed Page Down
  437.             {
  438.                 move_solid_rectangle_down_right( ch, &column, &row, &howMuchColumns, &howMuchRows );
  439.             }
  440.  
  441.         } // end of: if is pressed function key with leading 0 or 224
  442.         else    // if pressed ordinary keys
  443.         {
  444.             if( choice == 'Q' || choice == 'q' )    // if is pressed ordinary key Q or q
  445.             {
  446.                 move_solid_rectangle_up_left( ch, &column, &row, &howMuchColumns, &howMuchRows );
  447.             }
  448.  
  449.             if( choice == 'A' || choice == 'a' )    // if is pressed ordinary key A or a
  450.             {
  451.                 move_solid_rectangle_down_left( ch, &column, &row, &howMuchColumns, &howMuchRows );
  452.             }
  453.  
  454.             if( choice == 'W' || choice == 'w' )    // if is pressed ordinary key W or w
  455.             {
  456.                 move_solid_rectangle_up_right( ch, &column, &row, &howMuchColumns, &howMuchRows );
  457.             }
  458.  
  459.             if( choice == 'S' || choice == 's' )    // if is pressed ordinary key S or s
  460.             {
  461.                 move_solid_rectangle_down_right( ch, &column, &row, &howMuchColumns, &howMuchRows );
  462.             }
  463.  
  464.  
  465.             if( choice == ESC )                     // if is pressed ESC
  466.             {
  467.                 showcursor();                       // before exiting function
  468.                 return( choice );                   // end work
  469.             }
  470.  
  471.         } // end of: if pressed ordinary keys
  472.  
  473.     } // end of: while( 1 )
  474.  
  475.     showcursor();                                   // before exiting function
  476.     return( choice );                               // have to return something
  477. }
  478.  
  479. // END OF----KEYBOARD CONTROL--------------------------------------------------
  480.  
  481.  
  482. int main(void)
  483. {
  484.  
  485.     keyboard_control();
  486.  
  487.  
  488.     gotoxy( 0, MAX_ROWS );
  489.  
  490.     return 0;
  491. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement