简体   繁体   中英

Snake game crashes after second fruit

I need to make a Snake game using lists and I think I have it pretty much done, but for whatever reason the game always crashes upon picking up the second fruit. No game over or anything, it justs freezes after generating the third node. I already tried changing the program to work in different ways but no succes so far. Any suggestions are welcomed.

Here's the main code:

#include <iostream>
#include "doubleLinked.cpp"
#include <conio.h>
#include <stdlib.h>
using namespace std;

bool GameOver;
const int width = 20;
const int height = 20;
int x, y, fruitX, fruitY, score;
snake s;

enum eDirection
{
    STOP = 0,
    UP,
    DOWN,
    RIGHT,
    LEFT
};
eDirection dir;

void setUp();
void Input();
void Logic();
void Draw();
bool findSegment(segment *front, int x, int y);
void update(int coordX, int coordY, segment *dl);
void DrawEnd();

int main()
{

    setUp();
    while (!GameOver)
    {
        Draw();
        Input();
        Logic();
        update(x, y, s.front);
        usleep(100000);
    }
    DrawEnd();

    return 0;
}

//Sets initial parameters
void setUp()
{
    GameOver = false;
    dir = STOP;
    x = width / 2;
    y = height / 2;
    fruitX = rand() % width;
    fruitY = rand() % height;
    pushBack(T(x, y), &s);
    score = 0;
}

//Gets input from user
void Input()
{
    if (_kbhit())
    {
        switch (_getche())
        {
        case 'a':
            if (dir != RIGHT)
            {
                dir = LEFT;
            }
            break;
        case 'd':
            if (dir != LEFT)
            {
                dir = RIGHT;
            }
            break;
        case 'w':
            if (dir != DOWN)
            {
                dir = UP;
            }
            break;
        case 's':
            if (dir != UP)
            {
                dir = DOWN;
            }
            break;
        case 'f':
            GameOver = true;
            break;
        }
    }
}

//Draws matrix, snake and fruit
void Draw()
{
    system("clear");            //("cls") for windows
    for (int i = 0; i < width + 2; i++) 
        cout << "*";
    cout << endl;
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++) 
        {
            if (j == 0)
                cout << "*";
            if (i == s.front->info.coordinateY && j == s.front->info.coordinateX)
                cout << "O"; //head
            else if (i == fruitY && j == fruitX)
                cout << "^"; //fruit
            else
            {
                bool isSegment;
               
                if (s.front->next)
                {
                    isSegment = findSegment(s.front->next, j, i);
                }
                if (isSegment)
                {
                    cout << "o";//body part
                }
                else
                {
                    cout << " ";
                }
            }

            if (j == width - 1)
                cout << "*";
        }
        cout << endl;
    }
    for (int i = 0; i < width + 2; i++) 
        cout << "*";
    cout << endl;
    cout << "Score: " << score << endl;

//Coordinates for testing
    cout << s.front->info.coordinateX << endl;
    cout << s.front->info.coordinateY << endl;
    if (s.front->next)
    {
        cout << s.front->next->info.coordinateX << endl;
        cout << s.front->next->info.coordinateY << endl;
        if (s.front->next->next)
        {
            cout << s.front->next->next->info.coordinateX << endl;
            cout << s.front->next->next->info.coordinateY;
        }
    }
}

void Logic()
{

    switch (dir) //Updates current head coordinates
    {
    case LEFT:
        x--;
        break;
    case RIGHT:
        x++;
        break;
    case UP:
        y--;
        break;
    case DOWN:
        y++;
        break;
    default:
        break;
    }
//Collisions
    if (x > width || x < 0 || y > height || y < 0)
        GameOver = true; //Se finaliza el juego si topa en una pared :v

    if (s.front->next)
    {
        segment *currentpart = s.front->next;
        while (currentpart->next)
        {
            if (currentpart->info.coordinateX == x && currentpart->info.coordinateY == y)
                GameOver = true;
        }
    }

//Snake picks up fruit and a segment is added
    if (x == fruitX && y == fruitY)
    {
        score += 20; 
        fruitX = rand() % width;
        fruitY = rand() % height;
        int lastx = s.back->info.coordinateX;
        int lasty = s.back->info.coordinateY;
        pushBack(T(lastx, lasty), &s);
    }
}

//True if there's a segment in the coordinates
bool findSegment(segment *front, int x, int y)
{
    if (front->info.coordinateX == x && front->info.coordinateY == y)
    {
        return 1;
    }
    else if (front->next)
    {
        return findSegment(front->next, x, y);
    }
    else
    {
        return 0;
    }
}

//Updates coordinates for all segments
void update(int coordX, int coordY, segment *dl)
{

    int prevX = dl->info.coordinateX;
    int prevY = dl->info.coordinateY;
    dl->info.coordinateX = coordX;
    dl->info.coordinateY = coordY;
    if (dl->next)
    {
        update(prevX, prevY, dl->next);
    }
}

//Game over screen
void DrawEnd()
{

    system("clear"); //cls en windows
    cout << "##############################" << endl;
    cout << "#                            #" << endl;
    cout << "#   ####  ####  #####  ###   #" << endl;
    cout << "#   #  #  #  #  # # #  #     #" << endl;
    cout << "#   #     ####  # # #  ###   #" << endl;
    cout << "#   # ##  #  #  # # #  #     #" << endl;
    cout << "#   #  #  #  #  # # #  #     #" << endl;
    cout << "#   ####  #  #  # # #  ###   #" << endl;
    cout << "#                            #" << endl;
    cout << "#   ####  #   #  ###  ####   #" << endl;
    cout << "#   #  #  #   #  #    #  #   #" << endl;
    cout << "#   #  #  ## ##  ###  ####   #" << endl;
    cout << "#   #  #   # #   #    # #    #" << endl;
    cout << "#   #  #   ###   #    # ##   #" << endl;
    cout << "#   ####    #    ###  #  #   #" << endl;
    cout << "#                            #" << endl;
    cout << "##############################" << endl;
    cout << "Puntaje: " << score << endl;
    cin.get();
}

And the code for the double linked list i'm using

#include <iostream>
using namespace std;

typedef struct segmentInfo
{
    int coordinateX;
    int coordinateY;

    segmentInfo() {}
    segmentInfo(int _coordinateX, char _coordinateY) : coordinateX(_coordinateX), coordinateY(_coordinateY) {}

} T;

// Struct with ref to next and prev segments
struct segment
{
    T info;
    segment *prev, *next;
};

// Struct with front and back elements
struct snake
{
    segment *front, *back;

    snake()
    {
        front = back = NULL;
    }
};


void pushBack(T info, snake *dl)
{
    segment *n = new segment;
    n->info = info;
    n->next = NULL;

    // Same as push front
    if (!dl->front)
    {
        dl->front = dl->back = n;
        n->prev = n->next = NULL;

        return;
    }

  
    n->prev = dl->back;
    dl->back->next = n;
    dl->back = n;
}

This would be a great reason to learn how to use a debugger. I ran your code under a debugger, and it took me exactly to where the problem is. It was almost like a giant red highlighter saying "HERE IS THE PROBLEM".

Hint: look at your while loop in the function Logic() . What is meant to happen on each iteration of the loop?

Answer: You're missing currentpart = currentpart->next;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM