Jump to content

[C++] Snake AI (demonstration)

- - - - -

This topic has been archived. This means that you cannot reply to this topic.
1 reply to this topic

#1
Muted

Muted

    Learning Programmer

  • Members
  • PipPipPip
  • 86 posts
Hello, this is a simple demonstration of how you could go about making a very basic AI system. There are a few things I intentionally left out so the reader could learn and add them on for him or herself! Such as:
- Avoiding his own body
- Moving food (he must constantly check for the new position of it)
- Multiple Snakes (one CPU, one "player")

#include <iostream>

#include <vector>

#include <windows.h>

using namespace std;


enum {

    BLACK       = 0,

    DARK_BLUE   = 1,

    DARK_GREEN  = 2,

    TEAL        = 3,

    DARK_RED    = 4,

    DARK_PURPLE = 5,

    GOLD        = 6,

    GREY        = 7,

    DARK_WHITE  = 8,

    BLUE        = 9,

    GREEN       = 10,

    CYAN        = 11,

    RED         = 12,

    PURPLE      = 13,

    YELLOW      = 14,

    WHITE       = 15

};


void RemoveCursor() {


    /* Remove the cursor (does not work in full screen) */

    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);

    CONSOLE_CURSOR_INFO CursoInfo;

    CursoInfo.dwSize = 1;         /* The size of caret */

    CursoInfo.bVisible = false;   /* Caret is visible? */

    SetConsoleCursorInfo(hConsole, &CursoInfo);


    return;

}


void AddCursor() {


    /* Remove the cursor (does not work in full screen) */

    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);

    CONSOLE_CURSOR_INFO CursoInfo;

    CursoInfo.dwSize = 10;        /* The size of caret */

    CursoInfo.bVisible = true;   /* Caret is visible? */

    SetConsoleCursorInfo(hConsole, &CursoInfo);


    return;

}


void SetColor(const int foreground) {


    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);

    SetConsoleTextAttribute(hConsole, foreground);


    return;

}


void SetColor(const int foreground, const int background) {


    int Color = foreground + (background * 16);

    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);

    SetConsoleTextAttribute(hConsole, Color);


    return;

}


void ClearConsole(const int foreground, const int background) {


    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);


    COORD coordScreen = { 0, 0 };

    DWORD cCharsWritten;

    CONSOLE_SCREEN_BUFFER_INFO csbi;

    DWORD dwConSize;


    if (!GetConsoleScreenBufferInfo(hConsole, &csbi)) { return; }

    dwConSize = csbi.dwSize.X * csbi.dwSize.Y;


    SetColor(foreground, background);

    if (!FillConsoleOutputCharacter(hConsole, (TCHAR) ' ', dwConSize, coordScreen, &cCharsWritten)) { return; }

    if (!GetConsoleScreenBufferInfo(hConsole, &csbi)) { return; }

    if (!FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten)) { return; }


    return;

}


void PlaceCursor(const int x, const int y) {


    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);


    COORD PlaceCursorHere;

    PlaceCursorHere.X = x;

    PlaceCursorHere.Y = y;


    SetConsoleCursorPosition(hConsole, PlaceCursorHere);

    return;

}


int FoodX = rand() % 70 + 5;

int FoodY = rand() % 25 + 5;


int SnakeX[100];

int SnakeY[100];


vector<int> Instructions;


void CreatePath() {


    int DestX = FoodX;

    int DestY = FoodY;


    int TempX = SnakeX[0];

    int TempY = SnakeY[0];


    while (TempX != DestX || TempY != DestY) {

        if (DestX > TempX) { TempX++; Instructions.push_back(3); }

        if (DestX < TempX) { TempX--; Instructions.push_back(2); }

        if (DestY > TempY) { TempY++; Instructions.push_back(1); }

        if (DestY < TempY) { TempY--; Instructions.push_back(0); }

    }


    return;

}


void DrawSnake(const int color) {


    SetColor(color, BLACK);

    for (int x = 10; x > 0; x--) { SnakeX[x] = SnakeX[x - 1]; SnakeY[x] = SnakeY[x - 1]; }

    for (int x = 10; x >= 0; x--) { PlaceCursor(SnakeX[x], SnakeY[x]); printf("*"); }


    SetColor(GREEN, BLACK);

    PlaceCursor(SnakeX[0], SnakeY[0]); printf("@");

    if (SnakeX[0] != SnakeX[10] || SnakeY[0] != SnakeY[10]) { PlaceCursor(SnakeX[10], SnakeY[10]); SetColor(BLACK, BLACK); printf(" "); }


    return;

}


void RunPath(const int color) {


    /* It'll crash sometimes if it randomly is empty */

    if (!Instructions.empty()) {


        PlaceCursor(0, 1);

        SetColor(WHITE, BLACK);

        printf("Total moves: %i ", Instructions.size());


        PlaceCursor(0, 0);

        printf("Initial Snake position: %i, %i", SnakeX[0], SnakeY[0]);


        int X = SnakeX[0];

        int Y = SnakeY[0];


        //PlaceCursor(SnakeX[0], SnakeY[0]);

        //SetColor(RED, BLACK);

        //printf("x");


        SetColor(color, BLACK);

        for (int x = 0; x < Instructions.size() - 1; x++) {


            switch (Instructions.at(x)) {

                case 0: SnakeY[0]--; break;

                case 1: SnakeY[0]++; break;

                case 2: SnakeX[0]--; break;

                case 3: SnakeX[0]++; break;

            }


            Sleep(25);


            DrawSnake(color);


            //PlaceCursor(SnakeX[0], SnakeY[0]);

            //printf("x");

        }


        switch (Instructions.front()) {

            case 0: SnakeY[0]--; break;

            case 1: SnakeY[0]++; break;

            case 2: SnakeX[0]--; break;

            case 3: SnakeX[0]++; break;

        }


        PlaceCursor(FoodX, FoodY);

        SetColor(YELLOW, BLACK);

        printf("x");


        PlaceCursor(31, 0);

        SetColor(WHITE, BLACK);

        printf("- Current Snake position: %i, %i  ", SnakeX[0], SnakeY[0]);


        //Sleep(1000);


        /* To show the old path in a faded grey */

        SetColor(BLACK, BLACK);

        for (int x = 0; x < Instructions.size(); x++) {


            PlaceCursor(X, Y);

            printf("x");


            switch (Instructions.at(x)) {

                case 0: Y--; break;

                case 1: Y++; break;

                case 2: X--; break;

                case 3: X++; break;

            }

        }


        /* To ensure the food is erased */

        PlaceCursor(FoodX, FoodY);

        SetColor(BLACK, BLACK);

        printf(" ");

    }


    return;

}


void NewRun() {


    FoodX = rand() % 70 + 5;

    FoodY = rand() % 25 + 5;


    PlaceCursor(FoodX, FoodY);

    SetColor(YELLOW, BLACK);

    printf("x");


    Instructions.clear();


    return;

}


int main() {


    RemoveCursor();

    ClearConsole(BLACK, BLACK);


    srand(time(NULL));


    SnakeX[0] = 5;

    SnakeY[0] = 5;


    while (true) {

        CreatePath();

        RunPath(BLUE);

        NewRun();

    }


    cin.get();

    return 0;

}

Hope somebody finds this useful! :)
“You may be disappointed if you fail, but you are doomed if you don't try.”
- Beverly Sills

#2
marwex89

marwex89

    Writes binary right handed and hex left handed

  • Members
  • PipPipPipPipPipPipPipPipPip
  • 10,720 posts
Very cool, +rep! I will look more into it later, when I have time..
Hey! Check out my new Toyota keyboaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa