This is the Snake AI I'm working on (on and off). I'm not really sure how to make him
NOT hit himself 100% of the time without generating tons of possible moves ('genetic algorithm' as one book describes it). I've pretty much got him to not hit himself (4 possible moves, if there is no "safe" ones, he goes to the last one (right)), but it isn't as effective as I'd like it. The only other thing I could think of doing is generating the food (invisibly) ahead of time, and create x2 paths at a time, so he knows how to avoid himself 100%.
Code
#include <iostream>
#include <vector>
#include <TextControl.h> // I created this, it contains the functions for SetColor(), PlaceCursor(), RemoveCursor(), and ClearConsole()
using namespace std;
int TotalRuns = 0;
int TotalCrashes = 0;
int FoodX = rand() % 70 + 5;
int FoodY = rand() % 25 + 5;
int SnakeX[100] = {'\0'};
int SnakeY[100] = {'\0'};
vector<int> Instructions;
void ShowPath() {
int TempX = SnakeX[0];
int TempY = SnakeY[0];
SetColor(GREEN, BLACK);
for (int x = 0; x < Instructions.size() - 1; x++) {
switch (Instructions.at(x)) {
case 0: TempY--; break;
case 1: TempY++; break;
case 2: TempX--; break;
case 3: TempX++; break;
}
PlaceCursor(TempX, TempY);
printf("!");
}
return;
}
bool Crash(const int X[], const int Y[]) {
for (int x = 9; x > 1; x--) {
if (X[0] == X[x] && Y[0] ==Y[x]) {
return true;
}
}
return false;
}
void DrawSnake(const int color, int SnakeX[], int SnakeY[]);
void CreatePath() {
/* Copy food location */
int DestX = FoodX;
int DestY = FoodY;
int TempX[100] = {'\0'};
int TempY[100] = {'\0'};
/* Copy Snake location */
for (int x = 0; x < 100; x++) {
TempX[x] = SnakeX[x];
TempY[x] = SnakeY[x];
}
while (TempX[0] != DestX || TempY[0] != DestY) {
if (DestX > TempX[0]) { TempX[0]++; Instructions.push_back(3); }
if (DestX < TempX[0]) { TempX[0]--; Instructions.push_back(2); }
if (DestY > TempY[0]) { TempY[0]++; Instructions.push_back(1); }
if (DestY < TempY[0]) { TempY[0]--; Instructions.push_back(0); }
Sleep(25);
DrawSnake(RED, TempX, TempY);
static int NewMove = 0;
/* Oh noes! He crashed! Randomize a movement */
while (Crash(TempX, TempY)) {
SetColor(CYAN, BLACK);
PlaceCursor(TempX[0], TempY[0]); printf("x");
Sleep(500);
/* Remove the OLD move */
switch (Instructions.back()) {
case 0: TempY[0]++; break;
case 1: TempY[0]--; break;
case 2: TempX[0]++; break;
case 3: TempX[0]--; break;
}
NewMove++;
/* Add the NEW move and ensure there's no crash... */
switch (NewMove) {
case 0: TempY[0]--; break;
case 1: TempY[0]++; break;
case 2: TempX[0]--; break;
case 3: TempX[0]++; break;
}
Instructions.back() = NewMove;
if (NewMove > 4) { NewMove = 0; goto DEAD_SNAKE; }
}
}
DEAD_SNAKE:
//ShowPath();
return;
}
void DrawSnake(const int color, int SnakeX[], int SnakeY[]) {
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]);
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(15);
DrawSnake(color, SnakeX, SnakeY);
for (int x = 9; x > 2; x--) {
if (SnakeX[0] == SnakeX[x] && SnakeY[0] == SnakeY[x]) {
SetColor(WHITE, BLACK);
PlaceCursor(SnakeX[x], SnakeY[x]);
printf("X");
TotalCrashes++;
}
}
}
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]);
/* 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() {
HANDLE OutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTitle("Snake - AI Module");
SMALL_RECT windowSize = {0, 0, 79, 49};
SetConsoleWindowInfo(OutHandle, TRUE, &windowSize);
ClearConsole(BLACK, BLACK);
RemoveCursor();
srand(time(NULL));
SnakeX[0] = 5;
SnakeY[0] = 5;
while (true) {
CreatePath();
RunPath(BLUE);
NewRun();
PlaceCursor(0, 3);
SetColor(WHITE, BLACK);
printf("Total runs: ");
SetColor(CYAN, BLACK);
printf("%d", TotalRuns);
PlaceCursor(0, 4);
SetColor(WHITE, BLACK);
printf("Total crashes: ");
SetColor(RED, BLACK);
printf("%d", TotalCrashes);
TotalRuns++;
}
cin.get();
return 0;
}
Here's a screen shot of it in progress:

Any suggestions?