Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to stop input in Perl?

Tags:

input

perl

I'm making a reflex game. Here's the output -

__________________________________________________________________________
Reflex game initiated. Press ENTER to begin the game, and then press ENTER 
after the asterisks are printed to measure your reflexes!.


*************************

Your result: 0.285606 seconds.
logout

[Process completed]
__________________________________________________________________________

There's one small problem though - There's 0-10 seconds (based on a random variable) after you press enter to start the game and before the stars are printed. During that time, if the player presses ENTER, it's logged as their reflex time. So I need a way to stop my code from reading their ENTER button before the stars are printed. The code -

#!/usr/bin/perl

use Time::HiRes qw(sleep);
use Time::HiRes qw(gettimeofday);

#random delay variable
$random_number = rand();

print "Reflex game initiated. Press ENTER to begin the game, and then press ENTER after         the asterisks are printed to measure your reflexes!.\n";

#begin button
$begin = <>;

#waits x milliseconds
sleep(10*$random_number);

#pre-game
$start = [ Time::HiRes::gettimeofday() ];

print "\n****************************\n";

#user presses enter
$stop = <>;

#post game
$elapsed = Time::HiRes::tv_interval($start);

#delay time print
print "Your result: ".$elapsed." seconds.\n";
like image 500
user1472747 Avatar asked Jun 21 '12 16:06

user1472747


1 Answers

Repeating from the original answer by CanSpice:

Looks like Term::ReadKey may help.

#!perl

use strict;
use warnings;
use 5.010;

use Term::ReadKey;

say "I'm starting to sleep...";
ReadMode 2;
sleep(10);
ReadMode 3;
my $key;
while( defined( $key = ReadKey(-1) ) ) {}
ReadMode 0;
say "Enter something:";
chomp( my $input = <STDIN> );
say "You entered '$input'";

Here's what happens:

  • ReadMode 2 means "put the input mode into regular mode but turn off echo". This means that any keyboard banging that the user does while you're in your computationally-expensive code won't get echoed to the screen. It still gets entered into STDIN's buffer though, so...
  • ReadMode 3 turns STDIN into cbreak mode, meaning STDIN kind of gets flushed after every keypress. That's why...
  • while(defined($key = ReadKey(-1))) {} happens. This is flushing out the characters that the user entered during the computationally-expensive code. Then...
  • ReadMode 0 resets STDIN, and you can read from STDIN as if the user hadn't banged on the keyboard.

When I run this code and bang on the keyboard during the sleep(10), then enter some other text after the prompt, it only prints out the text I typed after the prompt appeared.

Strictly speaking the ReadMode 2 isn't needed, but I put it there so the screen doesn't get cluttered up with text when the user bangs on the keyboard.

like image 102
ZnArK Avatar answered Oct 13 '22 11:10

ZnArK