Using Exceptions in C++ for a Snake Game for Scientists

  • C/C++
  • Thread starter FallArk
  • Start date
In summary, the code uses a function to help with handling exceptions in a while loop that is part of a snake game. The function checks for a runtime_error and calls another function to process the exception. The purpose of the function is to handle exceptional situations that do not fit well in the normal program flow. The conversation also discusses the type of runtime_error and whether the function that processes the exception should return a bool.
  • #1
FallArk
127
0
How would I use function to help with exceptions when the code looks something like this:
Code:
while (true) {
    move++;
    try {
        movePlayer(board, uRow, uCol, move);
        moveOpponent(board, oRow, oCol, move);
        showBoard(board, move);
    }
    catch(runtime_error &except) {
        processException(except, win);
        break;
    }
}
Yes, it is part of the snake game.:)
My questions :
1.What is the type runtime_error?
2.Should the function processException be type bool?
 
Technology news on Phys.org
  • #2
FallArk said:
How would I use function to help with exceptions when the code looks something like this:
Code:
while (true) {
    move++;
    try {
        movePlayer(board, uRow, uCol, move);
        moveOpponent(board, oRow, oCol, move);
        showBoard(board, move);
    }
    catch(runtime_error &except) {
        processException(except, win);
        break;
    }
}
Yes, it is part of the snake game.:)
My questions :
1.What is the type runtime_error?
2.Should the function processException be type bool?

Hi FallArk! (Smile)

[m]runtime_error[/m] is a so called [m]exception[/m], which is intended to handle exceptional situations that do not fit well in the normal program flow.
To generate an exception, we have to [m]throw[/m] it.
Some of the standard library functions do that to handle exceptional situations.
A typical example is the [m]new[/m] operator that throws [m]bad_alloc[/m] (which is a [m]runtime_error[/m]) when there is not enough memory.

Suppose processException returned type bool, what would you do with it?
 
  • #3
I like Serena said:
Hi FallArk! (Smile)

[m]runtime_error[/m] is a so called [m]exception[/m], which is intended to handle exceptional situations that do not fit well in the normal program flow.
To generate an exception, we have to [m]throw[/m] it.
Some of the standard library functions do that to handle exceptional situations.
A typical example is the [m]new[/m] operator that throws [m]bad_alloc[/m] (which is a [m]runtime_error[/m]) when there is not enough memory.

Suppose processException returned type bool, what would you do with it?

Hey man, this is what I have:
Code:
#include <iostream>
#include <stdexcept>
#include <cstring>

using namespace std;

const int NUMROWS = 7;// CAN BE CHANGED FOR DIFFERENT GAME PLAY
const int NUMCOLS = 10;// CAN BE CHANGED FOR DIFFERENT GAME PLAY
const int TAILLENGTH = 15;// CAN BE CHANGED FOR DIFFERENT GAME PLAYstruct _cell {
char marker; int moveNumber;
};

void initBoard (_cell board[NUMROWS][NUMCOLS]) {
    for (int i = 0; i < NUMROWS; ++i) {
        for (int j = 0; j < NUMCOLS; ++j) {
            board[i][j].marker = '_';
            board[i][j].moveNumber = 0;
        }
    }
}

void showBoard (_cell board[NUMROWS][NUMCOLS], int &move) {
    for (int i = 0; i < NUMROWS; ++i) {
        for (int j = 0; j < NUMCOLS; ++j) {
                if ((board[i][j].marker != '_') && (move - board[i][j].moveNumber > TAILLENGTH))
                board[i][j].marker = '_';
            cout << board[i][j].marker << " ";
        }
        cout << endl;
    }
}

void placePiece (_cell board[NUMROWS][NUMCOLS], int row, int col, char player, int move) {
        board[row][col].marker = player;
        board[row][col].moveNumber = move;
}

