Search code examples
cgraphicsconsolecygwin

Not sure what's wrong with my logic for my snake game?


For reference, here is the link to my assignment (the course is a C language course): Snake

The mouth is supposed to be "<", ">", "v", or "^", depending on the direction, and the body segments are supposed to be "*".

So first of all, my up and down arrow key controls are switched, but it prints the correct character (i.e. it prints "v" when moving down and "^" when moving up), and I cannot figure out why.

Also, as the head moves, it just detaches from the body and doesn't print new body segments (See Screencap).

Below are my custom structs, main, scene_render and scene_update functions (we are NOT allowed to modify the main function for this assignment):

struct Point{
    int x;
    int y;
};

struct Snake {
    struct Point segments[MAX_SEGMENTS];
    int num_segments;
    int dir; //0=up, 1=down, 2=left, 3=right
};

struct Scene {
    // TODO: add fields
    struct Snake snake;
    struct Point fruit;
};

main

int main(void) {
    // Important: do NOT modify the main function
    struct Scene scene;

    scene_init(&scene);

    int keep_going = 1;
    while (keep_going == 1) {
        scene_render(&scene);
        cons_update();
        scene_delay(&scene);
        keep_going = scene_update(&scene);
    }

    return 0;
 }

scene_render

void scene_render(const struct Scene *s) {
    // TODO: add your code
    int num=s->snake.num_segments;
    cons_clear_screen();
    cons_move_cursor(s->snake.segments[0].y, s->snake.segments[0].x);
    if(s->snake.dir==0)
    {
        cons_printw("v");
    }
    else if(s->snake.dir==1)
    {
        cons_printw("^");
    }
    else if(s->snake.dir==2)
    {
        cons_printw(">");
    }
    else
    {
        cons_printw("<");
    }
    for(int i=1; i <num; i++)
    {
        cons_move_cursor(s->snake.segments[i].y, s->snake.segments[i].x);
        cons_printw("*");
    }
    cons_move_cursor(23, 79); //just to get blinking cursor out of the way
}

scene_update

int scene_update(struct Scene *s) {
    // This function should return 0 if the player presses 'q',
    // 1 otherwise.
    struct Scene temp=*s;
    int num=temp.snake.num_segments;

    int key = cons_get_keypress();
    // TODO: add your code
    if(key=='q')
    {
        return 0;
    }
    if(key==UP_ARROW && temp.snake.dir!=1)
    {
        temp.snake.dir=0;
        temp.snake.segments[0].y=(temp.snake.segments[0].y)+1;
        for(int i=1; i<num; i++)
        {
            temp.snake.segments[i].y=s->snake.segments[i].y;
            temp.snake.segments[i].x=s->snake.segments[i].x;
        }
    }
    else if(key==DOWN_ARROW && temp.snake.dir!=0)
    {
        temp.snake.dir=1;
        temp.snake.segments[0].y=(temp.snake.segments[0].y)-1;
        for(int i=1; i<num; i++)
        {
            temp.snake.segments[i].y=s->snake.segments[i].y;
            temp.snake.segments[i].x=s->snake.segments[i].x;
        }
    }
    else if(key==LEFT_ARROW && temp.snake.dir!=3)
    {
        temp.snake.dir=2;
        temp.snake.segments[0].x=(temp.snake.segments[0].x)-1;
        for(int i=1; i<num; i++)
        {
            temp.snake.segments[i].y=s->snake.segments[i].y;
            temp.snake.segments[i].x=s->snake.segments[i].x;
        }
    }
    else if(key==RIGHT_ARROW && temp.snake.dir!=2)
    {
        temp.snake.dir=3;
        temp.snake.segments[0].x=(temp.snake.segments[0].x)+1;
        for(int i=1; i<num; i++)
        {
            temp.snake.segments[i].y=s->snake.segments[i].y;
            temp.snake.segments[i].x=s->snake.segments[i].x;
        }
    }
    else if(key==-1)
    {
        if(temp.snake.dir==0)
        {
            temp.snake.segments[0].y=(temp.snake.segments[0].y)+1;
            for(int i=1; i<num; i++)
            {
                temp.snake.segments[i].y=s->snake.segments[i].y;
                temp.snake.segments[i].x=s->snake.segments[i].x;
            }
        }
        else if(temp.snake.dir==1)
        {
            temp.snake.segments[0].y=(temp.snake.segments[0].y)-1;
            for(int i=1; i<num; i++)
            {
                temp.snake.segments[i].y=s->snake.segments[i].y;
                temp.snake.segments[i].x=s->snake.segments[i].x;
            }   
        }
        else if(temp.snake.dir==2)
        {
            temp.snake.segments[0].x=(temp.snake.segments[0].x)-1;
            for(int i=1; i<num; i++)
            {
                temp.snake.segments[i].y=s->snake.segments[i].y;
                temp.snake.segments[i].x=s->snake.segments[i].x;
            }
        }
        else
        {
            temp.snake.segments[0].x=(temp.snake.segments[0].x)+1;
            for(int i=1; i<num; i++)
            {
                temp.snake.segments[i].y=s->snake.segments[i].y;
                temp.snake.segments[i].x=s->snake.segments[i].x;
            }
        }
    }
    temp.fruit.x=s->fruit.x;
    temp.fruit.y=s->fruit.y;
    *s=temp;

    return 1;
}

Solution

  • The reason why the body is detached from the head is because your movement code:

        if(temp.snake.dir==0)
        {
            temp.snake.segments[0].y=(temp.snake.segments[0].y)+1;
            for(int i=1; i<num; i++)
            {
                temp.snake.segments[i].y=s->snake.segments[i].y;
                temp.snake.segments[i].x=s->snake.segments[i].x;
            }
        }
    

    should be:

        if(temp.snake.dir==0)
        {
            temp.snake.segments[0].y=(temp.snake.segments[0].y)+1;
            for(int i=1; i<num; i++)
            {
                temp.snake.segments[i].y=s->snake.segments[i-1].y;
                temp.snake.segments[i].x=s->snake.segments[i-1].x;
            }
        }
    

    In other words, the first body part should move to where the head used to be. The second body part should move to where the first part used to be, etc. The way you have it right now, all the body parts just stay in the same place all the time. You need to make this change in many places, or better yet make a function to move the body so you don't have duplicated code everywhere.

    As for why up is down and vice versa, I can only imagine that the y coordinates of your screen are opposite what you think they are (increasing y values moves up vs down). You should check which way is which and make sure your code matches.