Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- self_driven_rectangle_v1.c by Dragan Milicev
- The solid rectangle can be moved automatic or manualy in 8 directions:
- UP up arrow
- DOWN down arrow
- LEFT left arrow
- RIGHT right arrow
- UP_LEFT Home or Q, q
- DOWN_LEFT End or A, a
- UP_RIGHT Page Up or W, w
- DOWN_RIGHT Page Down or S, s
- Key Escape ESC for quit program.
- Also numeric keypad can be used (NumLock must be off).
- Example of keyboard control.
- Example of work with pointers.
- https://www.tutorialspoint.com/cprogramming/c_pointers.htm
- Example of structure.
- https://www.tutorialspoint.com/cprogramming/c_structures.htm
- Example of passing a variable to the function by reference,
- so the function can change the value of that variable because
- it has address (pointer) of variable in memory.
- The beginning of the coordinate system is in the upper left UL corner
- of the window and there is a point ( x, y ) = ( xTL, yTL ) = ( 0, 0 )
- x is row, y is column.
- Columns increase to the right and rows increase downwards,
- starting with TL top left point of the console window (0, 0).
- Characteristic points of console window and rectangle are:
- TL top left (x, y) = ( 0, 0) = ( 0 , 0 )
- TR top right (x, y) = (80, 0) = ( MAX_COLUMNS, 0 )
- BL bottom left (x, y) = (0, 24) = ( 0 , MAX_ROWS )
- BR bottom right (x, y) = (80,24) = ( MAX_COLUMNS, MAX_ROWS )
- If MAX_COLUMNS 80 and MAX_ROWS 24 exceed the your console window box,
- try reducing them a little by changing the lines of code
- #define MAX_COLUMNS 80
- #define MAX_ROWS 24
- Rectangle is defined with 4 arguments,
- by top left TL point ( xTL, yTL ) and width and height (from TL point)
- rectangle ( xTL , yTL, width , height )
- width is from xTL to the right
- height is from yTL to the down
- Rectangle can be moved (controled) in eight directions,
- manualy by keyboard or
- automatic by program using random numbers generated by the rand() function.
- This Control mode (int control) can be changed with the key C.
- Default value is Control = AUTOMATIC and it can be
- MANUAL 0
- AUTOMATIC 1
- Directions of movement are:
- U UP 72
- D DOWN 80
- L LEFT 75
- R RIGHT 77
- UL UP_LEFT 71
- UR UP_RIGHT 73
- DL DOWN_LEFT 79
- DR DOWN_RIGHT 81
- Use keys on numpad (NumLock must be off):
- UL U UR
- L R
- DL D DR
- Touch point (int tp) is the point of contact of the rectangle with the wall and may be:
- tp NO 0 default value, there is no contact of the rectangle with the wall
- _
- tp UP 72 ^
- tp DOWN 80 _
- tp LEFT 75 |<
- tp RIGHT 77 >|
- Key B switch Beep mode (sound of rectangle touching the wall) on/off.
- Mode of movement (int modeOfMovement) of rectangle can be:
- NATURAL 0 bounce angles are equal to bump angles
- When rectangle hitting a wall,
- the bounce angle is equal to the bump angle,
- considering where the touch point is.
- This is default value modeOfMovement = NATURAL
- RANDOM 1 random bounce angles
- after contact of the rectangle with the wall,
- a new direction of movement of the rectangle is accidental.
- Opposite directions for bounce angles, considering where the touch point (tp) is, are:
- Bump tp Bounce
- direction direction
- _
- U U ^ D
- D D _ U
- L L |< R
- R R >| L
- _
- UL U ^ DL
- UL L |< UR
- _
- UR U ^ DR
- UR R >| UL
- DL L |< DR
- DL D _ UL
- DR D _ UR
- DR R >| DL
- The Speed (int speed) of movement of the rectangle can be changed
- using the + or - keys on the numeric keypad.
- Speed can be from 0 (the slowest) to 9 (the fastest), including limits.
- Default value is speed = 4.
- The higher the speed, the shorter is the wait time and vice versa, by using the formula
- wait( T * (10 - speed) );
- Struct rectangle with default values is:
- struct Rectangle {
- char ch; // char to print rectangle
- int xTL; // x (column) coordinate of (TL) top left corner of rectangle
- int yTL; // y (row) coordinate of (TL) top left corner of rectangle
- int width; // width (number of columns from x to left) of rectangle
- int height; // height (number of rows from y to down) of rectangle
- int direction; // direction of movement of rectangle
- int speed; // speed of moving rectangle, can be from 1 (the slowest) to 9 (the fastest)
- int tp; // touch point is the point of contact of the rectangle with the wall
- int beep; // Beep when touching a rectangle with a wall
- int control; // Control mode of movement of rectangle, can be AUTOMATIC or MANUAL
- int modeOfMovement; // mode of Movement of rectangle, can be NATURAL or RANDOM
- };
- To further develop the program:
- Try to change this program and make it a game of tennis.
- A player can play alone against a computer (one racquet)
- or two players against each other (two racquets on the left and right sides of the court).
- In the first case, allow 5 balls (small solid rectangle).
- The ball is lost if it hits the wall behind the racket.
- In the second case, count the points and play for example up to 11.
- Display the current score in the top line of the field.
- Author Dragan Milicev
- https://web.facebook.com/dmilicev
- Tested on Windows 7. Coded in CodeBlocks v16.01.
- Let me know of any errors (bugs) in the code you encountered, please.
- To see Ascii codes for keyboard keys try
- key_codes_with_getch()_v1.c
- https://pastebin.com/CTb71BSc
- and
- keyboard_ascii_codes_with_kbhit()_v1.c
- https://pastebin.com/7whsRfyj
- To see demonstrations of print speed in console window try
- hollow rectangle pattern v2.c
- https://pastebin.com/c0jWaxas
- To see demonstrations of generate random integer numbers
- between lower and upper, including them try
- generator_of_random_numbers_v1.c
- https://pastebin.com/yrzquvWT
- You can find all my C programs at Dragan Milicev's pastebin:
- https://pastebin.com/u/dmilicev
- https://www.facebook.com/dmilicev
- */
- // ----------BEGIN OF PROGRAM--------------------------------------------------
- #include <stdio.h>
- //#include <stlib.h> // RAND_MAX is defined in stdlib.h
- #include <conio.h> // for _getch() and _getche()
- #include <string.h> // for puts()
- #include <time.h> // for random numbers, for function rand()
- #include <windows.h> // tracking cursor all the time, for cursor position functions
- // gotoxy(x,y) , wherex() , wherey(), showcursor(), hidecursor()
- #define MAX_COLUMNS 80 // of the console window
- #define MAX_ROWS 24 // of the console window
- #define T 10 // for delay(T), waiting for speed, T=1000 for 1 second
- #define OFF 0 // for Beep mode
- #define ON 1 // for Beep mode
- #define UP 72 // up arrow
- #define DOWN 80 // down arrow
- #define LEFT 75 // left arrow
- #define RIGHT 77 // right arrow
- #define UP_LEFT 71 // Home
- #define UP_RIGHT 73 // Page Up
- #define DOWN_LEFT 79 // End
- #define DOWN_RIGHT 81 // Page Down
- #define ESC 27 // to end the program
- #define MANUAL 0 // Control mode
- #define AUTOMATIC 1 // Control mode
- #define NATURAL 0 // mode of Movement, bounce angles are equal to bump angles
- #define RANDOM 1 // mode of Movement, random bounce angles
- struct Rectangle {
- char ch; // char to print rectangle
- int xTL; // x (column) coordinate of (TL) top left corner of rectangle
- int yTL; // y (row) coordinate of (TL) top left corner of rectangle
- int width; // width (number of columns from x to left) of rectangle
- int height; // height (number of rows from y to down) of rectangle
- int direction; // direction of movement of rectangle
- int speed; // speed of moving rectangle, can be from 0 (the slowest) to 9 (the fastest)
- int tp; // touch point is the point of contact of the rectangle with the wall
- int beep; // Beep when touching a rectangle with a wall
- int control; // control mode of movement of rectangle, may be AUTOMATIC or MANUAL
- int modeOfMovement; // mode of movement of rectangle
- };
- // wait (do nothing) for time in milliseconds
- void wait( int milliseconds )
- {
- clock_t start_time = clock(); // get start time
- // looping (do nothing) till required time is not acheived
- while ( clock() < start_time + milliseconds )
- ; // do nothing
- }
- // generate and return random integer number between lower and upper, including them.
- int get_random_integer_from_lower_to_uppper( int lower, int upper )
- {
- // generate and return random number between 0 and upper-1
- //return( rand() % upper );
- // generate and return random number between 1 and upper
- //return( rand() % upper + 1 );
- // generate and return random integer number between lower and upper
- return( (rand() % (upper - lower + 1)) + lower );
- }
- // ----------CURSOR CONTROL FUNCTIONS------------------------------------------
- // make console cursor invisible
- void hidecursor()
- {
- HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
- CONSOLE_CURSOR_INFO info;
- info.dwSize = 20;
- info.bVisible = FALSE;
- SetConsoleCursorInfo(consoleHandle, &info);
- }
- // make console cursor invisible
- void showcursor()
- {
- HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
- CONSOLE_CURSOR_INFO info;
- info.dwSize = 20;
- info.bVisible = TRUE;
- SetConsoleCursorInfo(consoleHandle, &info);
- }
- // place cursor at position ( x, y ) = ( row, column )
- void gotoxy( int x, int y )
- {
- COORD coord;
- coord.X = x;
- coord.Y = y;
- SetConsoleCursorPosition( GetStdHandle(STD_OUTPUT_HANDLE), coord );
- }
- // return x coordinate (column) of current cursor position
- // on failure return -1
- int wherex()
- {
- CONSOLE_SCREEN_BUFFER_INFO csbi;
- if (!GetConsoleScreenBufferInfo( GetStdHandle(STD_OUTPUT_HANDLE), &csbi ) )
- return -1;
- return csbi.dwCursorPosition.X;
- }
- // return y coordinate (row) of current cursor position
- // on failure return -1
- int wherey()
- {
- CONSOLE_SCREEN_BUFFER_INFO csbi;
- if (!GetConsoleScreenBufferInfo( GetStdHandle( STD_OUTPUT_HANDLE ), &csbi ) )
- return -1;
- return csbi.dwCursorPosition.Y;
- }
- // END OF-----CURSOR CONTROL FUNCTIONS------------------------------------------
- // ----------FUNCTIONS TO PRINT HOLLOW AND SOLID RECTANGLE----------------------
- // Function to print hollow rectangle with char ch, with puts(), 10 times faster than printf()
- // from cursor position (x, y) = (row, column)
- // width must be between 2 and MAX_COLUMNS-2 (the smallest rectangle has no interior space, only the sides of the frame)
- // height must be between 2 and MAX_ROWS-2 (the smallest rectangle has no interior space, only the sides of the frame)
- void print_hollow_rectangle(char ch, int x, int y, int width, int height)
- {
- int i;
- char str1[MAX_COLUMNS+1]; // str1 is string for first and last line of rectangle
- char str2[MAX_COLUMNS+1]; // str2 is string for middle lines of rectangle
- if( x + width < 1 ) // 2 for two vertical edges of the rectangle
- width = 2;
- if( y + height < 2 ) // 2 for two horizontal edges of the rectangle
- height = 2;
- if( x + width > MAX_COLUMNS ) // if right side od rectangle greather then MAX_COLUMNS,
- width = MAX_COLUMNS - x; // then trunc it
- if( y + height > MAX_ROWS - 1 ) // if bottom side od rectangle greather then MAX_ROWS,
- height = MAX_ROWS - y; // then trunc it
- for (i = 0; i < width; i++) // creating string for first and last line of rectangle
- str1[i] = ch;
- str1[i+1] = '\0'; // end of first and last line string
- // creating string for middle lines of rectangle
- str2[0] = ch; // first left character of middle lines string
- for (i = 1; i < width-1; i++) // middle characters of middle lines are blanko (space, ' ')
- str2[i] = ' ';
- str2[i] = ch; // last right character of middle lines string
- str2[i+1] = '\0'; // end of middle lines string
- // print rectangle
- gotoxy( x, y ); // move cursor to (column, row)
- fputs(str1, stdout); // print string for first line of rectangle without '\n'
- for (i = 0; i < height-2; i++)
- {
- gotoxy( x, y+i+1 ); // move cursor to (column, row+i+1)
- fputs(str2, stdout); // print string for middle lines of rectangle without '\n'
- }
- gotoxy( x, y+i+1 ); // move cursor to (column, row+i+1)
- fputs(str1, stdout); // print string for last line of rectangle without '\n'
- }
- // Function to print solid rectangle with char R.ch, with puts(), 10 times faster than printf()
- // from cursor position (column, row) = (R.xTL, R.yTL)
- // width must be between 2 and MAX_ROWS-2 (the smallest rectangle has no interior space, only the sides of the frame)
- // height must be between 2 and MAX_COLUMNS-2 (the smallest rectangle has no interior space, only the sides of the frame)
- void print_solid_rectangle( struct Rectangle R )
- {
- int i;
- char str[MAX_COLUMNS+1]; // str is string for one line of rectangle
- if( R.xTL + R.width < 1 )
- R.width = 2; // 2 for two vertical edges of the rectangle
- if( R.yTL + R.height < 2 )
- R.height = 2; // 2 for two horizontal edges of the rectangle
- if( R.xTL + R.width > MAX_COLUMNS ) // if right side od rectangle greather then MAX_COLUMNS,
- R.width = MAX_COLUMNS - R.xTL; // then reduce it
- if( R.yTL + R.height > MAX_ROWS - 1 ) // if bottom side od rectangle greather then MAX_ROWS,
- R.height = MAX_ROWS - R.yTL; // then reduce it
- for (i = 0; i < R.width; i++) // fill string str with characters of one rectangle line
- str[i] = R.ch;
- str[i] = '\0'; // end string str
- for (i = 0; i < R.height; i++) // print solid rectangle
- {
- gotoxy( R.xTL, R.yTL+i ); // move cursor to (R.xTL, R.yTL+i+1)
- fputs(str, stdout); // print solid rectangle string without '\n'
- }
- }
- // Function to delete solid rectangle with char R.ch = ' ', with puts(), 10 times faster than printf()
- // from cursor position (column, row) = (R.xTL, R.yTL)
- // width must be between 2 and MAX_ROWS-2 (the smallest rectangle has no interior space, only the sides of the frame)
- // height must be between 2 and MAX_COLUMNS-2 (the smallest rectangle has no interior space, only the sides of the frame)
- void delete_solid_rectangle( struct Rectangle R )
- {
- int i;
- // print_solid_rectangle() and delete_solid_rectangle only differ along this line of code:
- R.ch = ' '; // to erase rectangle, we overwrite it with ' '
- char str[MAX_COLUMNS+1]; // str is string for one line of rectangle
- if( R.xTL + R.width < 1 )
- R.width = 2; // 2 for two vertical edges of the rectangle
- if( R.yTL + R.height < 2 )
- R.height = 2; // 2 for two horizontal edges of the rectangle
- if( R.xTL + R.width > MAX_COLUMNS ) // if right side od rectangle greather then MAX_COLUMNS,
- R.width = MAX_COLUMNS - R.xTL; // then reduce it
- if( R.yTL + R.height > MAX_ROWS - 1 ) // if bottom side od rectangle greather then MAX_ROWS,
- R.height = MAX_ROWS - R.yTL; // then reduce it
- for (i = 0; i < R.width; i++) // fill string str with characters of one rectangle line
- str[i] = R.ch;
- str[i] = '\0'; // end string str
- for (i = 0; i < R.height; i++) // print solid rectangle
- {
- gotoxy( R.xTL, R.yTL+i ); // move cursor to (R.xTL, R.yTL+i+1)
- fputs(str, stdout); // print solid rectangle string without '\n'
- }
- }
- // END OF---FUNCTIONS TO PRINT HOLLOW AND SOLID RECTANGLE----------------------
- // ----------FUNCTIONS TO MOVE SOLID RECTANGLE---------------------------------
- // erase current solid rectangle on that place by overwriting it with char ' '
- // print new solid rectangle one row up
- void move_solid_rectangle_up( struct Rectangle *R )
- {
- if( R->yTL > 1 ) // if rectangle is below top line of console window frame
- {
- delete_solid_rectangle( *R ); // erase current solid rectangle on that place by overwriting it with char ' '
- (R->yTL)--; // one row up
- print_solid_rectangle( *R ); // print new solid rectangle one row up
- }
- }
- // erase current solid rectangle on that place by overwriting it with char ' '
- // print new solid rectangle one row down
- void move_solid_rectangle_down( struct Rectangle *R )
- {
- if( R->yTL < MAX_ROWS-(R->width) ) // if rectangle is above the penultimate bottom line of the console window frame
- {
- delete_solid_rectangle( *R ); // erase current solid rectangle on that place by overwriting it with char ' '
- (R->yTL)++; // one row down
- print_solid_rectangle( *R ); // print new solid rectangle one row down
- }
- }
- // erase current solid rectangle on that place by overwriting it with char ' '
- // print new solid rectangle one column left
- void move_solid_rectangle_left( struct Rectangle *R )
- {
- if( R->xTL > 1 ) // if rectangle is right from second column of console window frame
- {
- delete_solid_rectangle( *R ); // erase current solid rectangle on that place by overwriting it with char ' '
- (R->xTL)--; // one column left
- print_solid_rectangle( *R ); // print new solid rectangle one column left
- }
- }
- // erase current solid rectangle on that place by overwriting it with char ' '
- // print new solid rectangle one column right
- void move_solid_rectangle_right( struct Rectangle *R )
- {
- if( R->xTL < MAX_COLUMNS-(R->width)-1 ) // if rectangle is left from the penultimate right line of the console window frame
- {
- delete_solid_rectangle( *R ); // erase current solid rectangle on that place by overwriting it with char ' '
- (R->xTL)++; // one column right
- print_solid_rectangle( *R ); // print new solid rectangle one column right
- }
- }
- // erase current solid rectangle on that place by overwriting it with char ' '
- // print new solid rectangle one row up and one column left
- void move_solid_rectangle_up_left( struct Rectangle *R )
- { // if rectangle is right from second column of console window frame and
- if( R->xTL > 1 && R->yTL > 1) // if rectangle is below top line of console window frame
- {
- delete_solid_rectangle( *R ); // erase current solid rectangle on that place by overwriting it with char ' '
- (R->xTL)--; // one column left
- (R->yTL)--; // one row up
- print_solid_rectangle( *R ); // print new solid rectangle one row up and one column left
- }
- }
- // erase current solid rectangle on that place by overwriting it with char ' '
- // print new solid rectangle one row down and one column left
- void move_solid_rectangle_down_left( struct Rectangle *R )
- { // if rectangle is right from second column of console window frame and
- // if rectangle is above the penultimate bottom line of the console window frame
- if( R->xTL > 1 && R->yTL < MAX_ROWS-(R->height)-1 )
- {
- delete_solid_rectangle( *R ); // erase current solid rectangle on that place by overwriting it with char ' '
- (R->xTL)--; // one column left
- (R->yTL)++; // one row down
- print_solid_rectangle( *R ); // print new solid rectangle one row down and one column left
- }
- }
- // erase current solid rectangle on that place by overwriting it with char ' '
- // print new solid rectangle one row down and one column right
- void move_solid_rectangle_down_right( struct Rectangle *R )
- { // if rectangle is left from the penultimate right line of the console window frame and
- // if rectangle is above the penultimate bottom line of the console window frame
- if( R->xTL < MAX_COLUMNS-(R->width)-1 && R->yTL < MAX_ROWS-(R->height)-1 )
- {
- delete_solid_rectangle( *R ); // erase current solid rectangle on that place by overwriting it with char ' '
- (R->xTL)++; // one column right
- (R->yTL)++; // one row down
- print_solid_rectangle( *R ); // print new solid rectangle one row down and one column right
- }
- }
- // erase current solid rectangle on that place by overwriting it with char ' '
- // print new solid rectangle one row up and one column right
- void move_solid_rectangle_up_right( struct Rectangle *R )
- { // if rectangle is below top line of console window frame and
- // if rectangle is left from the penultimate right line of the console window frame
- if( R->yTL > 1 && R->xTL < MAX_COLUMNS-(R->width)-1)
- {
- delete_solid_rectangle( *R ); // erase current solid rectangle on that place by overwriting it with char ' '
- (R->xTL)++; // one column right
- (R->yTL)--; // one row up
- print_solid_rectangle( *R ); // print new solid rectangle one row up and one column right
- }
- }
- // END OF----FUNCTIONS TO MOVE SOLID RECTANGLE---------------------------------
- // Print the speed status (1-9)
- void print_speed_status( struct Rectangle R )
- {
- gotoxy( 5, MAX_ROWS-1 );
- printf(" SPEED=%d ", R.speed);
- }
- // Print the Control status ( AUTOMATIC / MANUAL )
- void print_control_status( struct Rectangle R )
- {
- gotoxy( 20, MAX_ROWS-1 );
- if( R.control == AUTOMATIC)
- printf(" CONTROL=AUTOMATIC ");
- else
- printf(" CONTROL=MANUAL ***");
- }
- // Print the current sound mode ( ON / OFF )
- void print_beep_status( struct Rectangle R )
- {
- gotoxy( 45, MAX_ROWS-1 );
- if( R.beep == ON)
- printf(" BEEP=ON *");
- else
- printf(" BEEP=OFF ");
- }
- // Print the mode of movement status ( NATURAL / RANDOM )
- void print_mode_status( struct Rectangle R )
- {
- gotoxy( 61, MAX_ROWS-1 );
- if( R.modeOfMovement == NATURAL )
- printf(" MODE=NATURAL ");
- else
- printf(" MODE=RANDOM *");
- }
- // The first screen at the beginning of the program
- // shows the name of the program, the name of the author of the program,
- // the instruction manual for the program
- void welcome_screen(void)
- {
- printf("\n\n Program \"Self Driven Rectangle\" by Dragan Milicev \n\n"
- " https://web.facebook.com/dmilicev \n\n\n"
- " The solid rectangle can be moved automatic or manualy in 8 directions: \n\n"
- " UP up arrow \n\n"
- " DOWN down arrow \n\n"
- " LEFT left arrow \n\n"
- " RIGHT right arrow \n\n\n"
- " UP_LEFT Home or Q, q \n\n"
- " DOWN_LEFT End or A, a \n\n"
- " UP_RIGHT Page Up or W, w \n\n"
- " DOWN_RIGHT Page Down or S, s \n\n\n"
- " Key Escape ESC for quit program. \n\n"
- " Also numeric keypad can be used (NumLock must be off). \n\n\n"
- " + or - key to change the speed of rectangle \n\n"
- " B key changes Beep mode (sound of rectangle touching the wall) ( ON / OFF ) \n\n"
- " C key changes Control mode ( AUTOMATIC / MANUAL ) \n\n"
- " M key changes mode of Movement of rectangle ( NATURAL / RANDOM ) \n\n\n"
- );
- system("PAUSE"); // pause the screen
- system("CLS"); // clear that screen
- }
- // A message at the end of the program
- void good_bye_screen(void)
- {
- gotoxy( 0, MAX_ROWS );
- printf("\n\n That's All, Folks ! \n\n");
- }
- // How to automatic drive rectangle?
- // From current position, calculate and make one next move.
- // Based on the current direction, position of the touch point and
- // mode of movement, we choose new direction.
- int automatic_drive_rectangle( struct Rectangle *R )
- {
- // Based on the direction of movement of the rectangle,
- // we move the rectangle and check that it has reached the point of contact with the wall
- while( R->tp == 0 ) // while there is no touch point with wall
- { // keeps the same direction and check for rectangle contact with the wall
- switch( R->direction )
- {
- case UP:
- if( R->yTL > 1 )
- move_solid_rectangle_up( &(*R) );
- else
- R->tp = UP;
- break;
- case DOWN:
- if( R->yTL < MAX_ROWS - R->height -1 )
- move_solid_rectangle_down( &(*R) );
- else
- R->tp = DOWN;
- break;
- case LEFT:
- if( R->xTL > 1 )
- move_solid_rectangle_left( &(*R) );
- else
- R->tp = LEFT;
- break;
- case RIGHT:
- if( R->xTL < MAX_COLUMNS - R->width - 1 )
- move_solid_rectangle_right( &(*R) );
- else
- R->tp = RIGHT;
- break;
- case UP_LEFT:
- if( R->xTL > 1 && R->yTL > 1 )
- move_solid_rectangle_up_left( &(*R) );
- if( R->xTL == 1 )
- R->tp = LEFT;
- if( R->yTL == 1 )
- R->tp = UP;
- break;
- case UP_RIGHT:
- if( R->xTL < MAX_COLUMNS - R->width -1 && R->yTL > 1 )
- move_solid_rectangle_up_right( &(*R) );
- if( R->xTL == MAX_COLUMNS - R->width -1 )
- R->tp = RIGHT;
- if( R->yTL == 1 )
- R->tp = UP;
- break;
- case DOWN_LEFT:
- if( R->xTL > 1 && R->yTL < MAX_ROWS - R->height -1 )
- move_solid_rectangle_down_left( &(*R) );
- if( R->xTL == 1 )
- R->tp = LEFT;
- if( R->yTL == MAX_ROWS - R->height -1 )
- R->tp = DOWN;
- break;
- case DOWN_RIGHT:
- if( R->xTL < MAX_COLUMNS - R->width -1 && R->yTL < MAX_ROWS - R->height -1 )
- move_solid_rectangle_down_right( &(*R) );
- if( R->xTL == MAX_COLUMNS - R->width -1 )
- R->tp = RIGHT;
- if( R->yTL == MAX_ROWS - R->height -1 )
- R->tp = DOWN;
- break;
- default:
- break;
- } // switch( R->direction )
- // We calculate the waiting time based on the speed of the rectangle
- // The speed changes from 1 to 9, the waiting time changes from 9 to 1 times T
- wait( T * (10 - R->speed) );
- } // while( R->tp == 0 )
- // Now the rectangle touched the wall. Based on the current direction
- // and position of the touch point, we choose new direction:
- // First, make a sound: // For greater speeds there is a problem with sound,
- if( R->beep == ON ) // because the rectangle moves faster than the sound can complete
- printf("\a"); // The sound of the rectangle touching the wall
- /*
- Opposite directions for bounce angles, considering where the touch point (tp) is, are:
- Bump tp Bounce
- direction direction
- _
- U U ^ D
- D D _ U
- L L |< R
- R R >| L
- _
- UL U ^ DL
- UL L |< UR
- _
- UR U ^ DR
- UR R >| UL
- DL L |< DR
- DL D _ UL
- DR D _ UR
- DR R >| DL
- */
- // Choose bounce angles
- if ( R->modeOfMovement == NATURAL )
- { // Bounce angles are equal to bump angles.
- // When rectangle hitting a wall,
- // the bounce angle is equal to the bump angle,
- // considering where the touch point is.
- if(R->direction==UP && R->tp==UP) R->direction=DOWN;
- if(R->direction==DOWN && R->tp==DOWN) R->direction=UP;
- if(R->direction==LEFT && R->tp==LEFT) R->direction=RIGHT;
- if(R->direction==RIGHT && R->tp==RIGHT) R->direction=LEFT;
- if(R->direction==UP_LEFT && R->tp==UP) R->direction=DOWN_LEFT;
- if(R->direction==UP_LEFT && R->tp==LEFT) R->direction=UP_RIGHT;
- if(R->direction==UP_RIGHT && R->tp==UP) R->direction=DOWN_RIGHT;
- if(R->direction==UP_RIGHT && R->tp==RIGHT) R->direction=UP_LEFT;
- if(R->direction==DOWN_LEFT && R->tp==LEFT) R->direction=DOWN_RIGHT;
- if(R->direction==DOWN_LEFT && R->tp==DOWN) R->direction=UP_LEFT;
- if(R->direction==DOWN_RIGHT && R->tp==DOWN) R->direction=UP_RIGHT;
- if(R->direction==DOWN_RIGHT && R->tp==RIGHT) R->direction=DOWN_LEFT;
- }
- else // modeOfMovement == RANDOM
- { // Random bounce angles:
- // after contact of the rectangle with the wall,
- // a new direction of movement of the rectangle is accidental.
- // There are 8 directons of movement and because of that
- // we need random number form 1 to 8
- switch( get_random_integer_from_lower_to_uppper(1,8) )
- {
- case 1:
- R->direction=UP;
- break;
- case 2:
- R->direction=DOWN;
- break;
- case 3:
- R->direction=LEFT;
- break;
- case 4:
- R->direction=RIGHT;
- break;
- case 5:
- R->direction=UP_LEFT;
- break;
- case 6:
- R->direction=UP_RIGHT;
- break;
- case 7:
- R->direction=DOWN_LEFT;
- break;
- case 8:
- R->direction=DOWN_RIGHT;
- break;
- default:
- break;
- } // switch( get_random_integer_from_lower_to_uppper(1,8) )
- } // else // modeOfMovement == RANDOM
- R->tp = 0; // reset, now there is no contact of the rectangle with the wall
- // Now we have new direction and we are redy for next move.
- wait( T * (10 - R->speed) ); // waiting time, slowing down
- return 0;
- }
- // ----------KEYBOARD CONTROL--------------------------------------------------
- /*
- Keyboard control:
- The solid rectangle can be manualy moved in 8 directions:
- UP up arrow
- DOWN down arrow
- LEFT left arrow
- RIGHT right arrow
- UP_LEFT Home or Q, q
- DOWN_LEFT End or A, a
- UP_RIGHT Page Up or W, w
- DOWN_RIGHT Page Down or S, s
- Key Escape, ESC (27) for quit.
- */
- int keyboard_control(void)
- {
- int choice; // for pressed key
- struct Rectangle R;
- R.ch = '*'; // initial values for rectangle R
- R.xTL = 35; // starting position of hollow rectangle
- R.yTL = 10;
- R.width = 4; // dimension of solid rectangle
- R.height = 3;
- R.direction = UP_LEFT; // starting move of solid rectangle
- R.speed = 4; // speed can be from 1 to 10
- R.tp = 0; // there is no touch point of rectangle with wall
- R.beep = ON; // Beep mode is default ON
- R.control = AUTOMATIC; // Control mode of movement of rectangle, may be AUTOMATIC or MANUAL
- R.modeOfMovement = NATURAL; // mode of Movement of rectangle
- hidecursor();
- // print console window frame
- print_hollow_rectangle( '*', 0, 0, MAX_COLUMNS, MAX_ROWS );
- // Print default values
- print_speed_status( R ); // Print the initial speed for the first time
- print_control_status( R ); // Print the default Control mode for the first time
- print_beep_status( R ); // Print the default Beep mode for the first time
- print_mode_status( R ); // Print the default mode of Movement status for the first time
- print_solid_rectangle( R ); // starting position for solid rectangle
- while( 1 ) { // an infinite loop that exits with choice Ecsape, ESC (27)
- if ( R.control == AUTOMATIC ) // If the computer controls a rectangle
- {
- while( !_kbhit() ) // rotates in that loop until some key is pressed
- {
- automatic_drive_rectangle( &R ); // because no key was pressed
- }
- }
- choice = _getch(); // now key is pressed, read the keyboard
- if( choice == 0 || choice == 224 ) // if is pressed function key with leading 0 or 224
- {
- choice = _getch(); // let's empty that 0 or 224
- if( choice == UP ) // if pressed up arrow
- move_solid_rectangle_up( &R );
- if( choice == DOWN ) // if pressed down arrow
- move_solid_rectangle_down( &R );
- if( choice == LEFT ) // if pressed left arrow
- move_solid_rectangle_left( &R );
- if( choice == RIGHT ) // if pressed right arrow
- move_solid_rectangle_right( &R );
- if( choice == UP_LEFT ) // if pressed Home
- move_solid_rectangle_up_left( &R );
- if( choice == DOWN_LEFT ) // if pressed End
- move_solid_rectangle_down_left( &R );
- if( choice == UP_RIGHT ) // if pressed Page Up
- move_solid_rectangle_up_right( &R );
- if( choice == DOWN_RIGHT ) // if pressed Page Down
- move_solid_rectangle_down_right( &R );
- } // end of: if is pressed function key with leading 0 or 224
- else // if pressed ordinary key
- {
- if( choice == 'Q' || choice == 'q' ) // if is pressed ordinary key Q or q
- move_solid_rectangle_up_left( &R );
- if( choice == 'A' || choice == 'a' ) // if is pressed ordinary key A or a
- move_solid_rectangle_down_left( &R );
- if( choice == 'W' || choice == 'w' ) // if is pressed ordinary key W or w
- move_solid_rectangle_up_right( &R );
- if( choice == 'S' || choice == 's' ) // if is pressed ordinary key S or s
- move_solid_rectangle_down_right( &R );
- if( choice == '+' ) // The + key is pressed
- {
- if( R.speed < 9 )
- R.speed++; // we increase the speed
- print_speed_status( R ); // print the speed
- }
- if( choice == '-' ) // The - key is pressed
- {
- if( R.speed > 1 )
- R.speed--; // we decrease the speed
- print_speed_status( R ); // print the speed
- }
- if( choice == 'b' || choice == 'B' ) // The B key is pressed
- {
- if( R.beep == ON ) // we change Beep mode
- R.beep = OFF; // ( ON or OFF )
- else
- R.beep = ON;
- }
- if( R.speed > 7 ) // At higher speeds there is a problem with Beep
- R.beep=OFF; // because the rectangle moves faster than the sound can complete
- print_beep_status( R ); // print the Beep status
- if( choice == 'c' || choice == 'C' ) // The C key is pressed
- {
- if( R.control == AUTOMATIC ) // we change Control mode
- R.control = MANUAL; // ( AUTOMATIC or MANUAL )
- else
- R.control = AUTOMATIC;
- print_control_status( R ); // print the Control mode status
- }
- if( choice == 'm' || choice == 'M' ) // The M key is pressed
- {
- if( R.modeOfMovement == NATURAL ) // we change mode of Movement
- R.modeOfMovement = RANDOM; // ( NATURAL or RANDOM )
- else
- R.modeOfMovement = NATURAL;
- print_mode_status( R ); // print the mode of Movement status
- }
- if( choice == ESC ) // if is pressed ESC
- {
- showcursor(); // before exiting function
- return( choice ); // end of work, have to return something
- }
- } // end of: if pressed ordinary key
- } // end of: while( 1 )
- showcursor(); // before exiting function
- return( choice ); // end of work, have to return something
- }
- // END OF----KEYBOARD CONTROL--------------------------------------------------
- int main(void)
- {
- time_t t; // for random number generator
- // Intializes random number generator, should only be called once.
- srand((unsigned) time(&t));
- welcome_screen();
- keyboard_control();
- good_bye_screen();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement