"Guess a random letter" game with command line interface The code below if launched on the command line is a simple guessing game.
A random character 'a', 'b' or 'c' is chosen, and the user is prompted until they guess correctly.
It's arguable that invalid input and a win is not necessarily exceptional.  Should exceptions be used in this manner?
I am not sure what's a sensible way to check for a winning situation and to terminate the game.
&lt;?php

class ABorCException extends Exception {
    const WIN     = 'Win';
    const INVALID = 'Invalid';
}

class ABorC
{
    const CHOICES = ['a', 'b', 'c'];
    public $answer;
    public $turns;

    public function __construct($answer = null)
    {
        $this-&gt;answer = $answer ?? self::CHOICES[array_rand(self::CHOICES)];
    }

    public function turn($guess)
    {
        if(!in_array($guess, self::CHOICES))
            throw new ABorCException(ABorCException::INVALID);
        $this-&gt;turns[] = $guess;
        if($guess === $this-&gt;answer)
            throw new ABorCException(ABorCException::WIN);
    }
}

$game = new ABorC;

while (true) {
    try {
        $input = readline(&quot;Enter your guess a, b or c?\n&quot;);
        $game-&gt;turn($input);
        echo &quot;Wrong!\n&quot;, &quot;Guess again.\n&quot;;
    } catch (ABorCException $e) {
        if($e-&gt;getMessage()===ABorCException::INVALID) {
            echo &quot;Invalid input.\n&quot;;
        }
        if($e-&gt;getMessage()===ABorCException::WIN) {
            echo &quot;Correct!\n&quot;, &quot;You won in &quot;, count($game-&gt;turns), &quot; valid attempts.\n&quot;;
            exit;
        }
    }
}

Sample game:
$ php aborc.php 
Enter your guess a, b or c?a
Wrong!
Guess again.
Enter your guess a, b or c?z
Invalid input.
Enter your guess a, b or c?b
Correct!
You won in 2 valid attempts.
You are using exceptions for flow control, and that is considered an anti-pattern.
Exceptions are meant for unhandlable conditions that would otherwise corrupt your application. Winning the game should not corrupt the application and cause undefined behavior. If it does, you are likely building a stock trading application (I'm only kidding ;-) of course).
Invalid input could certainly corrupt things or cause undefined behavior, but in this case your program should expect invalid input and handle it gracefully. Always expect the unexpected with user input.
When reading input, check that it is correct. Loop until you get correct input.
The $game-turn() method could return a &quot;result&quot; object, which reports back whether the game has been won, and if so who the winner is (and possibly a score). Again, handle this with a simple if statement:
$result = $game-&gt;turn($input);

if ($result-&gt;isWinningTurn()) {
    echo &quot;Winner! {$result-&gt;winner}&quot;;
}
else {
    echo &quot;next move&quot;;
}

If $game-&gt;turn() throws an exception, I would expect it to be an unhandled condition or something unrecoverable like an out of memory exception. As a programmer, I would be VERY surprised if winning the game crashed the program.
Now, the turn() method should throw an exception if you give it bad input. That makes sense. But you need to check for valid input before calling $game-&gt;turn($input). You likely need an isValidInput method on the game object in order to check this.
$game-turn(&quot;d&quot;); // I expect this to throw

if ($game-&gt;isValidInput($input)) {
    $result = $game-&gt;turn($input)); // I expect this to always succeed

    if ($result.isWinningTurn()) {
        ...
    }
    else {
        ...
    }
}
else {
    echo &quot;Bad input, try again.&quot;
}