0

The problem is located under the Draw function, where I use the system() command.

#include <iostream>
#include <conio.h>
#include <stdlib.h>
using namespace std;

bool gameover;
const int width = 60;
const int height = 30;
int x, y, FruitX, FruitY;
enum edirection { Stop = 0, Left, Right, Up, Down, };
edirection dir;

void Setup()
{
    gameover = true;
    dir = Stop;
    x = width / 2;
    y = height / 2;
    FruitX = rand() % width;
    FruitY = rand() % height;
    
}

void Draw()
{
    system("cls"); //Clears Screen, but is not working!!!

    //Top Line
    for (int i = 0; i <= width; i++)
        cout << "#";
        cout << endl;
    
    //Side Lines
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            if (j == 0 || j == width - 1)
                cout << "#";
            
            if (i == y && j == x) 
                cout << "<";

            else if (i == FruitY && j == FruitX)
                cout << "@";
            
            else if (j > 0 || j != width - 1)
                cout << " ";
        } cout << endl;
    } 

    //Bottom Line
    for (int i = 0; i <= width; i++)
        cout << "#";
    cout << endl;
}

void Input()
{
    if (_kbhit())
    {
        switch (_getch())
        {
        case 'a':
            dir = Left;
            break;
        case 'd':
            dir = Right;
            break;
        case 'w':
            dir = Up;
            break;
        case 's':
            dir = Down;
            break;
        case 'x':
            gameover = true;
            break;
        }
    }
}

void Logic()
{
    switch (dir)
    {
    case Left:
        x--;
        break;
    case Right:
        x++;
        break;
    case Up:
        y--;
        break;
    case Down:
        y++;
        break;
    default:
        break;
    }
}

int main()
{
    Setup();
    while (!gameover);
    {
        Draw();
        Input();
        Logic();
    }
}
user438383
  • 5,716
  • 8
  • 28
  • 43
