Skip to main content
gamedev.net
🔒 Locked

Snake (more object-oriented)

Started by MuTeD 0 replies 700+ views
Original Post
MuTeD
MuTeD
I'm back! Although I doubt anybody would remember (seeing how seldm I use this forum). Here's Snake in a more object oriented manner:
#include <iostream>
#include <conio.h>
#include <TextControl.h>
using namespace std;

class CREATE_SNAKE {

    public:
        bool GameOver;
        bool Computer;
        bool IsImmortal;
        int X, Y;
        int Player;
        int PlaceX, PlaceY;
        int Width, Height;

    private:
        int Food[3];
        int SnakeColor;
        int SnakeSpeed;
        int CONTROL[4];
        int LastMove;
        int Horizontal[100], Vertical[100];
        int SnakeSize;
        int Score;
        int Lives;

    public:
        CREATE_SNAKE::CREATE_SNAKE(int ID, int X, int Y, int UP, int DOWN, int LEFT, int RIGHT, int COLOR);
        CREATE_SNAKE::CREATE_SNAKE(int ID);
        int GetSnakeSize() { return SnakeSize; }
        int GetXPos(int x) { return Horizontal[x]; }
        int GetYPos(int x) { return Vertical[x]; }
        void CollectFood();
        void ResetSnake();
        void SetUpArrow(int UpArrow) { CONTROL[0] = UpArrow; }
        void SetDownArrow(int DownArrow) { CONTROL[1] = DownArrow; }
        void SetLeftArrow(int LeftArrow) { CONTROL[2] = LeftArrow; }
        void SetRightArrow(int RightArrow) { CONTROL[3] = RightArrow; }
        void Crashed();
        void GetUserInput();
        void DrawSnake();
        void SetSpeed(int NewSpeed) { SnakeSpeed = NewSpeed; }
        void SetBoundaries(int xWidth, int xHeight, int xPlaceX, int xPlaceY);
        void DrawPlayingField(int color) { DrawBox(color, Width, Height, PlaceX, PlaceY); SetColor(BLACK, BLACK); }
        void DrawFood();
        void DisplayScore(int X, int Y) { PlaceCursor(X, Y); SetColor(WHITE, BLACK); printf("%i", Score); SetColor(BLACK, BLACK); }
        void DisplayLives(int X, int Y) { PlaceCursor(X, Y); SetColor(WHITE, BLACK); printf("%i", Lives); SetColor(BLACK, BLACK); }
        void Grow(int pieces) { SnakeSize += pieces; }
        void SetSnakeXY(int X, int Y) {
            for (int x = 0; x < 100; x++) { Horizontal[x] = 0; Vertical[x] = 0; }
            Horizontal[0] = PlaceX;
            Vertical[0] = PlaceY + 1;
            };

        void SendSnakeMsg(int Msg) { LastMove = Msg; }
        void AI();

        void UserSelectedDimensions();
};

CREATE_SNAKE::CREATE_SNAKE(int ID) {

    SnakeColor = CYAN;
    for (int x = 0; x < 100; x++) { Horizontal[x] = 0; Vertical[x] = 0; }
    GameOver = false;
    Computer = false;
    IsImmortal = false;
    Width = 80;
    Height = 25;
    PlaceX = 0;
    PlaceY = 0;
    Food[0] = 0;
    Food[1] = 0;
    SnakeSize = 5;
    Lives = 4;
    Score = 0;
    Player = ID;
}

CREATE_SNAKE::CREATE_SNAKE(int ID, int X, int Y, int UP, int DOWN, int LEFT, int RIGHT, int COLOR) {

    SnakeColor = COLOR;
    CONTROL[0] = UP;
    CONTROL[1] = DOWN;
    CONTROL[2] = LEFT;
    CONTROL[3] = RIGHT;
    LastMove = RIGHT;

    for (int x = 0; x < 100; x++) { Horizontal[x] = 0; Vertical[x] = 0; }
    GameOver = false;
    Computer = false;
    IsImmortal = false;
    Horizontal[0] = X;
    Vertical[0] = Y;
    Width = 80;
    Height = 25;
    PlaceX = 0;
    PlaceY = 0;
    Food[0] = 0;
    Food[1] = 0;
    SnakeSize = 5;
    Lives = 4;
    Score = 0;
    Player = ID;
}

