diff --git a/du8/program b/du8/program new file mode 100644 index 0000000..d3754bb Binary files /dev/null and b/du8/program differ diff --git a/du8/program.c b/du8/program.c new file mode 100644 index 0000000..03fa5d4 --- /dev/null +++ b/du8/program.c @@ -0,0 +1,263 @@ +#include +#include +#include +#include +#include +#include + +#define DESIRED_WIDTH 70 +#define DESIRED_HEIGHT 25 + +WINDOW * g_mainwin; +int g_oldcur, g_score = 0, g_width, g_height; +typedef struct { + int x; + int y; +} pos; +pos fruit; + +// 2D array of all spaces on the board. +bool *spaces; + +// -------------------------------------------------------------------------- +// Queue stuff + +// Queue implemented as a doubly linked list +struct s_node +{ + pos *position; // **TODO: make this a void pointer for generality. + struct s_node *prev; + struct s_node *next; +} *front=NULL, *back=NULL; +typedef struct s_node node; + +// Returns the position at the front w/o dequeing +pos* peek( ) +{ + return front == NULL ? NULL : front->position; +} + +// Returns the position at the front and dequeues +pos* dequeue( ) +{ + node *oldfront = front; + front = front->next; + return oldfront->position; +} + +// Queues a position at the back +void enqueue( pos position ) +{ + pos *newpos = (pos*) malloc( sizeof( position ) ); + node *newnode = (node*) malloc( sizeof( node ) ); + + newpos->x = position.x; + newpos->y = position.y; + newnode->position = newpos; + + if( front == NULL && back == NULL ) + front = back = newnode; + else + { + back->next = newnode; + newnode->prev = back; + back = newnode; + } +} + +// End Queue stuff + +// Snake stuff + +// Writes text to a coordinate +void snake_write_text( int y, int x, char* str ) +{ + mvwaddstr( g_mainwin, y , x, str ); //add a string of characters to a curses window and advance cursor +} + +// Draws the borders +void snake_draw_board( ) +{ + int i; + for( i=0; inext; + free( n ); + } + endwin(); + exit(0); +} + +// Is the current position in bounds? +bool snake_in_bounds( pos position ) +{ + return position.y < g_height - 1 && position.y > 0 && position.x < g_width - 1 && position.x > 0; +} + +// 2D matrix of possible positions implemented with a 1D array. This maps +// the x,y coordinates to an index in the array. +int snake_cooridinate_to_index( pos position ) +{ + return g_width * position.y + position.x; +} + +// Similarly this functions maps an index back to a position +pos snake_index_to_coordinate( int index ) +{ + int x = index % g_width; + int y = index / g_width; + return (pos) { x, y }; +} + +// Draw the fruit somewhere randomly on the board +void snake_draw_fruit( ) +{ + attrset( COLOR_PAIR( 3 ) );//curses character and window attribute control routines + int idx; + do + { + idx = rand( ) % ( g_width * g_height ); + fruit = snake_index_to_coordinate( idx ); + } + while( spaces[idx] || !snake_in_bounds( fruit ) ); + snake_write_text( fruit.y, fruit.x, "F" ); +} + +// Handles moving the snake for each iteration +bool snake_move_player( pos head ) +{ + attrset( COLOR_PAIR( 1 ) ) ; + + // Check if we ran into ourself + int idx = snake_cooridinate_to_index( head ); + if( spaces[idx] ) + snake_game_over( ); + spaces[idx] = true; // Mark the space as occupied + enqueue( head );//Inserting at the end of a linked list, returning head of list + g_score += 10; + + // Check if we're eating the fruit + if( head.x == fruit.x && head.y == fruit.y ) + { + snake_draw_fruit( ); + g_score += 1000; + } + else + { + // Handle the tail + pos *tail = dequeue( ); + spaces[snake_cooridinate_to_index( *tail )] = false; + snake_write_text( tail->y, tail->x, " " ); + } + + // Draw the new head + snake_write_text( head.y, head.x, "S" ); + + // Update scoreboard + char buffer[25]; + sprintf( buffer, "%d", g_score ); + attrset( COLOR_PAIR( 2 ) ); + snake_write_text( g_height+1, 9, buffer ); + return true; + +} + +int main( int argc, char *argv[] ) +{ + int key = KEY_RIGHT; + if( ( g_mainwin = initscr() ) == NULL ) {//initscr-создает окно курсес + perror( "error initialising ncurses" );// для вывода ошибок + exit( EXIT_FAILURE ); + } + + // Set up + srand( time( NULL ) ); + noecho( ); + curs_set( 2 ); + halfdelay( 1 ); + keypad( g_mainwin, TRUE ); + g_oldcur = curs_set( 0 ); + start_color( ); + init_pair( 1, COLOR_RED, COLOR_BLACK ); + init_pair( 2, COLOR_GREEN, COLOR_BLACK ); + init_pair( 3, COLOR_YELLOW, COLOR_BLACK ); + init_pair( 4, COLOR_BLUE, COLOR_BLACK ); + init_pair( 5, COLOR_CYAN, COLOR_BLACK ); + init_pair( 6, COLOR_MAGENTA, COLOR_BLACK ); + init_pair( 7, COLOR_WHITE, COLOR_BLACK ); + getmaxyx( g_mainwin, g_height, g_width );//Robot with colors + + g_width = g_width < DESIRED_WIDTH ? g_width : DESIRED_WIDTH; + g_height = g_height < DESIRED_HEIGHT ? g_height : DESIRED_HEIGHT; + + // Set up the 2D array of all spaces + spaces = (bool*) malloc( sizeof( bool ) * g_height * g_width );//memory allocation + + snake_draw_board( ); + snake_draw_fruit( ); + pos head = { 5,5 }; + enqueue( head ); + + // Event loop + while( 1 ) + { + int in = getch( ); + if( in != ERR ) + key = in; + switch( key ) + { + case KEY_DOWN: + case 'j': + case 'J': + case 's': + case 'S': + head.y++; + break; + case KEY_RIGHT: + case 'l': + case 'L': + case 'd': + case 'D': + head.x++; + break; + case KEY_UP: + case 'k': + case 'K': + case 'w': + case 'W': + head.y--; + break; + case KEY_LEFT: + case 'h': + case 'H': + case 'a': + case 'A': + head.x--; + break; + + } + if( !snake_in_bounds( head ) ) + snake_game_over( ); + else + snake_move_player( head ); + } + snake_game_over( ); +} \ No newline at end of file