James
  • 5
  • 1
  • 1
    Step through the code in a debugger. Look at the control flow being taken. – chris Jan 09 '22 at 19:00
  • 1
    The `Setup()` function sets `gameover` to `true`, so the loop body in `main()` is never executed, and `Draw()` is never called. – Peter Jan 09 '22 at 19:06
  • Global variables should be avoided as much as possible. See [here](https://stackoverflow.com/questions/484635/are-global-variables-bad) – digito_evo Jan 09 '22 at 19:12
  • If you call `system` it will open a new console and execute `cls` in that console and not in your application console. – Phil1970 Jan 09 '22 at 19:21
  • @digito_evo How should I change the code to where I do not have global variables? I tried implementing the global variables into the main function while also making the void functions prototypes so as the functions would be read in the main before the void functions were implemented but that did not work. – James Jan 09 '22 at 19:50
  • @Peter The video I watched did as you said, but for me it actually did not show anything. So I did it the opposite, which I thought kind of made more sense because gameover at true means when gameover is false, the game continues. The way I implemented it, it does everything but the terminal clear. – James Jan 09 '22 at 19:53
  • @Phil1970 How do I fix my issue. The exact problem is that when I put input through the keyboard, it closes the terminal instead of allowing the snake head (<) to move. – James Jan 09 '22 at 19:54

1 Answers1

0

I improved your code and now it works to some degree. However, I can't write the whole game for you since I have no info on how it should be written.

Take a look:

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <conio.h>


struct GameStatus
{
    static constexpr std::size_t width { 60 };
    static constexpr std::size_t height { 30 };

    std::size_t x { };
    std::size_t y { };
    std::size_t FruitX { };
    std::size_t FruitY { };
    enum edirection { Stop = 0, Left, Right, Up, Down, };
    edirection dir;

    bool gameover { };
};

void Setup( GameStatus& game_status )
{
    game_status.gameover = false;
    game_status.dir = game_status.Stop;
    game_status.x = game_status.width / 2;
    game_status.y = game_status.height / 2;

    std::srand( std::time( 0 ) );
    game_status.FruitX = std::rand( ) % game_status.width;
    game_status.FruitY = std::rand( ) % game_status.height;
}

void Draw( GameStatus& game_status )
{
    system( "cls" );

    //Top Line
    for ( std::size_t i { }; i <= game_status.width; ++i )
    {
        std::cout << '#';
    }

    std::cout << '\n';

    //Side Lines
    for ( std::size_t i { }; i < game_status.height; ++i )
    {
        for ( std::size_t j { }; j < game_status.width; ++j )
        {
            if ( j == 0 || j == game_status.width - 1 )
                std::cout << '#';
            
            if ( i == game_status.y && j == game_status.x )
                std::cout << '<';

            else if ( i == game_status.FruitY && j == game_status.FruitX )
                std::cout << '@';
            
            else if ( j > 0 || j != game_status.width - 1 )
                std::cout << ' ';
        }

        std::cout << '\n';
    } 

    //Bottom Line
    for ( std::size_t i { }; i <= game_status.width; ++i )
        std::cout << '#';

    std::cout << '\n';
}

void Input( GameStatus& game_status )
{
    if ( _kbhit( ) )
    {
        switch ( _getch( ) )
        {
            case 'a':
                game_status.dir = game_status.Left;
                break;
            case 'd':
                game_status.dir = game_status.Right;
                break;
            case 'w':
                game_status.dir = game_status.Up;
                break;
            case 's':
                game_status.dir = game_status.Down;
                break;
            case 'x':
                game_status.gameover = true;
                break;
        }
    }
}

void Logic( GameStatus& game_status )
{
    switch ( game_status.dir )
    {
        case game_status.Left:
            --game_status.x;
            break;
        case game_status.Right:
            ++game_status.x;
            break;
        case game_status.Up:
            --game_status.y;
            break;
        case game_status.Down:
            ++game_status.y;
            break;
        default:
            break;
    }
}


int main( )
{
    GameStatus game_status;

    Setup( game_status );

    while ( !game_status.gameover )
    {
        Draw( game_status );
        Input( game_status );
        Logic( game_status );
    }
}

You can see the struct GameStatus. All those dangerous globals are now encapsulated in an instance of this struct called game_status. All the functions can receive a reference to that object and then use it (read/modify).

digito_evo
  • 3,216
  • 2
  • 14
  • 42
  • This has given me a lot to look at, I appreciate your help ever so much. I am just trying to learn as much as I can, and you have given me a bunch to think about. – James Jan 09 '22 at 20:44
  • @James It is exactly the same as your code. I have not touched the logic. I have just added a struct (object-oriented programing) to get rid of those global variables. It's pretty simple. Nothing complicated. But it sure seems a bit overwhelming when you are a beginner. Also, I fixed a few minor bugs. – digito_evo Jan 09 '22 at 20:48
  • I have not learned about structs or what they are yet, but will definitely look more into it. Although it is the same code, your version looks more complex, and I feel as if I could learn some "syntax" or "style" from what you wrote. Sorry I do not know how to exactly phrase it haha. Again though, thank you for your time. Much appreciated. – James Jan 09 '22 at 20:57
  • @James You're welcome. If this answer helped you then please consider accepting it. – digito_evo Jan 09 '22 at 20:58
  • Just accepted it. Not just a noob at programming but on this site as well haha. Have a wonderful rest of your day! – James Jan 09 '22 at 21:01
  • @James In C++ `struct` is the same as `class`. They differ in only one thing which you can learn by reading about them. Also, the reason my version seems more complex is because of the noise caused by the variable `game_status`. If you pay attention you'll notice that it's petty much the same code. That's one of the downsides of object-oriented programing. In fact, I know quite many programmers who hate OOP. – digito_evo Jan 09 '22 at 21:02
  • @James In simple terms, I have just added `game_status.` to each of those global variables. `game_status` is the name of an object defined in the body of `main()`. And **`.`** is called the **member selection operator**. Read about these concepts on the web and you'll see that it's all digestible. – digito_evo Jan 09 '22 at 21:07