void CREATE_SNAKE::UserSelectedDimensions() {

    int x = 5;
    int y = 4;
    int px = 35;
    int py = 20;

    char Type[] = "Player";

    DrawBox(RED, x, y, px, py);

    while (true) {
        Sleep(50);

        PlaceCursor(20, 0);
        SetColor(WHITE, BLACK);
        printf("Press C to spawn as a ");
        SetColor(CYAN, BLACK);
        printf("computer");

        PlaceCursor(20, 1);
        SetColor(WHITE, BLACK);
        printf("Press P to spawn as a ");
        SetColor(CYAN, BLACK);
        printf("player");

        PlaceCursor(0, 5);
        SetColor(WHITE, BLACK);
        printf("SPAWN TYPE: ");
        SetColor(CYAN, BLACK);
        printf("%s", Type);

        SetColor(WHITE, BLACK);
        PlaceCursor(0, 0);
        printf("X: %i  ", px);
        PlaceCursor(0, 1);
        printf("Y: %i  ", py);
        PlaceCursor(0, 3);
        printf("Height: %i  ", y);
        PlaceCursor(0, 4);
        printf("Width: %i  ", x);

        /* Placement of the X, Y coordinates */
        if (GetAsyncKeyState(VK_UP) && !GetAsyncKeyState(VK_SHIFT) && py > 1) { DrawBox(BLACK, x, y, px, py); py--; DrawBox(RED, x, y, px, py); }
        if (GetAsyncKeyState(VK_DOWN) && !GetAsyncKeyState(VK_SHIFT) && (py + y) < 49) { DrawBox(BLACK, x, y, px, py); py++; DrawBox(RED, x, y, px, py); }
        if (GetAsyncKeyState(VK_LEFT) && !GetAsyncKeyState(VK_SHIFT) && px > 0) { DrawBox(BLACK, x, y, px, py); px--; DrawBox(RED, x, y, px, py); }
        if (GetAsyncKeyState(VK_RIGHT) && !GetAsyncKeyState(VK_SHIFT) && (px + x) < 80) { DrawBox(BLACK, x, y, px, py); px++; DrawBox(RED, x, y, px, py); }

        /* Resizing of the box */
        if (GetAsyncKeyState(VK_UP) && GetAsyncKeyState(VK_SHIFT) && y > 4) { DrawBox(BLACK, x, y, px, py); y--; DrawBox(RED, x, y, px, py); }
        if (GetAsyncKeyState(VK_DOWN) && GetAsyncKeyState(VK_SHIFT) && (py + y) < 49) { DrawBox(BLACK, x, y, px, py); y++; DrawBox(RED, x, y, px, py); }
        if (GetAsyncKeyState(VK_LEFT) && GetAsyncKeyState(VK_SHIFT) && x > 5) { DrawBox(BLACK, x, y, px, py); x--; DrawBox(RED, x, y, px, py); }
        if (GetAsyncKeyState(VK_RIGHT) && GetAsyncKeyState(VK_SHIFT) && (px + x) < 80) { DrawBox(BLACK, x, y, px, py); x++; DrawBox(RED, x, y, px, py); }

        if (GetAsyncKeyState('C') && !Computer) { strcpy(Type, "Computer"); Computer = true; }
        if (GetAsyncKeyState('P') && Computer) { strcpy(Type, "Player  "); Computer = false; }

        /* Place the box - "fade out" for cool effects! ;) */
        if (GetAsyncKeyState(VK_SPACE)) {
            Sleep(150);
            SetColor(GREY, BLACK);
            DrawBox(x, y, px, py);
            Sleep(150);
            SetColor(DARK_WHITE, BLACK);
            DrawBox(x, y, px, py);
            Sleep(150);
            SetColor(BLACK, BLACK);
            DrawBox(x, y, px, py);
            break;
        }
    }

    /* Save the X, Y, coordinates of the box */
    X = x; Y = y; PlaceX = px; PlaceY = py;

    SetBoundaries(x, y, px, py);
    ClearConsole();
    SetColor(BLACK, BLACK);

    return;
}

void CREATE_SNAKE::DrawFood() {

    srand(time(NULL));

    PLACEFOOD:
    Food[0] = rand() % Width + PlaceX;
    Food[1] = rand() % Height + PlaceY;

    if (Food[1] == PlaceY || Food[1] == Height + PlaceY - 1 || Food[0] == PlaceX || Food[0] == Width + PlaceX - 1) {
        goto PLACEFOOD;
    }

    for (int x = 0; x < SnakeSize; x++) { if (Food[0] == Horizontal[x] && Food[1] == Vertical[x]) { goto PLACEFOOD; } }

    PlaceCursor(Food[0], Food[1]);
    SetColor(YELLOW, BLACK);
    printf("x");
    SetColor(BLACK, BLACK);
}

