# Thread: Can you spot debug? [snake]

1. ## Can you spot debug? [snake]

A week ago I made the known game snake.
The problem is that sometimes the tail doesn't change to zero (=empty).
The idea of the move is that I take the corrent head and put the body then I put the head (='@') on the next step (up\down\left\right) and at last remove the tail by changing his value in the board to zero.
I hope I was clear.
Here is the main code:

Code:
void move(char board[n][m], int x)
{
board[hi][hj] = direction; // I SUSPECT THAT PART OF THE PROBLEM IS HERE //
CHEAT:
switch (x)
{
case UP:
{
if (direction == DOWN)
{
x = DOWN;
goto CHEAT;
}
if (hi > 0)
{
if (board[hi-1][hj] == FOOD)
exist = FALSE;
else if (board[hi-1][hj] == 0)
direction = UP;
hi--;
}
}
break;
case DOWN:
{
if (direction == UP)
{
x = UP;
goto CHEAT;
}
if (hi < n)
{
if (board[hi+1][hj] == FOOD)
exist = FALSE;
else if (board[hi+1][hj] == 0)
direction = DOWN;
hi++;
}
}
break;
case LEFT:
{
if (direction == RIGHT)
{
x = RIGHT;
goto CHEAT;
}
if (hj > 0)
{
if (board[hi][hj-1] == FOOD)
exist = FALSE;
else if (board[hi][hj-1] == 0)
direction = LEFT;
hj--;
}
}
break;
case RIGHT:
{
if (direction == LEFT)
{
x = LEFT;
goto CHEAT;
}
if (hj < m)
{
if (board[hi][hj+1] == FOOD)
exist = FALSE;
else if (board[hi][hj+1] == 0)
direction = RIGHT;
hj++;
}
}
break;
case ESC:
{
clr();
score = 0;
len = 3;
main();
}
}
board[hi][hj] = '@';
if (exist)
{
board[ti][tj] = 0;
if (board[ti+1][tj] == DOWN && ti < n)
ti++;
else if (board[ti-1][tj] == UP && ti > 0)
ti--;
else if (board[ti][tj+1] == RIGHT && tj < m)
tj++;
else if (board[ti][tj-1] == LEFT  && tj > 0)
tj--;
}
else
{
if (snd)
sound();
len++;
score += len*speed;
print();
create_food(board);
exist = TRUE;
}
}
Thanks (:

2. I'm not sure what your problem might be at the moment, but I don't see you doing bounds checking anywhere. In other words, what if ti is 0 and you try to access board[ti - 1]? You'll have a buffer underflow. Or if ti is too high for you to go board[ti + 1], you'll have a buffer overflow -- same problem, different direction.

I should also mention, of course, that goto is bad. I'm sure you know that already, but perhaps you don't know that calling main() recursively is also a bad idea. Not only might you overflow the stack eventually, but recursively calling main() is not allowed in C++. I think it's still allowed in C, but still, it's not a good idea. (Is that a circular argument? . . . .)

I hope n and m are #defines or enums or constant values of a sort.

3. You right, usually I do set bound [I forgot doing so this time] - fixed.
I know goto is bad, but unfortunately I got for using goto's \:
but don't worry I tend to be carefull with diz.
You right again I didn't think about it this way but I didn't have any choice - in C calling to a function that doesn't exist isn't allowed so if the player lose he will can't play again without exit.
No it's not.
n and m are #defines.
Why do you hope so?

4. Does it work now after the changes?

5. Also, the goto statements can be completely removed by putting another switch statement before the switch(x) statement.

--
Mats

6. Personally I m not against goto if it is used in a simple way. Simple, like the way it is used in the above program. Only one address to goto, which is in the top of the program.
Or when used to break from multiple for-loops

7. Originally Posted by C_ntua
Personally I m not against goto if it is used in a simple way. Simple, like the way it is used in the above program. Only one address to goto, which is in the top of the program.
Or when used to break from multiple for-loops
I don't disagree with a back-wards goto like the one above, but it should only be used if it's actually making the code simpler to understand - something that I don't believe is the case with the above code.

I'm not a "goto-forbidder", but I don't like to see goto used in replacement for code that is clear and easy to follow. Two switch-statements would be a better solution in that sense.

--
Mats

8. No.
---
As I said I use goto very carefully and "in a simple way" as C_ntua said.
You right it's a little bit confusing but as I said I am addict \:
goto always attracts a good experienced programmer [: but let's go back from this off topic to my damned problem plz.

9. Originally Posted by gavra
No.
---
As I said I use goto very carefully and "in a simple way" as C_ntua said.
You right it's a little bit confusing but as I said I am addict \:
goto always attracts a good experienced programmer [: but let's go back from this off topic to my damned problem plz.
I suspect you are not as experienced as you say you are - I have been programming for about 25 years now, and I have used goto sometimes, but only when there is a valid need for it. Yours is not. And it's not a sign of experience to use bad coding style.

--
Mats

10. I am not talking about me I am talking about you.
"goto always attracts a good experienced programmer to give a comment"

Anyway help me (again) with diz bug plz.

11. What is your updated code, and what exactly is the problem now?

12. I edit the one above so it's up to date.
The problem is that somehow the tail of the snake doesn't removed.
I think the board gets the wrong direction:
board[hi][hj] = direction;
but I don't know why..
cause it works and suddenly the bug comes and the tail stays.
Should I bring the EXE file (windows..) or the whole code?

13. Without the whole program, we can't step through the program, to see what's happening.

You'll need to post the whole program, but NOT the compiled, (exe) program. We can't step through the compiled program, and most people won't run an exe program from a stranger, for security reasons.

14. Originally Posted by gavra
"goto always attracts a good experienced programmer to give a comment"

Anyway help me (again) with diz bug plz.
But not the comments you want...

--
Mats

15. What do you mean?
---
Ok I don't have any problem to post the whole code eventhough I don't think you need the whole code but what ever your problem.
and plz don't call me "stranger".

I can't edit my first message so I will post the whole code here:

Code:
#include <stdio.h>
#include <conio.h>
#include <windows.h>
#include <stdlib.h>
#include <string.h>

#ifdef linux
#define clr() system("clear");
#elif _WIN32
#define clr() system("cls");
#endif

#define n 20
#define m 40
#define ESC 27
#define UP 72
#define LEFT 75
#define RIGHT 77
#define DOWN 80
#define PAUSE 112
#define ENTER 13
#define FOOD '\$'
#define TRUE 1
#define FALSE 0

int hi, hj, ti, tj, direction, score=0, speed=6, exist, temp, x, flag, p, snd=1, len=3;

void gotoxy(int y, int x)
{
COORD coord;
coord.X = x;
coord.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}

void sound()
{
Beep (2000,10);
}

{
DWORD attr;
attr = GetFileAttributes(fname);

if (attr == INVALID_FILE_ATTRIBUTES)
return 0;

attr ^= FILE_ATTRIBUTE_HIDDEN;

if (!SetFileAttributes(fname, attr))
return 0;

return 1;
}

{
FILE *in;
char c, tmp[9], i;
clr();
in = fopen ("c:\\Highscore.txt","r+");
if (in == NULL)
{
printf("No Highscores");
getchar();
clr();
main();
}
gotoxy(10,30);
printf("Name: ");
for (c = fgetc(in);(c > 64 && c!= EOF);c = fgetc(in))
printf("&#37;c",c);
if (c == 48)
printf("NONE");
gotoxy(11,30);
printf("Score: ");
tmp[i=0]=i;
for (c = fgetc(in);c != EOF;c = fgetc(in))
{
tmp[i] = c;
i++;
}
if (tmp[0] != 0)
{
tmp[i] = PAUSE;
for (i=0; tmp[i] != PAUSE ;i++)
printf("%c",tmp[i]);
}
else printf("NONE");
}

{
FILE *in, *out;
char str[9], name[10];
int max;
in = fopen ("c:\\Highscore.txt","r+");
if (in == NULL)
{
out = fopen("c:\\Highscore.txt","w+");
fputc ('0',out);
fclose (out);
in = fopen ("c:\\Highscore.txt","r+");
}
fgets (name,10,in);
fgets (str,9,in);
max = strtol(str, NULL, 10);
if (score > max)
{
gotoxy(10,30);
printf ("New Highscore!");
rewind (in);
gotoxy(11,30);
gets(name);
fprintf(in,"%s\n",name);
fprintf (in,"%d",score);
}
fclose(in);
}

void print()
{
gotoxy(10,45);
}

void draw (char board[n][m])
{
int i,j;
//clr();
gotoxy(1,1);
for (i=0;i<n;i++)
{
for (j=0;j<m;j++)
{
if (board[i][j] == UP || board[i][j] == DOWN || board[i][j] == LEFT || board[i][j] == RIGHT)
printf ("o");
else if (board[i][j] == 0)
printf (" ");
else printf("%c",board[i][j]);
}
gotoxy(i+1,m+1);
printf ("#\n#");
}
}

void cpu(char board[n][m])
{
int i,j;
for (i=0;i<n;i++)
{
for (j=0;j<m;j++)
if (board[i][j] == FOOD)
break;
if (board[i][j] == FOOD)
break;
}
if (hi > i && direction != DOWN && (board[hi-1][hj] == 0 || board[hi-1][hj] == FOOD))
x = UP;
else if (hj > j && direction != RIGHT && (board[hi][hj-1] == 0 || board[hi][hj-1] == FOOD))
x = LEFT;
else if (hi < i && direction != UP && (board[hi+1][hj] == 0 || board[hi+1][hj] == FOOD))
x = DOWN;
else if (hj < j && direction != LEFT && (board[hi][hj+1] == 0 || board[hi][hj+1] == FOOD))
x = RIGHT;
else
{
if (direction != DOWN)
x = UP;
else if (direction != LEFT)
x = RIGHT;
else if (direction != UP)
x = DOWN;
else if (direction != RIGHT)
x = LEFT;
}
gotoxy(15,60);
switch (x)
{
case UP: printf("%c",24);
break;
case DOWN: printf("%c",25);
break;
case LEFT: printf("%c",27);
break;
case RIGHT: printf("%c",26);
break;
}
}

void create_food (char board[n][m])
{
int i, j;
srand ((unsigned)time(NULL));
TRY:
i = rand() % (n-3) + 2;
j = rand() % (m-3) + 2;
if (board[i][j] != 0)
goto TRY;
board[i][j] = FOOD;
}

int crash (char board[n][m], int direction, int hi, int hj)
{
switch (direction)
{
case UP:
{
if (hi == 0 || board[hi-1][hj]  == UP || board[hi-1][hj]  == DOWN || board[hi-1][hj]  == LEFT || board[hi-1][hj]  == RIGHT)
return 1;
}
break;
case DOWN:
{
if (hi == n-1 || board[hi+1][hj]  == UP || board[hi+1][hj]  == DOWN || board[hi+1][hj]  == LEFT || board[hi+1][hj]  == RIGHT)
return 1;
}
break;
case LEFT:
{
if (hj == 0 || board[hi][hj-1]  == UP || board[hi][hj-1]  == DOWN || board[hi][hj-1]  == LEFT || board[hi][hj-1]  == RIGHT)
return 1;
}
break;
case RIGHT:
{
if (hj == m-1 || board[hi][hj+1]  == UP || board[hi][hj+1]  == DOWN || board[hi][hj+1]  == LEFT || board[hi][hj+1]  == RIGHT)
return 1;
}
break;
}
return 0;
}

void input()
{
x = getch();
if (x == 224)
x = temp = getch();
else if (x == PAUSE)
{
gotoxy(11,45);
system("pause");
gotoxy(11,45);
printf("Press P to Pause               ");
x = temp;
}
}

void move(char board[n][m], int x)
{
board[hi][hj] = direction;
CHEAT:
switch (x)
{
case UP:
{
if (direction == DOWN)
{
x = DOWN;
goto CHEAT;
}
if (hi > 0)
{
if (board[hi-1][hj] == FOOD)
exist = FALSE;
else if (board[hi-1][hj] == 0)
direction = UP;
hi--;
}
}
break;
case DOWN:
{
if (direction == UP)
{
x = UP;
goto CHEAT;
}
if (hi < n)
{
if (board[hi+1][hj] == FOOD)
exist = FALSE;
else if (board[hi+1][hj] == 0)
direction = DOWN;
hi++;
}
}
break;
case LEFT:
{
if (direction == RIGHT)
{
x = RIGHT;
goto CHEAT;
}
if (hj > 0)
{
if (board[hi][hj-1] == FOOD)
exist = FALSE;
else if (board[hi][hj-1] == 0)
direction = LEFT;
hj--;
}
}
break;
case RIGHT:
{
if (direction == LEFT)
{
x = LEFT;
goto CHEAT;
}
if (hj < m)
{
if (board[hi][hj+1] == FOOD)
exist = FALSE;
else if (board[hi][hj+1] == 0)
direction = RIGHT;
hj++;
}
}
break;
case ESC:
{
clr();
score = 0;
len = 3;
main();
}
}
board[hi][hj] = '@';
if (exist)
{
board[ti][tj] = 0;
if (board[ti+1][tj] == DOWN && ti < n)
ti++;
else if (board[ti-1][tj] == UP && ti > 0)
ti--;
else if (board[ti][tj+1] == RIGHT && tj < m)
tj++;
else if (board[ti][tj-1] == LEFT  && tj > 0)
tj--;
}
else
{
if (snd)
sound();
len++;
score += len*speed;
print();
create_food(board);
exist = TRUE;
}
}

void init (char board[n][m])
{
int i,j;
for (i=0;i<n;i++)
for (j=0;j<m;j++)
board[i][j] = 0;
board[hi = n/2][hj = m/2] = '@';
board[n/2][m/2+1] = LEFT;
board[ti = n/2][tj = m/2+2] = LEFT;
create_food (board);
exist = TRUE;
direction = LEFT;
x = LEFT;
gotoxy(0,0);
for (i=0;i<=n;i++)
printf("##");
printf ("\n#");
for (i=0;i<n;i++)
{
for (j=0;j<m;j++)
{
if (board[i][j] == UP || board[i][j] == DOWN || board[i][j] == LEFT || board[i][j] == RIGHT)
printf ("o");
else if (board[i][j] == 0)
printf (" ");
else printf("%c",board[i][j]);
}
gotoxy(i+1,m+1);
printf ("#\n#");
}
gotoxy(n+1,0);
for (i=0;i<=n;i++)
printf("##");
print();
gotoxy(11,45);
printf("Press P to Pause");
gotoxy(12,45);
}

void play(int player)
{
char board[n][m], crs = 0;
init(board);
while (!crash(board,direction,hi,hj))
{
if (player == 0)
cpu(board);
if (kbhit())
if (player == 0)
{
player = 1;
clr();
main();
}
else input();
move (board,x);
draw(board);
sleep (200 - ((speed-1) * 25));
}
clr();
if (player == TRUE)
{
gotoxy(10,30);
printf("You have died!");
sleep(1000);
sleep(1000);
clr();
}
score = 0;
len = 3;
main();
}

void demo()
{
int dm = 0;
while (!kbhit())
{
sleep(10);
dm++;
if (dm > 700)
play(0);
}
}

{
if (flag)
{
gotoxy(9,30);
printf("Start Game");
gotoxy(10,30);
printf("Options        ");
gotoxy(11,30);
printf("Credits        ");
gotoxy(12,30);
printf("Exit");
}
else
{
gotoxy(9,30);
if (snd)
printf("Sound: ON        ");
else printf("Sound: OFF        ");
gotoxy(10,30);
printf("Speed: %d        ", speed);
gotoxy(11,30);
printf("Highscore        ");
gotoxy(12,30);
printf("Back");
}
return;
}

{
demo();
input();
while (x != ENTER)
{
CHOOSE:
switch (x)
{
case UP:
{
gotoxy(p,29);
printf(" ");
if (p > 9)
p--;
gotoxy(p,29);
printf("%c",26);
}
break;
case DOWN:
{
gotoxy(p,29);
printf(" ");
if (p < 12)
p++;
gotoxy(p,29);
printf("%c",26);
}
break;
default:
{
input();
goto CHOOSE;
}
}
demo();
input();
if (snd)
sound();
}
switch (p)
{
case 9:
{
if (flag)
play(1);
if (snd)
snd = 0;
else snd = 1;
}
break;
case 10:
{
if (flag)
{
flag = FALSE;
gotoxy(9,29);
printf(" ");
x=0;
}
input();
while (x != ENTER)
{
switch (x)
{
case LEFT:
{
if (speed > 1)
speed--;
}
break;
case RIGHT:
{
if (speed < 9)
speed++;
}
break;
}
gotoxy(10,30);
printf("Speed: %d        ", speed);
input();
if (snd)
sound();
}
}
break;
case 11:
{
clr();
if (flag)
{
gotoxy(11,20);
getch();
gotoxy(11,20);
printf("                             ");
gotoxy(11,29);
printf("%c",26);
}
else
{
x = 0;
gotoxy(12,30);
printf("Reset Highscore [ENTER]");
RESET:
if (kbhit())
x = getch();
else demo();
if (x == ENTER)
{
FILE *out;
out = fopen("c:\\Highscore.txt","w");
fputc ('0',out);
fclose (out);
goto RESET;
}
else if (x == ESC)
{clr();}
if (x != ESC && x != ENTER)
goto RESET;
clr();
gotoxy(11,29);
printf("%c",26);
}

}
break;
case 12:
{
if (flag)
exit(0);
else
{
flag = TRUE;
}
}
break;
}
}

int main()
{
flag = TRUE;
p = 9;
gotoxy(9,29);
printf("%c",26);
}