An ASCII puzzle for an escape room challenge


The showDigit function (lines 82-126) is responsible for drawing the provided character on the display. I start by defining int iPattern and then use switch to find the character provided in cLetter.

On each line of the switch function, case says: If I match '<this>' then do whatever is after the colon (:). If it does not match, it moves on to the next case statement until it finds a match or drops off the end without a match. Once a match is found, iPattern is set to a number represented in binary with the 0b at the front (i.e., much like a preceding 0x denotes hex notation).

The binary number specifies which segments of the seven-segment display should be illuminated to display this character. Once the pattern is defined, the break exits the switch block. Without break, C would keep evaluating the rest of the case statements and possibly find another match. Here, the function exits as soon as a match is found.

Finally, line 125 calls lc.setRow, which is the LED controller's function to turn on a set of LEDs. setRow takes three arguments: the chip number (always 0 in this case), the position in which to place this character (iPosition), and which segments to illuminate (iPattern).


In the Arduino world, the special setup function (lines 128-164) is called once when the Arduino powers on, allowing you to initialize variables, turn on hardware, and make sure everything is properly configured before your main program runs. To begin, the code initializes the serial monitor in the Arduino IDE with Serial.begin (9600) for debugging messages. The baud rate (speed) of the serial connection is 9600, but this number doesn't really matter, as long as it matches what is selected in the serial monitor.

The pinMode of analog pins A0 through A7 are set to INPUT_PULLUP. As the value suggests, this makes the pin an input and also enables its internal pull-up resistor. Even though I'm using the Arduino analog pins, I'm just using them as digital inputs in this case. Pin 10 is set in the same way and will be the "check" input to determine whether the current wiring is correct.

The next series of pinModes sets a number of GPIO pins to OUTPUT. Pins 14, 15, and 16 are the data, clock, and chip select lines of the LED driver, and pins 2 through 9 are the top row of electrical connections on the puzzle. The digitalWrite sets pin 16 to HIGH, which allows the LED driver to listen to incoming data. Because the project only has one driver, it can be left on indefinitely; in this case, it could even be connected directly to V+, but this arrangement was more convenient.

The randomSeed function initializes the Arduino's random number engine. An analogRead of an unused digital input essentially picks up static, causing the return of a random number, which is used as a seed.

The rotateOutputs was defined earlier, so when the puzzle starts, the lower row of electrical connections is ready to go.

The last couple of lines set up the LED driver. An lc.shutdown set to false means the LEDs should not be shutdown. The lc.setIntensity sets the brightness of the display. The range is 0 to 16, so a value of 8 sets brightness at 50 percent. Finally, lc.clearDisplay erases anything that was previously on the display. The first two functions are called with a   as the first argument. The 7219 driver chip can be daisy-chained, so you have to specify the chip in the chain to which you are talking. Because this setup only has one chip, the value will always be  .


After the setup function finishes, the Arduino loop function (lines 166-210) loops continuously until power is removed. In this function resides the main logic of the program.

To begin, I check to see whether cLastLetter does not equal the current puzzle character, displayTarget (i.e., show the value the player is trying to achieve), and update cLastLetter to the current puzzle character.

Next, I check to see whether pin 10 is LOW. If so, the player wants to know whether their current wiring is correct. To check, I initialize iPort, then digitalRead each of the input pins, and add the appropriate power of 2 if the pin is LOW (lines 178-185). For a pin to be LOW, the player had to connect a clip lead between this connection and one of the active connections on the lower row indicated by LEDs.

Once I've calculated iPort, I check to see if it equals cLastLetter, which means the players have found the correct combination. In that case, I increment iLetterIndex, debug print "CORRECT", display YES on the LEDs, and then wait for 1 second (line 192).

The for loops over the characters discovered so far. I call showDigit and provide the position as 7 - i, which makes sure the drawing starts from the left side of the display. The second argument, puzzle [ i ], is the character at that position. As each character is discovered it is added to the display.

Finally, rotateOutputs ensures a different set of connections will be active for the next round. On the next iteration of the loop, iLetterIndex has been updated, so a new number will be displayed for the players to find.

If the players did not guess correctly, the else block (line 200) runs instead, debug prints INCORRECT, displays NO on the LEDs, waits for 1 second, redisplays the target value, and finally picks a new set of active connections with rotateOutputs.

Line 208 loops infinitely while a digitalRead of pin 10 returns LOW and delays a tenth of a second before checking again. Once pin 10 returns to HIGH (the clip is removed), the loop continues.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Linux Magazine

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

  • New Tech Retrofit

    An electronic project at a local science center was showing its age, calling for a refresh: in this case, rebuilding it almost from scratch with an Arduino instead of relays.

  • Perl: Arduino Project

    With a few lines of self-written firmware and a simple Perl script, Perlmeister Mike Schilli trains one of his Linux computers with a plugged in Arduino board to switch electrical equipment on and off using a relay. Enchanting.

  • Serial Communications

    We explore serial communications, from the electrical specs to protocols and libraries, with an example of serial communication with an Arduino.

  • Sudoku

    Some regard Sudoku as the 21st

    century Rubik’s Cube. We’ll

    show you how to get started

    with Sudoku in Linux.

  • Knight's Tour

    If you're looking for a head start on solving the classic Knight's Tour chess challenge, try this homegrown Python script.

comments powered by Disqus
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters

Support Our Work

Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.

Learn More