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: