Advertisement
neil_pearce

Guess a random number

Mar 20th, 2023
1,022
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 3.48 KB | Source Code | 0 0
  1. <?php
  2.  
  3. /*
  4.  * This code is just one of many possible solutions to the Weekly Challenge posed by Alex in his email
  5.  * dated 13/Mar/2023. The Challenge was to create an interactive script that generates a random number
  6.  * and asks the user to guess that number.
  7.  *
  8.  * If you are interested in improving your PHP skills, sign up for Alex's newsletter at
  9.  * https://alexwebdevelop.com and join Alex PHP café at https://www.facebook.com/groups/289777711557686
  10.  */
  11.  
  12. declare(strict_types=1);
  13.  
  14. /*
  15.  * Check environment
  16.  */
  17. PHP_SAPI === 'cli'
  18. or throw new RuntimeException('Must be run from the command line');
  19.  
  20. extension_loaded('readline')
  21. or throw new RuntimeException("PHP 'readline' extension not loaded");
  22.  
  23.  
  24. /*
  25.  * Validate the command line arguments
  26.  */
  27. if ($argc == 3) {
  28.     $max_random = validate_int($argv[1], 2, 65536);
  29.     $max_attempts = validate_int($argv[2], 1, 32);
  30. }
  31.  
  32. if (
  33.     $argc != 3
  34.     || $max_random === false
  35.     || $max_attempts === false
  36. ) {
  37.     /* arguments are not defined or invalid - display usage information */
  38.     $script_name = basename(__FILE__);
  39.     echo <<<USAGE
  40.  
  41.           Usage: $script_name max_random max_attempts
  42.  
  43.           Generates a random number and asks the user to guess that number.
  44.  
  45.           max_random:
  46.             the maximum random value that can be generated, an integer between 2 and 65536
  47.           max_attempts:
  48.             the maximum number of attempts the user can make, an integer between 1 and 32
  49.  
  50.         USAGE;
  51.  
  52.     exit(254);  // indicate usage displayed
  53. }
  54.  
  55.  
  56. $eot = 1;  // default end of task code to indicate failure
  57.  
  58.  
  59. /*
  60.  * Generate a random number
  61.  */
  62. $random = random_int(1, $max_random);
  63.  
  64. print_line(PHP_EOL . "I've thought of a number between %d and %d" . PHP_EOL, 1, $max_random);
  65.  
  66.  
  67. /*
  68.  * Loop prompting the user to enter a guess
  69.  */
  70. $attempts = 0;
  71. while (true) {
  72.     if (
  73.         ($input = readline('Enter guess: ')) === false
  74.         || trim($input) === ''
  75.     ) {
  76.         break;  // no input - terminate loop
  77.     }
  78.  
  79.     /* validate user input */
  80.     if (($guess = validate_int($input, 1, $max_random)) !== false) {
  81.         switch ($guess <=> $random) {  // use the spaceship operator to compare
  82.             case 0:
  83.                 print_line('Congratulations!');
  84.                 $eot = 0;  // set end of task code to indicate success
  85.                 break 2;  // exit switch and while
  86.  
  87.             case -1:
  88.                 $msg = 'Too low';
  89.                 break;
  90.  
  91.             case 1:
  92.                 $msg = 'Too high';
  93.                 break;
  94.         }
  95.  
  96.         /* only count valid attempts */
  97.         if (++$attempts >= $max_attempts) {
  98.             print_line('Too many attempts, the number was %d.', $random);
  99.             break;
  100.         }
  101.     } else {
  102.         $msg = sprintf('Enter an integer between 1 and %d', $max_random);
  103.     }
  104.  
  105.     print_line('%s, try again.', $msg);
  106. }
  107.  
  108. exit($eot);  // indicate whether successful or not
  109.  
  110.  
  111. /*
  112.  * Output a formatted string appending the correct end of line
  113.  *
  114.  * Example of a variable-length argument list using the variadic ('splat') operator
  115.  */
  116. function print_line(string $format, mixed ...$values): int
  117. {
  118.     return printf($format . PHP_EOL, ...$values);
  119. }
  120.  
  121.  
  122. /*
  123.  * Validate a string as an integer within a range
  124.  */
  125. function validate_int(string $value, int $min, int $max): int|false
  126. {
  127.     return filter_var($value, FILTER_VALIDATE_INT,
  128.                       ['options' => ['min_range' => $min, 'max_range' => $max]]);
  129. }
  130.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement