Загрузил(а) файлы в 'du8'
This commit is contained in:
parent
e4d549530c
commit
53c54eac8e
BIN
du8/program
Normal file
BIN
du8/program
Normal file
Binary file not shown.
263
du8/program.c
Normal file
263
du8/program.c
Normal file
@ -0,0 +1,263 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <curses.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#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; i<g_height; i++ )
|
||||||
|
{
|
||||||
|
snake_write_text( i, 0, "X" );
|
||||||
|
snake_write_text( i, g_width-1, "X" );
|
||||||
|
}
|
||||||
|
for( i=1; i<g_width-1; i++ )
|
||||||
|
{
|
||||||
|
snake_write_text( 0, i, "X" );
|
||||||
|
snake_write_text( g_height-1, i, "X" );
|
||||||
|
}
|
||||||
|
snake_write_text( g_height+1, 2, "Score:" );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resets the terminal window and clears up the mem
|
||||||
|
void snake_game_over( )
|
||||||
|
{
|
||||||
|
free( spaces );
|
||||||
|
while( front )
|
||||||
|
{
|
||||||
|
node *n = front;
|
||||||
|
front = front->next;
|
||||||
|
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( );
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user