Home > Enterprise >  Snake Game going too fast console c
Snake Game going too fast console c

Time:01-02

I've been following a few tutorials for making a somewhat Snake Game , just not a full-tailed-one , It's going alright and i think i got it almost right but I've got two problems

#include <bits/stdc  .h>
#include <conio.h>
#include <unistd.h>
using namespace std;

int side,x,y;
int fruitx,fruity,score,flag;
bool isOver;

void randomize();
void frame(int);
void userinp();
void game();

int main(){
    do{
        cout << "Enter the side of your frame!(not less than 20)\n";
        cin >> side;
    }while(side < 20);
    randomize();
    while(!isOver){
        frame(side);
        userinp();
        game();
    }
    return 0;
}

void randomize(){
    x = side/2;
    y = side/2;
    label1: fruitx = rand()%side;
    if (fruitx == 0 || fruitx == side)
        goto label1;
    label2:
    fruity = rand()%side;
    if (fruity == 0 || fruity == side)
        goto label2;

    score = 0;
}
void frame(int s){
    system("cls");
    for(int i=1;i<=s;i  ){
        for(int j=1;j<=s;j  ){
            if(i == 1 || i == s || j == 1 || j == s)
                cout << "*";
            else{
                if(i == x && j == y){
                    cout << "-";
                }
                else if(i == fruitx && j == fruity){
                    cout << "x";
                }
                else
                    cout << " ";
            }
        }
        cout << "\n";
    }
    cout << "Your score: " << score << endl;
}
void userinp(){
    if(kbhit()){
        switch (getch()){
        case 'a':
            flag = 1;
            break;
        case 's':
            flag = 2;
            break;
        case 'd':
            flag = 3;
            break;
        case 'w':
            flag = 4;
            break;
        default:
            isOver = true;
        }
    }
}
void game(){
    sleep(0.899);
    switch (flag){
    case 1:
        y--;
        break;
    case 2:
        x  ;
        break;
    case 3:
        y  ;
        break;
    case 4:
        x--;
        break;
    }
     if (x < 0 || x > side || y < 0 || y > side){
        x = side/2;
        y = side/2;
     }
     if (x == fruitx && y == fruity) {
        label3: fruitx = rand()%(side);
        if (fruitx == 0)
            goto label3;

        label4: fruity = rand()%(side);
        if (fruity == 0)
            goto label4;

        score  ;
    }
}

the first problem:

using system"(cls") helped with the screen not going down way many times to avoid the screen scrolling down i tried it to make the screen clear every time the sleep() is called but i cannot get how to slow down the process a bit using the sleep() function , It's either too slow or too fast The screen , Is there a different way to approach the whole thing or is the function itself not proper to use here ?

second problem: whenever i input the side with 20 , i cannot find the fruit itself at all but when it is any number more than this it does show me the random fruits just fine so is there a way to fix why at just side = 20 it would not work ?

PS: If there is anything that could be improved aside from these 2 problems i'd appreciate it .. Thanks in advance!

CodePudding user response:

First sleep is a bit rough. See answers here for better solutions: Sleep for milliseconds

Second you don't account for your own overhead. Your program might run faster/slower on different setups. For games in general you want to use a somewhat precise but fast time function to get an idea of how much to move everything (granted not really needed for snake). For more suggestions on this topic see this quesiton: How to Make a Basic FPS Counter?

Last the console is not really good for this sort of application. I would suggest switching to a simple GUI, just so you don't have to deal with the console craziness. If your goal is to have some sort of demo to learn something and move on it might be ok, and live with the strange behavior.

For the issue with the fruit:

  • NEVER use goto. It's very hard to reason about it and for the standard tools to deal with it. Use functions/loops that are easier reason about. In your case a do{ friutx = ...; } while (friuitx==0) would do.
  • The two places where you setup the fruit use different code. Likely even if you fix one, the other might still be broken. Create a function and call it from both places.
  • % will do a reminder (0 to side-1, inclusive). Looks like your target is 2 to side-1, so maybe do rand()%(side-1) 1 or better yet, use std::uniform_int_distribution.
  • It's not clear to me why it's not seen correctly. Use a debugger to check when you are rendering a frame what are the coordinates of the fruit. They might overlap the edges and be replaced with a *.
  • Related