void movePlayer (_cell board[NUMROWS][NUMCOLS], int &uRow, int &uCol, int move) {
    board[uRow][uCol].marker = 'u';
    cout << "Enter direction (N/S/E/W): ";
    char direction;
    cin >> direction;

    if (direction == 'N')
        uRow--;
    if (direction == 'S')
        uRow++;
    if (direction == 'W')
        uCol--;
    if (direction == 'E')
        uCol++;

    if ((uRow < 0)||(uRow > NUMROWS - 1)||(uCol < 0)||(uCol > NUMCOLS - 1)) {
        throw runtime_error("YOU FELL OFF THE BOARD!");
    }
    if (board[uRow][uCol].marker != '_'){
        throw runtime_error("BANG! YOU ARE DEAD!");
    }

    placePiece(board, uRow, uCol, 'U', move);
}void moveOpponent (_cell board[NUMROWS][NUMCOLS], int &Row, int &Col, int move) {
    board[Row][Col].marker = 'x';
    if ((Row > 0) && (board[Row - 1][Col].marker == '_')) {
        Row--;
        placePiece(board, Row, Col, 'X', move);
    }
    if ((Row < NUMROWS - 1) && (board[Row + 1][Col].marker == '_')){
        Row++;
        placePiece(board, Row, Col, 'X', move);
    }
    if ((Col > 0) && (board[Row][Col - 1].marker == '_')){
        Col--;
        placePiece(board, Row, Col, 'X', move);
    }
    if ((Col < NUMCOLS - 1) && (board[Row][Col + 1].marker =='_')){
        Col++;
        placePiece(board, Row, Col, 'X', move);
    }
    throw runtime_error("");
}

bool processException (runtime_error excpt, bool status) {
    cout << excpt.what() << endl;
    return true;
}

int main() {
    int uRow = 0, uCol = 0;
    int oRow = NUMROWS - 1, oCol = NUMCOLS - 1;
    bool win = true;
    int move = 0;
    _cell board[NUMROWS][NUMCOLS];
    initBoard(board);
    placePiece(board, uRow, uCol, 'U', move);
    placePiece(board, oRow, oCol, 'X', move);
    showBoard(board, move);

while (true) {
    move++;
    try {
        movePlayer(board, uRow, uCol, move);
        moveOpponent(board, oRow, oCol, move);
        showBoard(board, move);
    }
    catch(runtime_error &excpt) {
        processException(excpt, win);
        break;
    }
}
    showBoard(board, move);
    if(win)
        cout << "*** YOU WIN! ***" << endl;
    else
        cout << "*** YOU LOSE! ***" << endl;
string tmp; getline(cin, tmp);
}

I was thinking that, when the move functions throw something, the processException function returns false, so the game ends. But it did not work out
 
  • #4
FallArk said:
Code:
bool processException (runtime_error excpt, bool status) {
    cout << excpt.what() << endl;
    return true;
}
Code:
while (true) {
    try {
        movePlayer(board, uRow, uCol, move);
        moveOpponent(board, oRow, oCol, move);
    }
    catch(runtime_error &excpt) {
        processException(excpt, win);
        break;
    }
}

I was thinking that, when the move functions throw something, the processException function returns false, so the game ends. But it did not work out

The game ends when we break out of the while-loop.
To do so, either the while-condition has to be false, or we have to [m]break[/m] out of it, or we have to [m]throw[/m] an exception (that is not caught within the while-loop).
If a function returns false that has no immediate effect whatsoever on the program flow.
To use such are return value there should be an [m]if[/m] surrounding the function call to processException, but there isn't any. (Thinking)
 
  • #5
I like Serena said:
The game ends when we break out of the while-loop.
To do so, either the while-condition has to be false, or we have to [m]break[/m] out of it, or we have to [m]throw[/m] an exception (that is not caught within the while-loop).
If a function returns false that has no immediate effect whatsoever on the program flow.
To use such are return value there should be an [m]if[/m] surrounding the function call to processException, but there isn't any. (Thinking)

So the processException function should return false then, and it should break out of the while loop, right?
 
  • #6
FallArk said:
So the processException function should return false then, and it should break out of the while loop, right?

What would that look like? (Wondering)
 
  • #7
I like Serena said:
What would that look like? (Wondering)

Code:
bool processException (runtime_error excpt, bool status) {
    cout << excpt.what() << endl;
    status = lose;
    return false;
}
I think something like that:confused:
So, the status is not win anymore and it should break out of the while loop
 
  • #8
FallArk said:
Code:
bool processException (runtime_error excpt, bool status) {
    cout << excpt.what() << endl;
    status = lose;
    return false;
}
I think something like that:confused:
So, the status is not win anymore and it should break out of the while loop

Where does lose come from? How would you know if it's win or lose for that matter?

How would your main loop make use of the returned value? (Wondering)
 
  • #9
