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

  • Thread starter Thread starter FallArk
  • Start date Start date
AI Thread Summary
The discussion revolves around using exceptions in a C++ snake game to handle game state changes. The type `runtime_error` is identified as an exception for handling unexpected situations, such as moving out of bounds or colliding with an opponent. The `processException` function is debated regarding its return type and how it should influence game flow, with suggestions to simplify the logic by removing unnecessary boolean checks. It is emphasized that exceptions should be used to manage game states without complicating the code with additional variables. The conversation concludes that the current use of `runtime_error` may not be appropriate for tracking win/lose conditions, suggesting alternative approaches for better clarity.
FallArk
Messages
127
Reaction score
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
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?
 
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
 
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)
 
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?
 
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)
 
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
 
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)
 
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
 

Similar threads

Replies
6
Views
3K
Replies
18
Views
7K
Replies
7
Views
6K
Replies
3
Views
4K
Replies
3
Views
2K
Replies
16
Views
4K
Back
Top