/* Copyright (C) 2016-2019 The University of Notre Dame This software is distributed under the GNU General Public License. See the file LICENSE for details. */ #include "library/string.h" #include "library/syscalls.h" #include "library/stdio.h" #include "library/nwindow.h" #define SNAKE_MAX 128 #define THICK 5 struct coords { int x; int y; }; struct nwindow *nw = 0; int randint(int min, int max) { // Could be a lot better but at the moment it works uint32_t tm; syscall_system_time(&tm); int state = tm; if(state % 5 == 0) { state += 50000; } else if(state % 4 == 0) { state += 1000; } else if(state % 3 == 0) { state += 10000; } else if(state % 2 == 0) { state += 25000; } else { state += 16000; } int diff = max - min; return state % diff + min; } void init_snake_coords(struct coords *snake, int *length, int xsteps, int ysteps ) { *length = 3; snake[0].x = xsteps/2; snake[0].y = ysteps/2; int i; for(i=1;i<*length++;i++) { snake[i].x = snake[i-1].x-1; snake[i].y = snake[0].y; } } void scaled_rect( struct nwindow *nw, int x, int y, int scale ) { nw_rect(nw,x*scale,y*scale,scale,scale); } void update_snake(struct coords *snake, int *length, int x, int y, int grow ) { int i; if(!grow) { nw_fgcolor(nw,0,0,0); scaled_rect(nw,snake[*length-1].x,snake[*length-1].y,THICK); } *length += grow; for(i=*length-1;i>0;i--) { snake[i] = snake[i-1]; } snake[0].x = x; snake[0].y = y; nw_fgcolor(nw,0,255,0); scaled_rect(nw,x,y,THICK); } int check_snake_collision( struct coords *snake, int length ) { int i; for(i=1;ix = randint(0,xsteps); apple->y = randint(0,ysteps); nw_fgcolor(nw,255, 0, 0); scaled_rect(nw,apple->x,apple->y,THICK); } int move_snake(struct coords *snake, int *length, struct coords *apple, int xsteps, int ysteps, char dir) { int x, y; switch (dir) { case 'a': x = snake[0].x - 1; y = snake[0].y; break; case 'd': x = snake[0].x + 1; y = snake[0].y; break; case 'w': x = snake[0].x; y = snake[0].y - 1; break; case 's': x = snake[0].x; y = snake[0].y + 1; break; default: x = snake[0].x; y = snake[0].y; break; } if(x<=-1 || x>=xsteps || y<=-1 || y>=ysteps ) return -1; if(x==apple->x && y==apple->y) { update_snake(snake, length, x, y, 5); init_apple(apple,xsteps,ysteps); } else { update_snake(snake, length, x, y, 0); } if(check_snake_collision(snake,*length)) { return -1; } return 0; } int main(int argc, char *argv[]) { struct coords snake[SNAKE_MAX]; struct coords apple; int snake_length = 3; int speed = 100; nw = nw_create_default(); int width = nw_width(nw); int height = nw_height(nw); // Board dimensions in snake blocks int xsteps = width / THICK; int ysteps = height / THICK; nw_clear(nw,0, 0, width, height); nw_string(nw,THICK * 3, THICK * 4, "Press any key to start"); nw_string(nw,THICK * 3, THICK * 8, "w: up"); nw_string(nw,THICK * 3, THICK * 12, "s: down"); nw_string(nw,THICK * 3, THICK * 16, "a: left"); nw_string(nw,THICK * 3, THICK * 20, "d: right"); nw_flush(nw); char c = nw_getchar(nw,1); while(1) { char dir = 'd'; nw_clear(nw,0,0,width,height); init_snake_coords(snake, &snake_length, xsteps, ysteps); init_apple(&apple,xsteps, ysteps); while(1) { syscall_process_sleep(speed); c = nw_getchar(nw,0); if((c == 'a' && dir == 'd') || (c == 'd' && dir == 'a') || (c == 'w' && dir == 's') || (c == 's' && dir == 'w')) { // reject conflicting input } else if(c == 'w' || c == 'a' || c == 's' || c == 'd') { dir = c; } else if(c=='q') { break; } int status = move_snake(snake, &snake_length, &apple, xsteps, ysteps, dir); nw_flush(nw); if(status<0) break; } nw_flush(nw); nw_fgcolor(nw,255, 255, 255); nw_string(nw,THICK * 3, THICK * 4, "You lose!"); nw_string(nw,THICK * 3, THICK * 8, "Enter q to quit"); nw_string(nw,THICK * 3, THICK * 12, "Press any key to start"); nw_flush(nw); c = nw_getchar(nw,1); if (c == 'q') return 0; } }