Creating the Concentration Game PAIRS with Bash, Part II

Dave finishes up the PAIRS concentration game, only to realize it’s too
hard to solve!

In my last
article
, I tossed away my PC card and talked about how I was a fan of the
British colonial-era writer Rudyard Kipling. With that in mind, I do
appreciate that you’re still reading my column.

I was discussing the memory game that the British spy plays with the
orphan boy Kim in the book of the same name. The game in question involves
Kim
being shown a tray of stones of various shapes, sizes and colors. Then
it’s hidden, and he has to recite as many patterns as he can recall.

The card game Concentration is clearly inspired by the same pattern
memorization game, and it’s considerably easier to set up: shuffle a deck
of cards, place them face down in a grid, then flip pairs to find matches. In
the beginning, it’s just guessing, of course, but as the game proceeds, it
becomes more about spatial memory than luck. Someone with an eidetic memory
always will win.

Using letters makes things easy, so I suggested a row, column, notational
convention like this:


    1   2   3   4   5   6   7   8   9   10  11  12  13
1: [-] [-] [-] [-] [-] [-] [-] [-] [-] [-] [-] [-] [-]
2: [-] [-] [-] [A] [-] [-] [-] [-] [-] [-] [-] [-] [-]
3: [-] [-] [-] [-] [-] [-] [-] [-] [E] [-] [-] [-] [-]
4: [-] [-] [-] [-] [-] [-] [-] [-] [-] [-] [-] [-] [Z]

You can represent uppercase letters as a shell array like this:


declare -a letters=(A B C D E F G H I J K L M N O P Q R
                    S T U V W X Y Z)

Unfortunately, Bash doesn’t support multidimensional arrays, so you’re
going to have to represent the grid as a one-dimensional array. It’s not
too hard though, because the grid is straightforward. Here’s an index
formula if firstvalue is the first digit and rest is the remainder of the
index value:


index=$(( ( ( $firstvalue - 1 ) * 13 ) + $rest ))

The letter “E” in the above grid, at 3,9, would show up in the array
as ((3-1)*13)+9 or slot 35.

Shuffle Those Values

The script from my last
article
already initializes everything in sequential order
and defaults to 2 * 13 slots (for simplicity in debugging). The work of the
script is really in the shuffle, but it turns out that there’s a pretty
elegant little shuffle algorithm (shown in a kind of sloppy C for illustrative
purposes) floating around the internet that can be tapped for this task:


shuffle {
   for (i = n-1; i > 0; i-) {
     int j = rand() % (i+1);
     swap( array[i], array[j]);
   }
}

Translating this into a shell script and using better variable names,
here’s what I created:

Source: Linux Journal