An ASCII puzzle for an escape room challenge
showDigit
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
).
Setup
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 pinMode
s 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
.
Loop
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.
« Previous 1 2 3 4 Next »
Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
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.
News
-
Gnome OS Transitioning Toward a General-Purpose Distro
If you're looking for the perfectly vanilla take on the Gnome desktop, Gnome OS might be for you.
-
Fedora 41 Released with New Features
If you're a Fedora fan or just looking for a Linux distribution to help you migrate from Windows, Fedora 41 might be just the ticket.
-
AlmaLinux OS Kitten 10 Gives Power Users a Sneak Preview
If you're looking to kick the tires of AlmaLinux's upstream version, the developers have a purrfect solution.
-
Gnome 47.1 Released with a Few Fixes
The latest release of the Gnome desktop is all about fixing a few nagging issues and not about bringing new features into the mix.
-
System76 Unveils an Ampere-Powered Thelio Desktop
If you're looking for a new desktop system for developing autonomous driving and software-defined vehicle solutions. System76 has you covered.
-
VirtualBox 7.1.4 Includes Initial Support for Linux kernel 6.12
The latest version of VirtualBox has arrived and it not only adds initial support for kernel 6.12 but another feature that will make using the virtual machine tool much easier.
-
New Slimbook EVO with Raw AMD Ryzen Power
If you're looking for serious power in a 14" ultrabook that is powered by Linux, Slimbook has just the thing for you.
-
The Gnome Foundation Struggling to Stay Afloat
The foundation behind the Gnome desktop environment is having to go through some serious belt-tightening due to continued financial problems.
-
Thousands of Linux Servers Infected with Stealth Malware Since 2021
Perfctl is capable of remaining undetected, which makes it dangerous and hard to mitigate.
-
Halcyon Creates Anti-Ransomware Protection for Linux
As more Linux systems are targeted by ransomware, Halcyon is stepping up its protection.