void CREATE_SNAKE::SetBoundaries(int xWidth, int xHeight, int xPlaceX, int xPlaceY) {

    Width = xWidth;
    Height = xHeight;
    PlaceX = xPlaceX;
    PlaceY = xPlaceY;
    DrawBox(Width, Height, PlaceX, PlaceY);

    return;
}

void CREATE_SNAKE::ResetSnake() {

    DrawPlayingField(WHITE);
    for (int x = 0; x < SnakeSize; x++) { PlaceCursor(Horizontal[x], Vertical[x]); printf(" "); }
    for (int x = 0; x < 100; x++) { Horizontal[x] = 0; Vertical[x] = 0; }
    Horizontal[0] = PlaceX + 2;
    Vertical[0] = PlaceY + 1;
    LastMove = CONTROL[3]; /* To the right */
    SnakeSize = 5;

    if (!IsImmortal) {
        Lives--;

        SetColor(WHITE, BLACK);
        PlaceCursor(PlaceX, PlaceY + Height); printf("Lives: ");
        DisplayLives(PlaceX + 7, PlaceY + Height);
        SetColor(BLACK, BLACK);

        if (Lives <= 0) {
            GameOver = true;

            int CenterX = ((Width / 2) + PlaceX) - (9 / 2);
            int CenterY = ((Height / 2) + PlaceY) - 1;

            PlaceCursor(Food[0], Food[1]);
            SetColor(BLACK, BLACK);
            printf(" ");

            PlaceCursor(CenterX, CenterY);
            SetColor(WHITE, BLACK);
            printf("GAME OVER");
            Sleep(150);

            PlaceCursor(CenterX, CenterY);
            SetColor(RED, BLACK);
            printf("GAME OVER");
            Sleep(150);

            PlaceCursor(CenterX, CenterY);
            SetColor(WHITE, BLACK);
            printf("GAME OVER");
            Sleep(150);

            PlaceCursor(CenterX, CenterY);
            SetColor(RED, BLACK);
            printf("GAME OVER");
            Sleep(150);

            PlaceCursor(CenterX, CenterY);
            SetColor(YELLOW, BLACK);
            printf("GAME OVER");
            SetColor(BLACK, BLACK);
        }
    }

    return;
}

void CREATE_SNAKE::Crashed() {

    for (int x = SnakeSize - 1; x > 1; x--) {
        if (Horizontal[0] == Horizontal[x] && Vertical[0] == Vertical[x]) {
            PlaceCursor(Horizontal[0], Vertical[0]);
            SetColor(RED, BLACK);
            printf("X");
            PlaceCursor(30, 0);
            printf("Player %i has hit himself!", Player);
            Sleep(500);
            PlaceCursor(30, 0);
            SetColor(BLACK, BLACK);
            printf("                            ");
            ResetSnake();
            return;
        }
    }

    if (Vertical[0] == PlaceY || Vertical[0] == Height + PlaceY - 1 ||
        Horizontal[0] == PlaceX || Horizontal[0] == Width + PlaceX - 1) {

        char WallPieceHit = '\0';
        if (Vertical[0] == PlaceY || Vertical[0] == Height + PlaceY - 1) { WallPieceHit = 'Í'; } /* Vertical Wall */
        else { WallPieceHit = 'º'; } /* Horizontal Wall */

        PlaceCursor(Horizontal[0], Vertical[0]);
        SetColor(RED, BLACK);
        printf("%c", WallPieceHit);
        PlaceCursor(30, 0);
        printf("Player %i hit the wall!", Player);
        Sleep(500);
        PlaceCursor(30, 0);
        SetColor(BLACK, BLACK);
        printf("                         ");
        ResetSnake();
        return;
    }

    return;
}

void CREATE_SNAKE::GetUserInput() {

    HANDLE InHandle = GetStdHandle(STD_INPUT_HANDLE);
    FlushConsoleInputBuffer(InHandle);

    if (GetAsyncKeyState(CONTROL[0]) && LastMove != CONTROL[1]) { LastMove = CONTROL[0]; } else
    if (GetAsyncKeyState(CONTROL[1]) && LastMove != CONTROL[0]) { LastMove = CONTROL[1]; } else
    if (GetAsyncKeyState(CONTROL[2]) && LastMove != CONTROL[3]) { LastMove = CONTROL[2]; } else
    if (GetAsyncKeyState(CONTROL[3]) && LastMove != CONTROL[2]) { LastMove = CONTROL[3]; }

    return;
}

