Building game show buzzers with a Raspberry Pi

The Main Loop – Lines 70 to 91

Once everything is loaded and initialized, the main loop runs until the program terminates. To begin, set up the loop:

running = True
while running == True:

The running variable is what the while statement will check. Any code or function that needs to end the program sets running = False; then, the loop terminates on the next iteration. Any cleanup code is located below the loop, and the program ends. In the code in line 72,

choice = terminal.getch ( 12 , 5 )

terminal.getch gets one character from the keyboard. The two parameters are the screen coordinates where the character is printed (if echo is turned on). The coordinates are relative to whichever window you call getch on, in this case, you only have one window.

Because I set terminal.nodelay ( 1 ) when I initialized curses (line 50), terminal.getch will not block (see "About Blocking Inputs" for more information). If no key press is waiting, then terminal.getch returns -1. An if statement checks for this:

if choice == -1: continue

If there's nothing to do (i.e., no key press), continue sends the loop back to the top. Once a key press has been received, the program proceeds to the rest of the loop:

if choice == ord ( "1" ):
    showWinner ( 1 )

The remainder of the main loop is a string of if/elif statements that check the key press that was received. If it was a number, it calls showWinner, which manually shows a winner on the contestant's LCD. This demonstrates what the board looks like when someone buzzes in and provides a manual backup in case of hardware problems.

About Blocking Inputs

If an input blocks, then it will not return until it receives a character. This is often undesirable because your program will be unresponsive. Waiting for a keyboard input might not be so bad, but the same principal applies to network and serial communication. In that case, your program will appear to freeze until data arrives.

To solve this problem, programmers use non-blocking input and integrate input processing into the main loop of the program. Handling this is just one of the tasks, along with updating the screen, checking external inputs, and so on. When a key press (or other communication data) is received, it's added to a buffer, and the main loop continues to run. Eventually, an "I'm done" character (e.g., carriage return) or the appropriate number of bytes will arrive from your data source. Once this happens, your program can process the entire buffer at once, without locking up the user interface.

If the user presses b (line 85) then showWinner is called again. Instead of passing a specific number, it also calls the getBuzzers function, which watches for changes in the GPIO (the contestant's buzzers). getBuzzers won't return (it blocks) until one of the contestant's buttons is pressed. When a contestant buzzes in, her number is passed to showWinner, which displays the winner on the contestant's LCD.

Pressing r (line 88) resets the system. This step clears the screen on the contestant's LCD, but b must be pressed before the buzzers will respond again. Pressing x (line 90) sets running to False. This represents the last elif in the chain, so when the loop recycles it will check and find running no longer to be true and will exit. Cleanup code located below the loop runs, and then the program ends normally.

Cleanup – Line 93

It's very important to call curses.endwin() when you're done with curses. If you don't (or if the program crashes), your terminal may be left in an unusual state – echo disabled, strange colors, or worse. With the use of curses.endwin(), you restore your terminal to whatever state it was in when you launched the program. If your terminal still isn't right, you can type reset at a shell prompt (even if you can't see characters appearing in the terminal) and press Enter. After a few seconds, you should get a new prompt, and everything should be back to normal.

On the Pygame side of the house, there's not much to do. Pygame cleans up after itself when it sees that your program is ending. It will close the graphics window (if there is one) and uninitialize all of its modules.

Pygame does provide pygame.quit(), but its use is recommended only when you've finished with your graphics needs but want the remainder of your program to continue running. This might be the case when using Pygame to plot graphs or show pictures but the program is otherwise widget or console based.

Buy this article as PDF

Express-Checkout as PDF

Pages: 8

Price $2.95
(incl. VAT)

Buy Raspberry Pi Geek

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

  • Creating a multiplayer quick-reaction game

    The quick-reaction game provides an introduction to building simple circuits with the Raspberry Pi and controlling those circuits with ScratchGPIO, an advanced version of Scratch.

  • A Python interface to a large-format pen plotter

    Getting a large-format plotter operational presented a personal challenge. A Raspberry Pi with a USB-to-serial dongle was the easiest way to start plotting on my home network.

  • Pygame modules for interactive programs

    Pygame modules are particularly suited to programming highly interactive software. We look at the modules dedicated to events, sound, and input by keyboard, mouse, and game controller.

  • Graphical displays with Python and Pygame

    As its name implies, Pygame is a set of Python modules designed to write games. However, many Pygame modules are useful for any number of projects. We introduce you to a few Pygame modules that you can use to create custom graphical displays for your project.

  • Fast clocks, model railroads, LED displays, and more

    Some model train enthusiasts like to run their trains like a real railroad with a dispatcher controlling movements, issuing train orders, and making sure the train stays on schedule. But, time runs differently for these trains, thanks to fast clocks.