-1

i am trying to implement this snake tutorial https://www.youtube.com/watch?v=XdahrXxX5zE&list=PL3pKgZpYZLjmNpbeZrcL8pBSq3YPb-8G6&index=14, and i stuck trying to make the snake move by itself in the direction that i pressed (a,w,s,d), and i am in the part of the tutoria where the guy says that i need to reemmplaze the var with the dir variable in order to make the continuis movemento of the snake this is where my programs have odd errors, first the snake does not move continously and y already did the part in the tutorial that makes that, and when i keep press one of the keys it do start to move continuisly but it stop to answering to the keyboard

weird bugs i have also more odd bugs like that segment violation or the fack that i need to press a key to make the frog appears but this is not that bad as the first bug describe at the begiinit it does not allowme to continue the program

here is my code


#include <cctype>
#include <cstdlib>
#include <curses.h>
#include <stdio.h>
#include <wchar.h>
#include <locale.h>
#include <stdlib.h>
#include <ncurses.h>
#include <ctime>
#include <time.h>
#include <errno.h>
#define N 20
#define M 40
int i,j,Field[N][M],x,y,gy,Head,Tail,Game,Frogs,a ,b,var,dir;
void snakeInitialization(){
  for(i=0;i<N;i++){
    for(j=0;j<M;j++){
      Field [i][j]=0;
    }
  }
  x=N/2;
  y=M/2;
  Head=5;
  Tail=1;
  gy=y;
  Game = 0;
  Frogs = 0;
  a = 0;
  b = 0;
  var = 0;
  for(i=0;i<Head;i++)
  {
    gy++;
    Field[x][gy-Head]=i+1;
  }
}
int kbhit(void)    /* comment */
{
    int ch, r;

    // turn off getch() blocking and echo
    nodelay(stdscr, TRUE);
    noecho();

    // check for input
    ch = getch();
    if( ch == ERR)      // no input
            r = FALSE;
    else                // input
    {
            r = TRUE;
            ungetch(ch);
    }

    // restore block and echo
    nodelay(stdscr, FALSE);
    return(r);
}
int msleep(long msec)
{
    struct timespec ts;
    int res;

    if (msec < 0)
    {
        errno = EINVAL;
        return -1;
    }

    ts.tv_sec = msec / 1000;
    ts.tv_nsec = (msec % 1000) * 1000000;

    do {
        res = nanosleep(&ts, &ts);
    } while (res && errno == EINTR);

    return res;
}

void print()
{
  wchar_t RDC = 0x255D;//right down corner simbol
  wchar_t LDC = 0x255A;//left down corner unicode simbol
  wchar_t VW = 0x2551;//vertical wall simbol
  wchar_t HW = 0x2550;//Horizontal wall simbol
  wchar_t RUC = 0x2557;//right up corner simbol
  wchar_t LUC = 0x2554;//left up corner simbol
  wchar_t HS = 0x2593;
  wchar_t BS = 0x2591;
  wchar_t Frg = 0x1318F;//frog
  // wprintf(L"unicode code  255A prints  %lc\n", LDC);
  // wprintf(L"unicode code 2551 prints %lc\n",VW);
  // wprintf(L"unicode code 2550 prints %lc\n",HW);
  // wprintf(L"unicode code 255D prints %lc\n",RDC);
  // wprintf(L"unicode code 2557 prints %lc\n",RUC);

  // printf ("asscii of 188 gives: %c\n\n",188);
  // printf("%c", 65);
  for (i=0;i<=M+1;i++)
  {
    if(i==0)
    {
      printw("%lc",LUC);
    }
    else if (i==M+1){
      printw("%lc",RUC);
    }
    else{
      printw("%lc",HW);
    }
  }
  printw("\n");
  for(i=0;i<N;i++)
  {
    printw("%lc",VW);
    for (j=0;j<M;j++)
    {
      if(Field[i][j]==0) printw(" ");
      if(Field[i][j]>0&&Field[i][j]!=Head) printw("%lc",BS);
      if(Field[i][j]==Head) printw("%lc",HS);
      if(Field[i][j]==-1) printw("%lc",Frg);
      if(j==M-1) printw("%lc\n",VW);
    }
  }
  for (i=0;i<=M+1;i++)
  {
    if(i==0)
    {
      printw("%lc",LDC);
    }
    else if (i==M+1){

      printw("%lc",RDC);
    }
    else{
      printw("%lc",HW);
    }
  }
}
void ResetScreenPosition(){
  move(0, 0);
}
void Random (){
  srand(time(0));
  a = 1 + rand() % 18;
  b = 1 + rand() % 38;
  if (Frogs == 0 && Field[a][b]==0) {
    Field[a][b] = -1;
    Frogs = 1;
  }
}
long int getch_noblock(){
  if(!kbhit())
    return getch();
  else
    return -1;
}
void movement(){
  var = getch_noblock();
  var = tolower(var);
  if (var == 'd' || var == 'a' || var == 'w' || var == 's') {
    dir=var; 
  }
  if (dir == 'd'){
    y++;
    Head++;
    Field[x][y]=Head;
  }
  if (dir == 'a'){
    y--;
    Head++;
    Field[x][y]=Head;
  }
  if (dir == 'w'){
    x--;
    Head++;
    Field[x][y]=Head;
  }
  if (dir == 's'){
    x++;
    Head++;
    Field[x][y]=Head;
  }
}
int main (int argc, char *argv[]) {
  setlocale(LC_CTYPE, "");
  snakeInitialization();  // moving cursor, x = 20, y = 10
  initscr();
  while (Game == 0) {
    print();
    ResetScreenPosition();
    Random();
    movement();
    msleep(99);
    refresh();

  }
  endwin();
  return 0;
}

