Connect The Thoughts

Release Date: 2012

Language Used:

Objective-C

Software Used:

Xcode

Platforms:

iOS

About:

Connect The Thoughts is a game I worked on with Raymond Shaw and Michael Stroud, two professors from Merrimack College in North Andover, MA. The goal of the game was to create a fun way to generate data on how people relate words to other words.

The game is a multiplayer title, utilizing Apple's Game Center backend to transfer data between players. More specifically, it uses Game Center's asynchronous gameplay style, allowing players to be involved in multiple games simultaneously. It also uses Game Center's leaderboards, keeping track of things like games played and games won.

Player 1 is given a random word, then asked to provide three other words that relate to the first word. Player 2 recieves these three words as clues, and is asked to try to guess player 1's word. The less clues they need, the more points both players are awarded. If the word is never guessed, no points are awarded.

Connect The Thoughts also uses in-app purchases to allow players to purchase virtual currency to spend on hints in the game, such as an extra hint or the length of the word. This currency is also awarded after a successful game, making in-app purchases a helpful, but not required, addition to the game.

Note: Due to limitations in Apple's iOS Simulator, a live demo is not possible for the game in-browser. If you'd like to try the game, you can download it for free using the app store link.

Code Samples

Random Word Setup

In the game, player 1 recieves a random word from a predefined list. To prevent the player from seeing duplicate words in a short time, a second array is created from the first list, and random words are taken from that. Once that list runs out, it is refilled from the primary list. This ensures all words will be exhausted before cycling through them again. This method also allowed us to easily update the master word list with new words.

- (void)setupArrays {
/*
On first launch, we will generate a string based on the contents of the first row of a csv.
We will save this string with the file name: fileStringData.txt
Then we will create two NSArrays: a primaryWordsArray and a secondaryWordsArray.
The primary array will hold an array of all our words, and will not be edited.
The secondary array will hold an exact copy of the primary array. When a new word is requested at the start of a game,
it will be taken from the secondary array, as well as deleted from the secondary array.
If the secondary array ever runs out of items, we will re-populate it with the contents of the primary array.
On launches after the first launch, we will generate a string based on the contents of the first row of a csv, and check it
against the version that is already saved. If it is different, then we are dealing with an updated words list, so update the fileStringData and primary and secondary arrays.
If it is the same, we are dealing with the current version of the words list, so do nothing.
This is done with the goal to not repeat words until all the words have been exhausted from the words list.
*/
// filePath, fileString and fileStringData all refer to the CSV given to us by Michael and Ray
// sorry for the kinda screwy naming
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"Words List" ofType:@"csv"];
NSString *fileString = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
// Creating a file path under iPhone OS:
// 1) Search for the app's documents directory (copy+paste from Documentation)
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *libraryDirectory = [paths objectAtIndex:0];
// 2) Create the full file path by appending the desired file name
NSString *fileStringData = [libraryDirectory stringByAppendingPathComponent:@"fileStringData.txt"];
NSString *allRowsArrayData = [libraryDirectory stringByAppendingPathComponent:@"allRowsArrayData.dat"];
NSString *primaryArrayData = [libraryDirectory stringByAppendingPathComponent:@"primaryArrayData.dat"];
NSString *secondaryArrayData = [libraryDirectory stringByAppendingPathComponent:@"secondaryArrayData.dat"];
// Our Arrays
NSArray *allRowsArray = [[NSArray alloc] initWithContentsOfFile:allRowsArrayData];
NSMutableArray *primaryWordsArray = [[NSMutableArray alloc] initWithContentsOfFile:primaryArrayData];
NSMutableArray *secondaryWordsArray = [[NSMutableArray alloc] initWithContentsOfFile:secondaryArrayData];
// update the fileString, if needed
// will hold our newest file string to compare against the one already saved (fileStringData.txt)
// also used to check to see if fileStringData exists, since we are creating it with the contents of fileStringData
NSString *newFileString = [[NSString alloc] initWithContentsOfFile:fileStringData encoding:NSUTF8StringEncoding error:nil];
// if newFileString is empty, that means fileStringData.txt is empty, so create and save it
if (newFileString == nil) {
// save and update newFileString
[fileString writeToFile:fileStringData atomically:YES encoding:NSUTF8StringEncoding error:nil];
newFileString = [[NSString alloc] initWithContentsOfFile:fileStringData encoding:NSUTF8StringEncoding error:nil];
}
// if allRowsArray doesn't exist, create it, and the primary and secondary arrays, and save them
// if allRowsArray does exist, update the arrays if we are running a new version (if the new fileString is different than the stored one)
if (allRowsArray == nil) {
// show the loading screen
[self performSelectorOnMainThread:@selector(showLoadingScreen) withObject:nil waitUntilDone:NO];
// update allRowsArray
allRowsArray = [NSArray arrayWithContentsOfCSVString:fileString encoding:NSUTF8StringEncoding error:nil];
[allRowsArray writeToFile:allRowsArrayData atomically:YES];
// create the primary array, and save it
primaryWordsArray = [allRowsArray objectAtIndex:0];
[primaryWordsArray writeToFile:primaryArrayData atomically:YES];
// create and save the secondary array (this is the one we will take words from and re-populate when it reaches 0)
secondaryWordsArray = [[NSMutableArray alloc] initWithArray:primaryWordsArray];
[secondaryWordsArray writeToFile:secondaryArrayData atomically:YES];
// hide the loading screen
[self performSelectorOnMainThread:@selector(hideLoadingScreen) withObject:nil waitUntilDone:NO];
} else if (![newFileString isEqualToString:fileString]) {
// show the loading screen
[self performSelectorOnMainThread:@selector(showLoadingScreen) withObject:nil waitUntilDone:NO];
// update fileString
[fileString writeToFile:fileStringData atomically:YES encoding:NSUTF8StringEncoding error:nil];
fileString = [[NSString alloc] initWithContentsOfFile:fileStringData encoding:NSUTF8StringEncoding error:nil];
// update allRowsArray
allRowsArray = [NSArray arrayWithContentsOfCSVString:fileString encoding:NSUTF8StringEncoding error:nil];
[allRowsArray writeToFile:allRowsArrayData atomically:YES];
// update primaryWordsArray
primaryWordsArray = [allRowsArray objectAtIndex:0];
[primaryWordsArray writeToFile:primaryArrayData atomically:YES];
// update secondary array
secondaryWordsArray = [[NSMutableArray alloc] initWithArray:primaryWordsArray];
[secondaryWordsArray writeToFile:secondaryArrayData atomically:YES];
// hide the loading screen
[self performSelectorOnMainThread:@selector(hideLoadingScreen) withObject:nil waitUntilDone:NO];
}
}