void CREATE_SNAKE::DrawSnake() {

    if (LastMove == CONTROL[0]) { PlaceCursor(Horizontal[0],   Vertical[0]--); } else
    if (LastMove == CONTROL[1]) { PlaceCursor(Horizontal[0],   Vertical[0]++); } else
    if (LastMove == CONTROL[2]) { PlaceCursor(Horizontal[0]--, Vertical[0]);   } else
    if (LastMove == CONTROL[3]) { PlaceCursor(Horizontal[0]++, Vertical[0]);   }

    SetColor(SnakeColor, BLACK);
    for (int x = SnakeSize; x > 0; x--) { Horizontal[x] = Horizontal[x - 1]; Vertical[x] = Vertical[x - 1]; }
    for (int x = SnakeSize; x >= 0; x--) { PlaceCursor(Horizontal[x], Vertical[x]); printf("*"); }

    PlaceCursor(Horizontal[0], Vertical[0]); printf("@");
    if (Horizontal[0] != Horizontal[SnakeSize] || Vertical[0] != Vertical[SnakeSize]) {
        PlaceCursor(Horizontal[SnakeSize], Vertical[SnakeSize]); SetColor(BLACK, BLACK); printf(" ");
    }

    PlaceCursor(Food[0], Food[1]);
    SetColor(YELLOW, BLACK);
    printf("x");
    SetColor(BLACK, BLACK);
    return;
}

void CREATE_SNAKE::CollectFood() {

    /* Begin loop */
    if (Horizontal[0] == Food[0] && Vertical[0] == Food[1]) {
    PLACEFOOD:

        Food[0] = rand() % Width + PlaceX;
        Food[1] = rand() % Height + PlaceY;

        /* Check wall range - if false start over */
    if (Food[1] == PlaceY || Food[1] == Height + PlaceY - 1 || Food[0] == PlaceX || Food[0] == Width + PlaceX - 1) {
            goto PLACEFOOD;
        }

        /* Check if it's on the snake - if false start over */
        for (int x = 0; x < SnakeSize; x++) {
            if (Food[0] == Horizontal[x] && Food[1] == Vertical[x]) {
                goto PLACEFOOD;
            }
        }

        Score++;
        Grow(1);

        PlaceCursor(Food[0], Food[1]);
        SetColor(YELLOW, BLACK);
        printf("x");

        SetColor(WHITE, BLACK);
        PlaceCursor(PlaceX, PlaceY - 1);
        printf("Player %i (score): ", Player);
        DisplayScore(PlaceX + 18, PlaceY - 1);
        SetColor(BLACK, BLACK);

    } /* End loop */

    return;
}

void CREATE_SNAKE::AI() {

    if (Food[1] > Vertical[0]) { if (LastMove != CONTROL[0]) { LastMove = CONTROL[1]; } else { LastMove = CONTROL[2]; } } else
    if (Food[1] < Vertical[0]) { if (LastMove != CONTROL[1]) { LastMove = CONTROL[0]; } else { LastMove = CONTROL[2]; } } else
    if (Food[0] > Horizontal[0]) { if (LastMove != CONTROL[2]) { LastMove = CONTROL[3]; } else { LastMove = CONTROL[0]; } } else
    if (Food[0] < Horizontal[0]) { if (LastMove != CONTROL[3]) { LastMove = CONTROL[2]; } else { LastMove = CONTROL[0]; } }

    return;
}

void CheckPlayersHit(vector<CREATE_SNAKE> &Snake, int SnakeX) {

/* Main idea on how to check collision status (initial Snake vs. opposing):
    - Cycle through all Snakes
    - Compare each Snake (head) cycled against all other Snakes (bodies)

    Step 1) Find initial Snake to compare to all others
    Step 2) Find size of initial Snake so you can compare against all others
    Step 3) Compare initial Snake (loop based on size) against all others
*/

    /* Loop through all Snakes in the vector */
    for (int x = SnakeX - 1; x >= 0; x--) {

        /* Loop through Snake X's size */
        for (int o = SnakeX - 1; o >= 0; o--) {

            /* Loop through all (other) Snakes in the vector to check a collison status against */
                for (int s = Snake.at(o).GetSnakeSize() - 1; s > 0; s--) {
                    if (Snake.at(x).Player != Snake.at(o).Player && !Snake.at(x).GameOver) {
                    if (Snake.at(x).GetXPos(0) == Snake.at(o).GetXPos(s) && Snake.at(x).GetYPos(0) == Snake.at(o).GetYPos(s)) {
                    Snake.at(x).ResetSnake();
                    }
                }
            }
        }
    }

    return;
}