I like Serena said:
Where does lose come from? How would you know if it's win or lose for that matter?

How would your main loop make use of the returned value? (Wondering)

wait, that's stupid. never mind. win is a bool type variable.
should I just do
win = false;
then?
 
  • #10
FallArk said:
wait, that's stupid. never mind. win is a bool type variable.
should I just do
win = false;
then?

Well, you don't have access to win here, so you can't assign it any value.
But even if you could, you're assuming the player lost, which would be the case if the exception came from movePlayer().
What if the exception comes from moveOpponent()?
 
  • #11
I like Serena said:
Well, you don't have access to win here, so you can't assign it any value.
But even if you could, you're assuming the player lost, which would be the case if the exception came from movePlayer().
What if the exception comes from moveOpponent()?

But how would I do that? Can I use if statements to achieve this?
 
  • #12
FallArk said:
But how would I do that? Can I use if statements to achieve this?

There's no real need.
Forget about all those booleans and assignments and return values.

You are already printing what happened to the output.
No need to set any boolean value nor to pass it around.
In the main-loop, there is already a [m]break[/m] statement that will break out of the while-loop.

The [m]if (win)[/m] statement that prints who won, should also go.
It's redundant and we are not (properly) tracking the win status.

Note that exceptions are an alternative to if-statements.
If we do the one, we should not try to do the other.
 
  • #13
I like Serena said:
There's no real need.
Forget about all those booleans and assignments and return values.

You are already printing what happened to the output.
No need to set any boolean value nor to pass it around.
In the main-loop, there is already a [m]break[/m] statement that will break out of the while-loop.

The [m]if (win)[/m] statement that prints who won, should also go.
It's redundant and we are not (properly) tracking the win status.

Note that exceptions are an alternative to if-statements.
If we do the one, we should not try to do the other.

I know that once the compiler reaches throw, it will jump to return or break, but as you pointed out earlier, i need to make the function know which move function returned false. Is there ways to manipulate throw then?
 
  • #14
FallArk said:
I know that once the compiler reaches throw, it will jump to return or break,

I'm afraid that's not true.
When the compiler reaches throw, it will jump out of the entire program, causing it to terminate abnormally.
That is, unless there is a [m]catch[/m] somewhere that catches the exception.

but as you pointed out earlier, i need to make the function know which move function returned false. Is there ways to manipulate throw then?

Just listing possibilities:

1. Throw a boolean (win or lose) instead of an exception. That is, use [m]throw false[/m] if we're losing.
2. Use different exceptions, so that win and lose can be distinguished.
3. Set win=false respectively win=true before throwing.
4. Make the win/lose status part of the exception, meaning we'll have to create our own custom exception.
5. Don't worry about which function threw if there is no need to know, which is actually the case.

For the record, runtime_error is really completely wrong in this particular context.
There is no error that occurs at runtime at all.
It's just about the status of winning or losing.
 
  • #15
I like Serena said:
I'm afraid that's not true.
When the compiler reaches throw, it will jump out of the entire program, causing it to terminate abnormally.
That is, unless there is a [m]catch[/m] somewhere that catches the exception.
Just listing possibilities:

1. Throw a boolean (win or lose) instead of an exception. That is, use [m]throw false[/m] if we're losing.
2. Use different exceptions, so that win and lose can be distinguished.
3. Set win=false respectively win=true before throwing.
4. Make the win/lose status part of the exception, meaning we'll have to create our own custom exception.
5. Don't worry about which function threw if there is no need to know, which is actually the case.

For the record, runtime_error is really completely wrong in this particular context.
There is no error that occurs at runtime at all.
It's just about the status of winning or losing.

But I can't modify the main, since it is given and I need to fill out the missing pieces. If the function throws true/false, then the catch part should catch boolean instead of runtime_error right?
 
  • #16
FallArk said:
But I can't modify the main, since it is given and I need to fill out the missing pieces. If the function throws true/false, then the catch part should catch boolean instead of runtime_error right?

Correct.
 
  • #17
I like Serena said:
Correct.

There is nothing I can do to make the function know which move returns false then?
 
  • #18
FallArk said:
There is nothing I can do to make the function know which move returns false then?

Sure you can.
But as I see it, with the current framework, there is not really a good option.
And rather than providing a bad option, can you clarify which parts of the program are supposed to be fixed exactly?
 
  • #19