and here is the full snake code from the tutorial https://github.com/pawanprjl/Snake-Game-in-C

i thought it could be the kbhit implemetation but i cant figure out. and this is the part of the code that i cant figure out how to make it work as i see in the video

    void movement(){
  var = getch_noblock();
  var = tolower(var);
  if (var == 'd' || var == 'a' || var == 'w' || var == 's') {
    dir=var; 
  }
  if (dir == 'd'){
    y++;
    Head++;
    Field[x][y]=Head;
  }
  if (dir == 'a'){
    y--;
    Head++;
    Field[x][y]=Head;
  }
  if (dir == 'w'){
    x--;
    Head++;
    Field[x][y]=Head;
  }
  if (dir == 's'){
    x++;
    Head++;
    Field[x][y]=Head;
  }
}
Linuxero
  • 37
  • 2
  • Welcome to Stack Overflow. Please read [the help pages](http://stackoverflow.com/help), take the SO [tour], read [ask], as well as [how to write the "perfect" question](https://codeblog.jonskeet.uk/2010/08/29/writing-the-perfect-question/), especially its [checklist](https://codeblog.jonskeet.uk/2012/11/24/stack-overflow-question-checklist/). Also please learn how to create a [mre], with emphasis on the *minimal* part. – Some programmer dude Jun 06 '23 at 03:23
  • I also recommend you try to learn programming from another source, one that doesn't teach you bad habits like all those global variables, including header file you don't need, using only a single large source file, inconsistent formatting, and of course that teach you only one language at a time. Are you programming in C or C++? Those are two *Very* different languages, and your design and implementation depends *very* much on the selected language. – Some programmer dude Jun 06 '23 at 03:24
  • weird bugs like : access violations . No this is not a weird bug, this is a fundamental one (that needs fixing first). Remember C++ does protect you from accessing memory where you should not access it. Like reading/writing from an address outside the bounds of an array. – Pepijn Kramer Jun 06 '23 at 03:36
  • Before you start using external libraries (like ncurses) first get some more basic C++ knowledge from : [a recent C++ book](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) or from [learncpp.com](https://www.learncpp.com/) that site is decent and pretty up to date. Then use [cppreference](https://en.cppreference.com/w/) for reference material (and examples). When you have done all that keep using [C++ core guidelines](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines) to keep up to date with the latest best practices since C++ keeps evolving. – Pepijn Kramer Jun 06 '23 at 03:36
  • Your `Random` function is flawed. Is that part of the video you're learning from? The `time` function usually returns the time in *seconds* from some specific point. Think about what happens if you call it multiple times in one second, what seed will be set, and what random number will be generated from that seed, if you're using a deterministic PRNG like `rand`. – Some programmer dude Jun 06 '23 at 03:50
  • @Someprogrammerdude yes te ramdom funtion is part of the vidio , it seems very weird to me but it seems to work. – Linuxero Jun 06 '23 at 04:09
  • 1
    You should call `srand` only *once* in your program, unless you want to get the same series of numbers. That the video contains that simple flaw means it's probably not a very good resource to use for learning. In fact, it's likely that over 99% of all videos on YouTube are probably of the same dubious quality. And like I also said above, if you learned all the bad habits shown in the code from such videos, you should stop using them. Please invest in some books, and take actual (paid) online courses. Might be expensive right now, but in the long run it will pay off. – Some programmer dude Jun 06 '23 at 04:21
  • can you recomend a very good paid coursee ? i do not know if you are referring to the udemy ones – Linuxero Jun 06 '23 at 04:25

1 Answers1

1

Your getch_noblock function is making a blocking call to getch if kbhit returns zero.

  if(!kbhit())
    return getch();

That would be fine if a zero return-value from kbhit means that there's something to read. But that's not the case.

The "standard" kbhit function returns non-zero when a key-press is available, and zero otherwise. It appears your implementation does, too:

    ch = getch();
    if( ch == ERR)      // no input
            r = FALSE;
    else                // input
    {
            r = TRUE;
            ungetch(ch);
    }

And so your non-blocking read function is broken. This is the correct way:

long int getch_noblock(){
  if(kbhit())
    return getch();
  else
    return -1;
}
paddy
  • 60,864
  • 6
  • 61
  • 103