Magic Square
Summary
Implement a "Magic Square", where a person selects a particular letter on the screen, and the computer tells them what they chose.
Topics
Requires beginning programming topics: variables, assignment, loops, input and output. Also requires a random number generator and character functions.
Standards
From the CSTA standards:
1B-AP-09 Create programs that use variables to store and modify data. (P5.2)
1B-AP-10 Create programs that include sequences, events, loops, and conditionals. (P5.2)
Audience
Introductory programming students in 9-12
Difficulty
Easy to medium level of difficulty, depending on how much scaffolding is provided.
Strengths
The "mind-reader" aspect inspires students to get it to work so they can show it to family and friends. Basic programming constructs (variables, assignment, loops, decision statements) must all be used to get it to work properly.
Weaknesses
It does require the use of a random number generator, which might be unfamiliar to students
Dependencies
Requires beginning programming topics: variables, assignment, loops, input and output. Using a random number generator and character functions are required, though they can be provided as easily reusable sample code. Functions are not required but are helpful.
Variants
The program can prompt for what "level" of analysis to do, and sometimes give randomly wrong answers at "lower" levels of analysis, to strengthen the illusion that it is based on pattern matching.
A GUI version similarly can use some sort of timing on button presses to make it seem like the user interaction makes a difference in the computer's guess.
See the presentation slides.
Video of Program
See the following YouTube video showing how the program works: https://youtu.be/VsabYB3aJbM
Play Online
Run a version of this program built in Code.org's App Lab at bit.ly/uicmindreader, also shown below:
Sample Runs of the Program
Playing the game looks like the following, where user input of the level to use is shown in bold. (For the non-extra credit version this input should always be 0.)
Program #3: Mind Reader
BTT CS 111: Program Design I in Python
Our subconscious get expressed in different ways, including
through choices we make, how we type, and how quickly we type.
Python libraries include Artificial Intelligence (AI) neural
network tools that can recognize patterns.
For this program choose the algorithm analysis level. Higher
levels take longer, but are more accurate. Level 4 works most
of the time.
Enter level > 1: 0
99:x 98:W 97:X 96:q 95:O 94:H 93:B 92:f 91:l 90:h
89:r 88:s 87:A 86:g 85:i 84:y 83:F 82:c 81:t 80:T
79:o 78:e 77:a 76:y 75:F 74:f 73:K 72:t 71:G 70:V
69:g 68:w 67:m 66:a 65:n 64:e 63:t 62:c 61:J 60:T
59:A 58:V 57:k 56:j 55:j 54:t 53:w 52:f 51:P 50:f
49:I 48:A 47:x 46:m 45:t 44:R 43:n 42:M 41:a 40:B
39:F 38:g 37:y 36:t 35:o 34:q 33:q 32:y 31:D 30:X
29:L 28:j 27:t 26:N 25:c 24:K 23:t 22:e 21:I 20:W
19:c 18:t 17:v 16:j 15:C 14:E 13:w 12:p 11:x 10:C
9:t 8:T 7:m 6:H 5:t 4:i 3:u 2:e 1:u 0:t
1. Choose any two-digit number in the table above (e.g. 73).
2. Subtract its two digits from itself (e.g. 73 - 7 - 3 = 63)
3. Find this new number (e.g. 63) and remember the letter next to it.
4. Press 'a' to analyze responses: a
Your letter is: t
Playing the game again might look like:
Program #3: Mind Reader
BTT CS 111: Program Design I in Python
Our subconscious get expressed in different ways, including
through choices we make, how we type, and how quickly we type.
Python libraries include Artificial Intelligence (AI) neural
network tools that can recognize patterns.
For this program choose the algorithm analysis level. Higher
levels take longer, but are more accurate. Level 4 works most
of the time.
Enter level > 1: 0
99:D 98:m 97:e 96:c 95:M 94:J 93:y 92:H 91:r 90:I
89:F 88:d 87:G 86:A 85:U 84:I 83:i 82:f 81:h 80:J
79:X 78:l 77:t 76:v 75:q 74:f 73:p 72:h 71:C 70:R
69:j 68:J 67:W 66:J 65:Y 64:g 63:h 62:N 61:j 60:o
59:h 58:I 57:b 56:b 55:U 54:h 53:I 52:R 51:P 50:k
49:v 48:c 47:G 46:u 45:h 44:i 43:l 42:X 41:K 40:r
39:k 38:B 37:h 36:h 35:Y 34:T 33:h 32:K 31:f 30:o
29:b 28:w 27:h 26:J 25:V 24:k 23:k 22:K 21:E 20:u
19:T 18:h 17:c 16:t 15:o 14:e 13:M 12:f 11:s 10:l
9:h 8:o 7:L 6:L 5:J 4:d 3:g 2:g 1:b 0:h
1. Choose any two-digit number in the table above (e.g. 73).
2. Subtract its two digits from itself (e.g. 73 - 7 - 3 = 63)
3. Find this new number (e.g. 63) and remember the letter next to it.
4. Press 'a' to analyze responses: a
Your letter is: h
What You Need to Know
The function used to get a random letter is shown below. This is used once at the beginning of the program to select the secret_character, and is also called once for every table location that is below loop counter value of 90 that is not divisible by 9, to get a random character to be displayed.
def get_Random_Letter():
# Get a random number, which will be the offset from 'a' or 'A'
letter_offset = random.randrange(0,25)
# Randomly choose between upper and lower case
if bool(random.getrandbits(1)):
# Make it upper case
random_char = chr(65 + letter_offset) #65 is the code for 'A'
else:
# Make it lower case
random_char = chr(97 + letter_offset) # 97 is the code for 'a'
return random_char
The secret to the program is that the program itself chooses a random "magic character" ahead of time, which in the case of the most recent table above is the character 'h'. For any number, if you subtract its individual digits from itself, then you end up with a number that is evenly divisible by 9. When the table is printed, in all the numbered locations below 90 where 9 is a factor (9, 18, 27, 36, 45, 54, 63,72, 81) the special character 'h' that was chosen ahead of time is displayed there. For all the rest of the characters a random character is chosen.
Suggested Steps
Display the header lines at the top of the program
Use a while loop to count from 99 down to 0. Display just those numbers, with a colon ':' and then a space after each one.
Add code using the mod (%) function so that you print a new line character after each set of 10 output values. This will result in a row of numbers from 99 down to 90, a second row from 89 down to 80, and so on.
After each number now also get a random letter by calling get_Random_Letter() (see below) and print that letter after the colon.
Declare and use a variable for the secret letter. To do this, at the beginning of your program call function get_Random_Letter()and store the result into the secret letter variable (e.g. secret_char = get_Random_Letter() ). So that your output matches the expected output in the test cases, you should call the random number generator the minimum number of times. When your program starts, as explained above you should call function get_Random_Letter() once to find and store the secret letter, as explained above. Then for each table entry that is not less than 90 and evenly divisible by 9) you will again call get_Random_Letter(). You should not call the random number generator besides this, so that your output matches the expected output.
Add code at the spot in your program where you display a random character for each table entry. If the loop counter is less than 90 and the counter value is evenly divisible by 9, then display the already-chosen secret_char and not a random character.
Add the text and prompt at the bottom of the program.
Extra Credit
An extra credit version includes extra flair in the computer making the guess where there is extra output because the program is "Building a Neural Network" to make its forecast. This can be found at:
Running the extra credit version looks like:
Program #3: Mind Reader
BTT CS 111: Program Design I in Python
Our subconscious get expressed in different ways, including
through choices we make, how we type, and how quickly we type.
Python libraries include Artificial Intelligence (AI) neural
network tools that can recognize patterns.
For this program choose the algorithm analysis level. Higher
levels take longer, but are more accurate. Level 4 works most
of the time.
Enter level > 1: 4
99:D 98:m 97:e 96:c 95:M 94:J 93:y 92:H 91:r 90:I
89:F 88:d 87:G 86:A 85:U 84:I 83:i 82:f 81:h 80:J
79:X 78:l 77:t 76:v 75:q 74:f 73:p 72:h 71:C 70:R
69:j 68:J 67:W 66:J 65:Y 64:g 63:h 62:N 61:j 60:o
59:h 58:I 57:b 56:b 55:U 54:h 53:I 52:R 51:P 50:k
49:v 48:c 47:G 46:u 45:h 44:i 43:l 42:X 41:K 40:r
39:k 38:B 37:h 36:h 35:Y 34:T 33:h 32:K 31:f 30:o
29:b 28:w 27:h 26:J 25:V 24:k 23:k 22:K 21:E 20:u
19:T 18:h 17:c 16:t 15:o 14:e 13:M 12:f 11:s 10:l
9:h 8:o 7:L 6:L 5:J 4:d 3:g 2:g 1:b 0:h
1. Choose any two-digit number in the table above (e.g. 73).
2. Subtract its two digits from itself (e.g. 73 - 7 - 3 = 63)
3. Find this new number (e.g. 63) and remember the letter next to it.
4. Press 'a' to analyze responses: a
Building neural network
.
.
.
.
Your letter is: h
Java Version
/** ---------------------------------------------
* This program implements a "Magic Square".
* The user chooses a two-digit number (i.e. 45) then
* subtracts the two digits in that number (i.e. 45 - 4 - 5 = 36)
* The user then remembers the letter next to that number.
*
* The computer then predicts what that letter is.
*
* Class: CS 102, Spring 2007
* Lab: Englebert Humberdink, Mon. 5:00 AM
* System: BlueJ 2.0.5, jsdk 1.5, Windows XP
*
* @author Dale Reed
* @version Jan 19, 2007
* ----------------------------------------------
*/
import java.util.Scanner; // used for console input
import java.util.Random; // used to get random numbers
// Declare the class
public class MagicSquare3
{
// Fields that can be accessed anywhere in the class go here
Scanner keyboard = new Scanner( System.in); // used to read user input
Random randomNumbers = new Random(); // used to generate random numbers
//----------------------------------------------------------------------------------------
// main() - startup main loop. It is necessary to create an instance of this class
// and then call a method from that instance, otherwise there are all kinds
// of error messages having to do with non-static objects (e.g. keyboard)
// being called from a static context (e.g. main). By creating the instance
// and *then* using keyboard, it is not longer being called from a static
// context. Don't worry about understanding all this right now.
//
public static void main(String[] args)
{
// create an instance of this class
MagicSquare3 theMagicSquare3Instance = new MagicSquare3();
// call a non-static method to do everything else
theMagicSquare3Instance.mainLoop();
}
//----------------------------------------------------------------------------------------
// mainLoop() - display identifying information and run main loop
//
void mainLoop()
{
// Display identifying information
System.out.println( "Author: Dale Reed \n" +
"Program 1: Magic Square \n" +
"TA: Billie Joe Armstrong, T 6:00 AM \n" +
"Jan 18, 2007\n");
// declare variables
String menuResponse = ""; // stores keypresses of user input
int randomNumber; // stores random numbers
char specialSymbol; // The special character for multiples of 9
// Outer loop allows repeating the program
while( ! menuResponse.equals("x")) {
// get a random number from 0..25
randomNumber = Math.abs( randomNumbers.nextInt()%26);
// determine the special character for multiples of 9
// If the random number is even, we'll create an upper case character. If the random number
// is odd, we'll create a lower-case character.
if( randomNumber%2 == 0) {
// random number is even, since the remainder after dividing by 2 == 0
specialSymbol = (char) ('A' + randomNumber); // create new upper-case letter
}
else {
specialSymbol = (char) ('a' + randomNumber); // create new lower-case letter
}
// set the counter and run the loop that displays the numbers
int counter = 99;
char characterToPrint = ' '; // stores the character to print on each iteration
System.out.println(); // leave a blank line at top of table
while( counter >= 0) {
// Find a random number from 0..25
randomNumber = Math.abs( randomNumbers.nextInt()%26);
// find out which character we will be printing, and store it in characterToPrint
// if the counter is a multiple of 9, store the special character to be displayed
if( ((counter%9) == 0) && (counter!=90)) {
characterToPrint = specialSymbol;
}
else {
// counter is not a multiple of 9
// If the random number is even, we'll create an upper case character. If the random number
// is odd, we'll create a lower-case character.
if( randomNumber%2 == 0) {
// random number is even, since the remainder after dividing by 2 == 0
characterToPrint = (char)('A'+randomNumber); // create new upper-case letter
}
else {
characterToPrint = (char)('a'+randomNumber); // create new lower-case letter
}
}
// now print the character, whatever it is
System.out.printf( "%4d:%c ", counter, characterToPrint);
// print an extra space to make things line up for values < 10
// go to a new line if we are at an even multiple of 10
if( counter%10 == 0) {
System.out.println();
}
// decrement the counter
counter--;
}//end while ( counter...
// display instructions
System.out.println();
System.out.println( "1. Choose any two-digit number in the table above (e.g. 73). ");
System.out.println( "2. Subtract its two digits from itself (e.g. 73 - 7 - 3 = 63) ");
System.out.println( "3. Find this new number (e.g. 63) and remember the letter next to it. ");
System.out.print( "4. Now press the return key and I'll read your mind...");
menuResponse = keyboard.nextLine(); // read user input
// display "mind-reading" answer
System.out.println();
System.out.println( "I sense you are thinking of: " + specialSymbol);
// prompt for repeat or exit
System.out.println();
System.out.print( "Enter 'r' to repeat or 'x' to exit: ");
menuResponse = keyboard.nextLine(); // read user input
if( menuResponse.equals("x")) {
break; // exit the loop
}
}//end while( ! menuResponse...
System.out.println(" Thanks for playing, goodbye. \n\n");
}//end method mainLoop()
}//end class MagicSquare
C++ Version
/* ------------------------------------------------
* guessit.cc
* Program displays a grid of numbered symbols, then asks
* user to select one position, remembering the number.
* The digits of that number are subtracted from the original
* number, giving a new number. The user is asked to
* remember the symbol at that new number position.
* The computer then "guesses" what that symbol is and
* displays it.
*
* Class: Program #1 for CS 141, Fall 2017.
* Lab: Wed 5am
* System: Windows 10
* Author: Dale Reed
*
Running the program looks like:
Program #1: Guess It
Author: Dale Reed
Lab: Tues 5am
System: C++ on Cloud 9
99:w 98:X 97:e 96:k 95:R 94:a 93:y 92:g 91:y 90:w
89:c 88:e 87:V 86:N 85:w 84:y 83:X 82:a 81:w 80:P
79:c 78:y 77:D 76:c 75:R 74:N 73:m 72:w 71:q 70:H
69:R 68:c 67:k 66:R 65:B 64:g 63:w 62:N 61:F 60:N
59:D 58:P 57:i 56:D 55:T 54:w 53:F 52:R 51:w 50:w
49:D 48:m 47:J 46:o 45:w 44:T 43:L 42:s 41:J 40:J
39:k 38:i 37:P 36:w 35:F 34:e 33:a 32:w 31:m 30:H
29:V 28:H 27:w 26:c 25:N 24:y 23:V 22:V 21:w 20:c
19:D 18:w 17:c 16:g 15:V 14:P 13:y 12:H 11:o 10:R
9:w 8:i 7:m 6:w 5:s 4:k 3:J 2:u 1:R 0:w
1. Choose any two-digit number in the table above (e.g. 73).
2. Subtract its two digits from itself (e.g. 73 - 7 - 3 = 63)
3. Find this new number (e.g. 63) and remember the letter next to it.
4. Now press the return key and I'll read your mind...
You selected the character: w
*/
#include <iostream> // For printf
#include <ctime> // For time()
#include <cstdlib> // For srand()
#include <iomanip> // For formatted output
using namespace std;
//-----------------------------------------------------------------------------------------
int main()
{
int randValue; // random number
char c; // random character, determined with a random number
char specialCharacter; // The special character that the computer will "guess"
// seed the random number generator
srand( time( 0)); // use this for different results each time
// Display ID information
cout << "\n";
cout << "Program #1: Guess It \n";
cout << "Author: Dale Reed \n";
cout << "Lab: Tues 5am \n";
cout << "System: C++ on Cloud 9\n";
cout << " \n";
// Choose a random character
randValue = rand() % 26; // generates a random value 0..25
// Add this random number to either 'A' or 'a' to get a random character.
// If the random number is odd, add it to 'a'. If even, add it to 'A'
if( randValue %2 == 0) {
specialCharacter = 'A' + randValue;
}
else {
specialCharacter = 'a' + randValue;
}
// For debugging:
// cout << "Special character is: %c \n\n", specialCharacter);
// Set the output precision
cout << fixed;
cout << setprecision(5);
// Display the 10x10 table of numbers and random characters
for( int i=99; i>=0; i--) {
// Get a random number 0..25
randValue = rand() % 26;
// Get a random character c, again making it upper-case if the random number
// was even, and making it lower-case if the random number was odd.
if( randValue %2 == 0) {
c = 'A' + randValue;
}
else {
c = 'a' + randValue;
}
// Display the number that preceeds each displayed character
printf("%2d:", i);
// Display this random character. If the position is a multiple
// of 9, display the "special" character instead.
if( i%9 != 0) {
cout << c; // display the random character
}
else {
cout << specialCharacter; // display the special character
}
cout << " ";
// print a newline character if we're at the end of a line
if( i%10 == 0) {
cout << "\n";
}
}//end for( int i...
// Display instructions and have user press enter when ready
cout << "\n";
cout << "1. Choose any two-digit number in the table above (e.g. 73). \n";
cout << "2. Subtract its two digits from itself (e.g. 73 - 7 - 3 = 63) \n";
cout << "3. Find this new number (e.g. 63) and remember the letter next to it. \n";
cout << "4. Now press 'r' and I'll read your mind... ";
cin >> c; // read user input
cout << endl;
// Display computer forecast
cout << "You selected the character: " << specialCharacter;
cout << endl;
return 0;
}//end main()
Python Version
# Magic Square mind-reader program
# Dale Reed, UIC BTT CS 111, Spring 2022
#
# Program #3: Mind Reader
# BTT CS 111: Program Design I in Python
#
# Sample run of program:
#
# Our subconscious get expressed in different ways, including
# through choices we make, how we type, and how quickly we type.
# Python libraries include Artificial Intelligence (AI) neural
# network tools that can recognize patterns.
# For this program choose the algorithm analysis level. Higher
# levels take longer, but are more accurate. Level 4 works most
# of the time.
# Enter level > 1: 0
#
# 99:y 98:i 97:P 96:o 95:u 94:g 93:p 92:m 91:T 90:y
# 89:w 88:I 87:H 86:D 85:k 84:a 83:U 82:A 81:E 80:M
# 79:G 78:N 77:A 76:H 75:O 74:P 73:h 72:E 71:H 70:H
# 69:O 68:J 67:a 66:R 65:u 64:F 63:E 62:X 61:j 60:x
# 59:X 58:W 57:N 56:v 55:j 54:E 53:S 52:P 51:q 50:S
# 49:b 48:H 47:m 46:v 45:E 44:L 43:W 42:V 41:l 40:O
# 39:q 38:y 37:Q 36:E 35:m 34:P 33:a 32:b 31:W 30:T
# 29:s 28:u 27:E 26:F 25:H 24:A 23:G 22:r 21:M 20:L
# 19:s 18:E 17:O 16:I 15:R 14:x 13:M 12:X 11:E 10:Y
# 9:E 8:g 7:b 6:L 5:r 4:q 3:P 2:l 1:l 0:E
#
# 1. Choose any two-digit number in the table above (e.g. 73).
# 2. Subtract its two digits from itself (e.g. 73 - 7 - 3 = 63)
# 3. Find this new number (e.g. 63) and remember the letter next to it.
# 4. Now press 'a' to analyze responses: a
#
# Your letter is: E
import random # Needed for random number generation
import time # Needed for sleep, which pauses the program
# --------------------------------------------------------------------------
# Get a random letter, which could be upper-case or lower-case
def get_Random_Letter():
# Get a random number, which will be the offset from 'a' or 'A'
letter_offset = random.randrange(0,25)
# Randomly choose between upper and lower case
if bool(random.getrandbits(1)):
# Make it upper case
secret_char = chr(65 + letter_offset)
else:
# Make it lower case
secret_char = chr(97 + letter_offset)
return secret_char
# --------------------------------------------------------------------------
# Main part of the program.
# Display identifying information when program runs
print('Program #3: Mind Reader')
print('BTT CS 111: Program Design I in Python')
print()
# Pretend that we have different "levels" of brain scan.
# Display a distractor message.
print('Our subconscious get expressed in different ways, including')
print('through choices we make, how we type, and how quickly we type.')
print('Python libraries include Artificial Intelligence (AI) neural ')
print('network tools that can recognize patterns.')
print('For this program choose the algorithm analysis level. Higher')
print('levels take longer, but are more accurate. Level 4 works most')
print('of the time.')
level = int( input('Enter level > 1: '))
print()
# Use the level as the random number generator seed. Multiple runs using the same
# level should give the same result.
random.seed( level)
# Generate a random secret letter
secret_char = get_Random_Letter()
counter = 99
while counter >= 0:
# Get the character to be displayed. This should be a random character,
# unless the current counter value is evenly divisible by 9, in which
# case it should be the secret_char.
if (counter % 9 == 0) and (counter < 90):
the_char = secret_char
else:
the_char = get_Random_Letter()
print(f'{counter:2d}:{the_char} ', end = '')
# Print a new line if we're at the end of a row
if counter % 10 == 0:
print()
# Increment the loop counter
counter -= 1
# Display instructions for users to find their new table cell, and
# prompt for 'a' to analyze responses.
print()
print('1. Choose any two-digit number in the table above (e.g. 73).')
print('2. Subtract its two digits from itself (e.g. 73 - 7 - 3 = 63) ')
print('3. Find this new number (e.g. 63) and remember the letter next to it. ')
userInput = input("4. Press 'a' to analyze responses: ")
# If input was > 0 then display the dots . . . indicating the program is thinking
if level > 0:
print(' Building neural network')
counter = 1
# Ensure the number of seconds to wait is a maximum of 5
if level > 5:
level = 5
while counter <= level:
print(' .')
time.sleep( 1)
counter += 1
# Display the computer's character guess
print()
print('Your letter is: ', end = '')
# Display the correct answer for levels 5+. For level 0 always give the right answer.
# For levels 1..4 use probabilities. The probability of the right answer being shown
# depends on the level: 1 = 20%, 2 = 40%, 3 = 60%, 4 = 80%, 5+ = 100%
if level == 0:
success_probability = 1.0 # Ensure level 0 always gives the correct answer
else:
success_probability = level * .2
random_Number = random.random()
if random_Number <= success_probability:
# Show the correct answer
print(secret_char)
else:
print( get_Random_Letter())
Python Starter Code
# Sample code to illustrate concepts needed for this program
import random # Needed for random number generation
# Initialize the random number generator so the results are reproducible each time.
# Comment out the following line, or simply remove the number in parenthesis to give
# different results each time the program is run. Make sure this line is uncommented
# when you test/turn in your program, so your results will match the expected results!
# random.seed( 1)
# Generate a random number in the range 0..25
value = random.randrange(0,25)
print('Random value is:',value)
# Display the corresponding alphabetical character. 65 corresponds to 'A', 66 to 'B',
# and so on. The chr() function converts a number to its corresponding character.
print( chr(65+value))
# Get a random true / false value
random_true_or_false = bool(random.getrandbits( 1)) # Generate a single 0/1 bit and convert it to true/false
print('Random value is:',random_true_or_false)
# Illustrate how a while loop works
counter = 1 # Initialize the loop counter
while counter < 10: # Check the loop ending condition
print( counter," ",end=' ')
counter += 1 # Increment the loop counter
print()
# Prompt for a value, and print a message indicating whether or not it is divisible by 3
print('Enter an integer number, to see if it is divisible by 3:', end=' ')
value = int(input())
if value % 3 == 0:
print(value,'is divisible by 3.')
else:
print(value,'is NOT divisible.')
Dale Reed, reed@uic.edu
Brenda Remess, bremess@cps.edu