I like Serena said:
Sure you can.
But as I see it, with the current framework, there is not really a good option.
And rather than providing a bad option, can you clarify which parts of the program are supposed to be fixed exactly?

Sure. The below parts cannot be modified:
Code:
int main() {
    int uRow = 0, uCol = 0;
    int oRow = NUMROWS - 1, oCol = NUMCOLS - 1;
    bool win = true;
    int move = 0;
    _cell board[NUMROWS][NUMCOLS];
    initBoard(board);
    placePiece(board, uRow, uCol, 'U', move);
    placePiece(board, oRow, oCol, 'X', move);
    showBoard(board, move);

while (true) {
    move++;
    try {
        movePlayer(board, uRow, uCol, move);
        moveOpponent(board, oRow, oCol, move);
        showBoard(board, move);
    }
    catch(runtime_error &excpt) {
        processException(excpt, win);
        break;
    }
}
    showBoard(board, move);
    if(win)
        cout << "*** YOU WIN! ***" << endl;
    else
        cout << "*** YOU LOSE! ***" << endl;
string tmp; getline(cin, tmp);
}
I need to write the appropriate functions to make it work.:confused:
 
  • #20
Okay... so here's a bad option that will work:
Code:
void movePlayer(...) {
    throw runtime_error("YOU LOSE");
}

void moveOpponent(...) {
    throw runtime_error("OPPONENT LOSES");
}

void processException(const runtime_error &excpt, bool &win) {
    win = (excpt.what() == string("OPPONENT LOSES"));
}

Effectively we pass the win/lose status inside the exception.
Btw, note that win has to be an output parameter (with an &) of processException().
 
  • #21
I like Serena said:
Okay... so here's a bad option that will work:
Code:
void movePlayer(...) {
   throw runtime_error("YOU LOSE");
}

void moveOpponent(...) {
   throw runtime_error("OPPONENT LOSES");
}

void processException(const runtime_error &excpt, bool &win)
{
   win = (excpt.what() == string("OPPONENT LOSES"));
}

Effectively we pass the win/lose status inside the exception.
Btw, note that win has to be an output parameter (with an &) of processException().

Ah, I see! since excpt.what() (from my textbook only works with runtime_error) outputs what ever is in runtime_error(), and runtime_error is sort of a string, this way the compiler would be able to understand what I want it to do! is that right? :)
 
  • #22
FallArk said:
Ah, I see! since excpt.what() (from my textbook only works with runtime_error) outputs what ever is in runtime_error(), and runtime_error is sort of a string, this way the compiler would be able to understand what I want it to do! is that right? :)

Yes.
For the record excpt.what() works with any exception, including for instance logic_error, invalid_argument, and out_of_range.
 
  • #23
I like Serena said:
Yes.
For the record excpt.what() works with any exception, including for instance logic_error, invalid_argument, and out_of_range.

Thanks man! It really helps! You get a cookie!:p
 

FAQ: Using Exceptions in C++ for a Snake Game for Scientists

What is an exception in C++?

An exception in C++ is a way to handle errors or unexpected events that occur during the execution of a program. It allows the program to transfer control to a specific block of code, known as an exception handler, to handle the error or event.

How do you throw an exception in C++?

To throw an exception in C++, you use the throw keyword followed by the type of exception you want to throw. For example, throw std::runtime_error("Error message"); will throw a runtime_error exception with the specified error message.

How do you handle exceptions in C++?

You handle exceptions in C++ using a try-catch block. The code that may throw an exception is placed in the try block, and the corresponding exception handler is placed in the catch block. If an exception is thrown, the program will jump to the catch block to handle it.

Can you have multiple catch blocks for a single try block in C++?

Yes, you can have multiple catch blocks for a single try block in C++. This allows you to handle different types of exceptions in different ways. You can also have a catch block that catches all types of exceptions by using an ellipsis (...) as the parameter in the catch block.

How do you create custom exception classes in C++?

You can create custom exception classes in C++ by creating a class that inherits from the std::exception class. This allows you to define your own exception types with custom messages and behaviors. You can then throw and catch instances of your custom exception class in your code.

Similar threads

Replies
6
Views
3K
Replies
5
Views
3K
Replies
18
Views
7K
Replies
7
Views
6K
Replies
1
Views
1K
Replies
4
Views
4K
Replies
3
Views
1K
Replies
4
Views
2K
Back
Top