From 6b5d621820e9d7a0bb63aa293d211160d61abcfe Mon Sep 17 00:00:00 2001 From: randomuser Date: Mon, 15 Aug 2022 18:42:26 -0500 Subject: [PATCH] improve anaconda.c make some changes to anaconda: -> fix memory leaks -> add tabs instead of spaces -> show score on screen -> adapt to different screen sizes --- c/anaconda.c | 297 +++++++++++++++++++++++++++++---------------------- 1 file changed, 171 insertions(+), 126 deletions(-) diff --git a/c/anaconda.c b/c/anaconda.c index fda09e7..2018e4c 100644 --- a/c/anaconda.c +++ b/c/anaconda.c @@ -8,15 +8,15 @@ #include typedef struct point { - double x; - double y; - struct point *next; + double x; + double y; + struct point *next; } point; typedef struct anaconda { - int score; - double rot; - struct point *chain; + int score; + double rot; + struct point *chain; } anaconda; Display *d; @@ -26,13 +26,13 @@ int s; GC gc; void xinit(void) { - d = XOpenDisplay(NULL); - s = DefaultScreen(d); - w = XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 100, 100, 1, - BlackPixel(d, s), WhitePixel(d, s)); - XSelectInput(d, w, ExposureMask | KeyPressMask | PointerMotionMask); - XMapWindow(d, w); - gc = XCreateGC(d, w, 0, NULL); + d = XOpenDisplay(NULL); + s = DefaultScreen(d); + w = XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 100, 100, 1, + BlackPixel(d, s), WhitePixel(d, s)); + XSelectInput(d, w, ExposureMask | KeyPressMask | PointerMotionMask); + XMapWindow(d, w); + gc = XCreateGC(d, w, 0, NULL); } /* thanks to @@ -41,162 +41,207 @@ void xinit(void) { */ int ccw(point *a, point *b, point *c) { - return (c->y - a->y) * (b->x - a->x) > - (b->y - a->y) * (c->x - a->x); + return (c->y - a->y) * (b->x - a->x) > + (b->y - a->y) * (c->x - a->x); } int intersect(point *a, point *b, point *c, point *d) { - return (ccw(a, c, d) != ccw(b, c, d)) && (ccw(a, b, c) != ccw(a, b, d)); + return (ccw(a, c, d) != ccw(b, c, d)) && (ccw(a, b, c) != ccw(a, b, d)); } int randrange(int b, int s) { - return rand() % (b - s + 1) + s; + return rand() % (b - s + 1) + s; } int eucliddist(point *a, point *b) { - return sqrt(pow(a->x - b->x, 2) + pow(a->y - b->y, 2)); + return sqrt(pow(a->x - b->x, 2) + pow(a->y - b->y, 2)); } point *mkPoint(double x, double y) { - point *ret = malloc(sizeof *ret); + point *ret = malloc(sizeof *ret); - ret->x = x; - ret->y = y; - ret->next = NULL; + ret->x = x; + ret->y = y; + ret->next = NULL; - return ret; + return ret; } point *rotate(point *p, double rot) { - double rad = rot * M_PI/180; + double rad = rot * M_PI/180; - return mkPoint( - p->x * cos(rad) - p->y * sin(rad), - p->x * sin(rad) + p->y * cos(rad) - ); + return mkPoint( + p->x * cos(rad) - p->y * sin(rad), + p->x * sin(rad) + p->y * cos(rad) + ); } void appendPoint(point *dest, point *origin) { - while(dest->next) dest = dest->next; - dest->next = origin; + while(dest->next) dest = dest->next; + dest->next = origin; } -int updateAnaconda(anaconda *anaconda, int w, int h, point *apple) { - point *temp, *new, *ptr; - new = anaconda->chain; - temp = rotate(mkPoint(10, 0), anaconda->rot); - new = mkPoint( - new->x + temp->x, - new->y + temp->y - ); - new->next = anaconda->chain; - anaconda->chain = new; +int updateAnaconda(anaconda *anaconda, point *basepoint, int w, int h, point *apple) { + point *temp, *new, *ptr; + new = anaconda->chain; - free(temp); + temp = rotate(basepoint, anaconda->rot); + new = mkPoint( + new->x + temp->x, + new->y + temp->y + ); + new->next = anaconda->chain; + anaconda->chain = new; - if(eucliddist(new, apple) <= 30) { - anaconda->score += 30; - apple->x = randrange(20, w / 2); - apple->y = randrange(20, h / 2); - } else { - ptr = new; + free(temp); - while(1) { - if(ptr->next) { - if(ptr->next->next) ptr = ptr->next; - else break; - } else break; - } - free(ptr->next); - ptr->next = NULL; - } + if(eucliddist(new, apple) <= 30) { + anaconda->score += 30; + apple->x = randrange(20, w / 2); + apple->y = randrange(20, h / 2); + } else { + ptr = new; - ptr = anaconda->chain; - for(int i = 0; i < 3; i++) { - if(ptr->next) ptr = ptr->next; - else return 1; /* we're fine, the snake is too short to intersect itself */ - } + while(1) { + if(ptr->next) { + if(ptr->next->next) ptr = ptr->next; + else break; + } else break; + } + free(ptr->next); + ptr->next = NULL; + } - while(ptr->next) { - if(intersect(new, new->next, ptr, ptr->next)) return 0; - ptr = ptr->next; - } + ptr = anaconda->chain; + for(int i = 0; i < 3; i++) { + if(ptr->next) ptr = ptr->next; + else return 1; /* we're fine, the snake is too short to intersect itself */ + } - if( - new->x >= w || new->x <= 0 || - new->y >= h || new->y <= 0 - ) return 0; + while(ptr->next) { + if(intersect(new, new->next, ptr, ptr->next)) return 0; + ptr = ptr->next; + } - if(eucliddist(new, apple) <= 30) { - anaconda->score += 30; - apple->x = randrange(20, w / 2); - apple->y = randrange(20, h / 2); - } + if( + new->x >= w || new->x <= 0 || + new->y >= h || new->y <= 0 + ) return 0; - return 1; + if(eucliddist(new, apple) <= 30) { + anaconda->score += 30; + apple->x = randrange(20, w / 2); + apple->y = randrange(20, h / 2); + } + + return 1; +} + +void freeAnaconda(anaconda *anaconda) { + point *current = anaconda->chain; + point *next = NULL; + for(;;) { + if(!current) break; + next = current->next; + free(current); + current = next; + } + + free(anaconda); + + return; } point *generateChain(int length) { - point *ret = mkPoint(100, 100); - point *head = ret; + point *ret = mkPoint(100, 100); + point *head = ret; - for(int i = 1; i < length - 1; i++) { - ret->next = mkPoint( - 10 * i + 100, - 5 * i + 100 - ); - ret = ret->next; - } + for(int i = 1; i < length - 1; i++) { + ret->next = mkPoint( + 10 * i + 100, + 5 * i + 100 + ); + ret = ret->next; + } - return head; + return head; } anaconda *mkAnaconda(point *point, double rot) { - anaconda *ret = malloc(sizeof *ret); + anaconda *ret = malloc(sizeof *ret); - ret->chain = point; - ret->rot = rot; - ret->score = 0; + ret->chain = point; + ret->rot = rot; + ret->score = 0; - return ret; + return ret; } int main(void) { - anaconda *anaconda = mkAnaconda(generateChain(30), 0); - xinit(); - srand(time(0)); - int width = DisplayWidth(d, s); - int height = DisplayHeight(d, s); - point *apple = mkPoint(randrange(20, width / 2 - 20), randrange(20, height / 2 - 20)); - while(1) { - if(!updateAnaconda(anaconda, width, height, apple)) { - return 0; - } - XClearWindow(d, w); - point *ptr = anaconda->chain; - while(ptr->next) { - XDrawLine(d, w, gc, ptr->x, ptr->y, ptr->next->x, ptr->next->y); - ptr = ptr->next; - } - printf("%f %f\n", apple->x, apple->y); - XDrawArc(d, w, gc, apple->x - (5/2), apple->y - (5/2), 5, 5, 0, 360*64); - while(XPending(d)) { - XNextEvent(d, &e); - switch(e.type) { - case KeyPress: - switch(e.xkey.keycode) { - case 113: /* left arrow key */ - anaconda->rot += 10; - break; - case 114: /* right arrow key */ - anaconda->rot -= 10; - break; - } - break; - } - } - usleep(100000); - } + anaconda *anaconda = mkAnaconda(generateChain(30), 0); + point *basepoint = mkPoint(10, 0); + char scorebuffer[30]; + xinit(); + srand(time(0)); + int width = DisplayWidth(d, s); + int height = DisplayHeight(d, s); + point *apple = mkPoint(randrange(20, width / 2 - 20), randrange(20, height / 2 - 20)); + int exposed = 0; + while(1) { + if(exposed) { + if(!updateAnaconda(anaconda, basepoint, width, height, apple)) { + freeAnaconda(anaconda); + free(apple); + free(basepoint); + return 0; + } + XClearWindow(d, w); + point *ptr = anaconda->chain; + while(ptr->next) { + XDrawLine(d, w, gc, ptr->x, ptr->y, ptr->next->x, ptr->next->y); + ptr = ptr->next; + } + XDrawArc(d, w, gc, apple->x - (5/2), apple->y - (5/2), 5, 5, 0, 360*64); + int len = snprintf(&scorebuffer, 30, "%i", anaconda->score); + XDrawString(d, w, gc, 25, 25, &scorebuffer, len); + } + while(XPending(d)) { + XNextEvent(d, &e); + switch(e.type) { + case KeyPress: + switch(e.xkey.keycode) { + case 113: /* left arrow key */ + anaconda->rot += 10; + break; + case 114: /* right arrow key */ + anaconda->rot -= 10; + break; + } + break; + case Expose: + /* hold off drawing until we get an expose event */ + exposed = 1; - return 0; + width = e.xexpose.width; + height = e.xexpose.height; + + if(apple->x > width) { + free(apple); + apple = mkPoint(randrange(20, width / 2 - 20), randrange(20, height / 2 - 20)); + } else if (apple->y > height) { + free(apple); + apple = mkPoint(randrange(20, width / 2 - 20), randrange(20, height / 2 - 20)); + } + + break; + } + } + usleep(100000); + } + + freeAnaconda(anaconda); + free(apple); + free(basepoint); + + return 0; }