I've been working on an AI for my game [Snake]. I've created an extremely simple "system-based" AI logic that was poor, but worked.
I've since then been attempting to create an AI where the Snake actually paths his way to the food, rather than finding it real-time by avoiding objects as he goes.
The "objects" he avoids is:
- The wall
- His own body
- Other Snake players ("players" means computers/humans)
This is the newest version (and I'm confused as to why it does this now):
Code
#include <iostream>
#include <vector>
#include <TextControl.h>
using namespace std;
int TotalRuns = 0;
int TotalCrashes = 0;
int FoodX = 0;
int FoodY = 0;
int SnakeX[100] = {'\0'};
int SnakeY[100] = {'\0'};
vector<int> Instructions;
void DrawSnake(const int, int, int);
bool Crash(const int X[], const int Y[]) {
for (int x = 9; x > 1; x--) {
if (X[0] == X[x] && Y[0] == Y[x]) {
PlaceCursor(0, 45);
SetColor(RED, BLACK);
printf("X: %d ", X[0]);
PlaceCursor(0, 46);
SetColor(RED, BLACK);
printf("Y: %d ", Y[0]);
//Sleep(250);
return true;
}
}
return false;
}
void CreatePath() {
Instructions.clear();
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];
}
int TempNum = 0;
while (TempX[0] != FoodX || TempY[0] != FoodY) {
if (FoodX > TempX[0]) {
TempX[0]++; Instructions.push_back(3);
while (Crash(TempX, TempY)) {
switch (TempNum) {
case 0: { TempX[0]++; } break;
case 1: { TempY[0]--; } break;
case 2: { TempX[0]++; } break;
case 3: { TempY[0]--; } break;
}
Instructions.back() = TempNum;
PlaceCursor(0, 35); printf("%d", TempNum);
TempNum++;
Sleep(250);
if (TempNum >= 4) { break; }
}
}
if (FoodX < TempX[0]) {
TempX[0]--; Instructions.push_back(2);
while (Crash(TempX, TempY)) {
switch (TempNum) {
case 0: { TempX[0]++; } break;
case 1: { TempY[0]--; } break;
case 2: { TempX[0]++; } break;
case 3: { TempY[0]--; } break;
}
Instructions.back() = TempNum;
PlaceCursor(0, 35); printf("%d", TempNum);
TempNum++;
Sleep(250);
if (TempNum >= 4) { break; }
}
}
if (FoodY > TempY[0]) {
TempY[0]++; Instructions.push_back(1);
while (Crash(TempX, TempY)) {
switch (TempNum) {
case 0: { TempX[0]++; } break;
case 1: { TempY[0]--; } break;
case 2: { TempX[0]++; } break;
case 3: { TempY[0]--; } break;
}
Instructions.back() = TempNum;
PlaceCursor(0, 35); printf("%d", TempNum);
TempNum++;
Sleep(250);
if (TempNum >= 4) { break; }
}
}
if (FoodY < TempY[0]) {
TempY[0]--; Instructions.push_back(0);
while (Crash(TempX, TempY)) {
switch (TempNum) {
case 0: { TempX[0]++; } break;
case 1: { TempY[0]--; } break;
case 2: { TempX[0]++; } break;
case 3: { TempY[0]--; } break;
}
Instructions.back() = TempNum;
PlaceCursor(0, 35); printf("%d", TempNum);
TempNum++;
Sleep(250);
if (TempNum >= 4) { break; }
}
}
TempNum = 0;
//Sleep(50);
//DrawSnake(RED, TempX, TempY);
}
SetColor(CYAN, BLACK);
PlaceCursor(25, 0);
printf("AI PATH COMPLETED");
Sleep(500);
PlaceCursor(25, 0);
printf(" ");
return;
}
void DrawSnake(const int color, int Xz[], int Yz[]) {
SetColor(color, BLACK);
for (int x = 10; x > 0; x--) { Xz[x] = Xz[x - 1]; Yz[x] = Yz[x - 1]; }
for (int x = 10; x >= 0; x--) { PlaceCursor(Xz[x], Yz[x]); printf("*"); }
SetColor(GREEN, BLACK);
PlaceCursor(Xz[0], Yz[0]); printf("@");
//PlaceCursor(Xz[10], Yz[10]); SetColor(BLACK, BLACK); printf(" ");
if (Xz[0] != Xz[10] || Yz[0] != Yz[10]) { PlaceCursor(Xz[10], Yz[10]); SetColor(BLACK, BLACK); printf(" "); }
return;
}
void RunPath(const int color) {
/* It'll crash sometimes if it randomly is empty */
if (!Instructions.empty()) {
SetColor(color, BLACK);
for (int x = 0; x < Instructions.size(); 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(50);
DrawSnake(color, SnakeX, SnakeY);
if (Crash(SnakeX, SnakeY)) { for (int x = 0; x < 100; x++) { SnakeX[x] = 5; SnakeY[x] = 5; } Instructions.clear(); }
}
}
return;
}
void NewRun() {
FoodX = rand() % 70 + 5;
FoodY = rand() % 25 + 5;
PlaceCursor(FoodX, FoodY);
SetColor(YELLOW, BLACK);
printf("x");
Instructions.clear();
return;
}
void SpawnFood(const int X, const int Y) {
if (SnakeX[0] == FoodX && SnakeY[0] == FoodY) {
FoodX = X;
FoodY = Y;
PlaceCursor(FoodX, FoodY);
SetColor(YELLOW, BLACK);
printf("x");
} else {
SetColor(CYAN, BLACK);
PlaceCursor(0, 0);
printf("SnakeX: %d ", SnakeX[0]);
PlaceCursor(0, 1);
printf("SnakeY: %d ", SnakeY[0]);
}
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] = 60;
SnakeY[0] = 25;
FoodX = 60;
FoodY = 25;
Instructions.clear();
while (true) {
SpawnFood(25, 25);
CreatePath();
RunPath(BLUE);
SpawnFood(25, 40);
CreatePath();
RunPath(BLUE);
SpawnFood(30, 20);
CreatePath();
RunPath(BLUE);
SpawnFood(25, 20);
CreatePath();
RunPath(BLUE);
SpawnFood(35, 20);
CreatePath();
RunPath(BLUE);
}
cin.get();
return 0;
}
Specifically what's confusing is: The Snake (when "thinking") does not follow the same "rules" as the Snake when it's really running. They follow two different paths, which is fucking whacko. The AI Snake will take an actual SHORTER and ANGLED path, when the real Snake is forced to take UP then RIGHT then UP then RIGHT (no angled movements). This time, I'm dead-positive there isn't a logical error, as you can clearly see the code, it uses the same DrawSnake function, and it uses the same vector for instructions.
Snake AI not shown:
http://www.youtube.com/watch?v=ztQU55dIyfsSnake AI shown:
http://www.youtube.com/watch?v=DRCAhBIjZpsI'm pretty sure the error I'm looking for is located in (or has to do with): DrawSnake(const, int, int)!The logical error has nothing to do with DrawSnake function.
I'm starting to think perhaps it's how I have the instructions set up...
Both the AI and the "real" Snake share the same instruction vector - perhaps that's it?
EDIT: This is a link to the (extremely old and out-dated) "Snake" project (on D2JSP):
http://forums.d2jsp.org/index.php?showtopic=32208514&f=120&st=0This post was edited by Muted on Oct 7 2009 05:04pm