bool GameInProgress(vector<CREATE_SNAKE> &Snake, int SnakeX, int &Winner) {

    int GamesEnded = 0;
    bool Player[SnakeX];

    /* Fill in the values */
    for (int x = SnakeX - 1; x >= 0; x--) {
        Player[x] = Snake.at(x).GameOver;

        if (Player[x] == true) { GamesEnded++; }
        if (Player[x] == false) { Winner = (x + 1); }
    }

    if (GamesEnded == SnakeX) { return false; }
    else { return true; }
}

int main() {

    HANDLE OutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
    HANDLE InHandle = GetStdHandle(STD_INPUT_HANDLE);
    SetConsoleTitle("Snake");
    SMALL_RECT windowSize = {0, 0, 79, 49};
    SetConsoleWindowInfo(OutHandle, TRUE, &windowSize);

    ClearConsole();
    RemoveCursor();
    int GameSpeed = 50;
    int Winner = 0;

    int NumSnakes = 0;
    printf("How many Snakes do you want? ");
    scanf("%d", &NumSnakes);
    ClearConsole();

    vector<CREATE_SNAKE> Snake;
    for (int x = 0; x <= NumSnakes; x++) { Snake.push_back(CREATE_SNAKE(x + 1)); }
    for (int x = 0; x <= NumSnakes; x++) {
        Snake.at(x).SetUpArrow(VK_UP);
        Snake.at(x).SetDownArrow(VK_DOWN);
        Snake.at(x).SetLeftArrow(VK_LEFT);
        Snake.at(x).SetRightArrow(VK_RIGHT);
    }

    Snake.at(1).SetUpArrow('W');
    Snake.at(1).SetDownArrow('S');
    Snake.at(1).SetLeftArrow('A');
    Snake.at(1).SetRightArrow('D');

    for (int x = 0; x < NumSnakes; x++) { Snake.at(x).UserSelectedDimensions(); }

    PlaceCursor((80 / 2) - 6, (50 / 2) - 1);
    SetColor(RED);
    printf("READY?");
    Sleep(500);

    PlaceCursor((80 / 2) - 6, (50 / 2) - 1);
    SetColor(YELLOW);
    printf("SET...");
    Sleep(500);

    PlaceCursor((80 / 2) - 6, (50 / 2) - 1);
    SetColor(GREEN);
    printf("GO!   ");
    Sleep(500);

    PlaceCursor((80 / 2) - 6, (50 / 2) - 1);
    SetColor(BLACK);
    printf("   ");

    for (int x = 0; x < NumSnakes; x++) { Snake.at(x).DrawPlayingField(WHITE); }

    while (GameInProgress(Snake, NumSnakes, Winner)) {

        for (int x = 0; x < NumSnakes; x++) {
            if (!Snake.at(x).GameOver) {
                Snake.at(x).GetUserInput();
                Snake.at(x).DrawSnake();
                Snake.at(x).CollectFood();
                if (Snake.at(x).Computer) { Snake.at(x).AI(); }
                Snake.at(x).Crashed();
            }
        }

        CheckPlayersHit(Snake, NumSnakes);

        PlaceCursor(30, 0);
        SetColor(WHITE, BLACK);
        printf("GameSpeed: %i ", GameSpeed);

        if (GetAsyncKeyState(VK_ADD) && GameSpeed > 0) { GameSpeed--; }
        if (GetAsyncKeyState(VK_SUBTRACT) && GameSpeed < 150) { GameSpeed++; }

        if (GetAsyncKeyState(VK_ESCAPE)) { break; }
        Sleep(GameSpeed);
    }

    int CenterX = ((Snake.at(Winner - 1).Width / 2) + Snake.at(Winner - 1).PlaceX) - (23 / 2);
    int CenterY = ((Snake.at(Winner - 1).Height / 2) + Snake.at(Winner - 1).PlaceY);

    PlaceCursor(CenterX, CenterY);
    SetColor(WHITE, BLACK);
    printf("THE WINNER IS: Player %i", Winner);

    PlaceCursor(0, 0);
    SetColor(BLACK, BLACK);

    FlushConsoleInputBuffer(InHandle);
    _flushall();
    _getch();
    return 0;
}

“You may be disappointed if you fail, but you are doomed if you don't try.”Beverly Sills

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.