NY Times Connections Game in Google Sheets
Introduction
The New York Times has long been a leader in word games, captivating players with titles like Spelling Bee, Wordle, and most recently, Connections. These games offer not only entertainment but also a valuable mental exercise, encouraging strategic thinking and vocabulary expansion. Inspired by the innovative nature of these NY Times games, I decided to implement a version of NY Times Connections in Google Sheets using Google Apps Script. This project is an ode to the original game—I hope this Google Sheets version can serve as a gateway for more people to discover and appreciate the original NY Times Connections game as part of their daily routine. This project is designed to be an accessible and educational tool that can help students, particularly those learning English as a second language (ESL), to engage with language in a fun, interactive way. Teachers can customize the word categories and members based on their curriculum.
Project Overview
Objective: To emulate the NY Times Connections game in Google Sheets, allowing users to categorize words based on common themes.
Rules: Players are presented with a 4x4 grid of words and must group them into four categories by identifying which words belong together. The challenge lies in finding the connections between the words, which can be more complex than they initially appear.
How to Play
Educational Benefits
The game is an excellent educational tool that fosters critical thinking and analytical skills by encouraging players to consider the relationships between different words. As they group words into categories, players experience vocabulary expansion and deepen their understanding of word meanings and connections. The puzzle format is inherently engaging, keeping students focused as they persist in finding the correct groupings. By making learning fun through word categorization, the learning process becomes more enjoyable, with a competitive element that adds excitement as students aim to complete the game as quickly and accurately as possible. This competition not only enhances attention to detail but also fosters a competitive learning environment, driving students to improve their vocabulary and categorization skills through healthy rivalry.
YouTube preview:
Technical Setup - Google Sheet Structure
There are two main sheets used in the project:
The Category Words Sheet serves as the database for the game's categories and their corresponding members. Each row in this sheet contains a category in the first column, such as "Fruits," and a comma-separated list of items in the second column, like "Apple, Banana, Cherry." The data for this sheet was generated using AI tools like ChatGPT, which allowed for the quick creation of a wide variety of categories and members. This approach not only saved time but also ensured a diverse range of content, making the game more engaging and educational. Additionally, this setup is scalable; if you want to add more categories in the future, you simply need to append them to this sheet, and the game will automatically incorporate the new data.
The Connections Game Sheet is where the gameplay takes place. The primary interface is a 4x4 grid, located in cells C3:F6, where users interact with the game. To play, users select four words by holding down the appropriate key on their keyboard—Ctrl on Windows, Cmd on Mac, or Shift on Chrome OS—while clicking on the words in the grid. After making their selection, they click the 'Check' button to see if their selection is correct. When a correct selection is made, the corresponding cells are highlighted with a pastel color, and the text is struck through. The game also provides immediate feedback by displaying the category name and the selected words in a summary area located in cells H2 to the right of the grid.
AI, specifically ChatGPT, played a significant role in generating the category data for the game. The efficiency of AI allowed for the quick creation of a diverse range of categories and their members, covering common topics like “Fruits” as well as more niche areas like “Magical Creatures” or “Programming Languages.” The data is structured in a format that makes it easy to expand the game’s content without requiring any code changes. This AI-generated content not only makes the game more fun but also introduces students to new words and concepts, adding educational value.
领英推荐
In addition to generating data, AI also assisted in writing the Google Apps Script that powers the game. For instance, AI helped create the newGame function, which populates the grid with words and resets the game state to ensure each game is unique and challenging. The AI also contributed to scripting the logic that validates whether the selected words belong to the same category, ensuring smooth gameplay. Moreover, the feedback system, which highlights correct selections and displays the corresponding category in the summary area, was also co-authored with the help of AI.
The game’s mechanics involve several key processes. First, the script randomly selects four categories from the "Category Words" sheet and then randomly picks four members from each category to populate the grid. The cells are formatted to enhance readability and user experience, ensuring that all the information is clearly displayed. As players make correct selections, the game tracks how many categories have been correctly identified and provides immediate visual feedback by highlighting and striking through the selected words. This immediate feedback not only enhances the user experience but also makes the game more engaging and educational.
Explanation of Functions
newGame Function
The newGame function is responsible for setting up a fresh game in the Google Sheets version of NY Times Connections. It starts by accessing the spreadsheet and the specific sheets where the game and category data are stored. It then adjusts the size of the rows and columns to create a 4x4 grid, making sure that the grid is clear and ready for a new game by removing any existing content. The function also ensures that the text in the grid cells is properly formatted and wrapped, so all words are easily readable.
Next, the function retrieves all the available categories and their associated words from the "Category Words" sheet. It randomly selects four different categories and then randomly picks four words from each selected category to fill the grid. The words are shuffled to ensure they are placed randomly within the grid.?
checkSelection Function
The checkSelection function is activated when a player selects four words and clicks the 'Check' button. This function first checks if exactly four words have been selected. If not, it prompts the player to select the correct number of words. Once four words are selected, the function compares these words with the categories listed in the "Category Words" sheet.
For each selected word, the function identifies all possible categories that the word might belong to. It then checks for a common category that all four selected words share. If a single common category is found, the selected cells are highlighted with a random pastel color, and the text is struck through, indicating that the selection is correct. The category name and selected words are also displayed in a summary area to the right of the grid.?
If all four categories in the grid are correctly identified, the game asks if the player wants to start a new game. If the selection is incorrect, the player is alerted that the words do not belong to the same category.
showInstructions Function
The showInstructions function provides players with the necessary instructions on how to play the game. When this function is called, it displays an alert box with step-by-step instructions. The instructions explain how to select four words that belong to the same category and which key to hold down on the keyboard while clicking on the words, depending on the operating system (Windows, Mac, or Chrome OS). It also reminds players to click the 'Check' button after making their selection to see if they are correct. This function ensures that all players, regardless of their familiarity with the game or the platform, can easily understand how to play.
Feedback and User Experience
Providing Clear Feedback: When a player makes a selection, the script provides immediate feedback on whether the selection is correct. This helps players learn from their mistakes and understand the connections between words more clearly.
Smooth Gameplay: The use of toast notifications and non-intrusive feedback ensures that the game remains engaging and that players can focus on categorizing words without unnecessary interruptions.
Conclusion
The Google Sheets implementation of NY Times Connections offers a unique blend of entertainment and education, making it a valuable tool for both teachers and students. Whether you're looking to enhance vocabulary, improve categorization skills, or simply enjoy a challenging word game, this project provides a fun and accessible way to engage with language.?
Full Code Base
The full Code.gs file is here and below.
Here again is the template preview.
function newGame() {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var gameSheet = spreadsheet.getSheetByName('Connections Game');
var categoriesSheet = spreadsheet.getSheetByName('Category Words');
// Resize the rows and columns to fit the 4x4 grid
var gridRange = gameSheet.getRange('C3:F6');
for (var i = 3; i <= 6; i++) {
gameSheet.setRowHeight(i, 60); // Adjust row height if needed
gameSheet.setColumnWidth(i, 200); // Adjust column width if needed
}
// Clear any existing values in the grid
gridRange.clearContent();
gridRange.setBackground(null);
gridRange.setFontLine('none');
// Set font to Oswald and size to 14 for the grid
gridRange.setFontFamily('Oswald');
gridRange.setFontSize(14);
// Wrap text in the grid
gridRange.setWrap(true);
// Clear the display range H2:I5 and apply text wrap
var displayRange = gameSheet.getRange('H2:I5');
displayRange.clearContent();
displayRange.setWrap(true);
// Get all category data
var categories = categoriesSheet.getDataRange().getValues();
// Function to get a random integer between min and max (inclusive)
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
// Select four different random categories
var selectedCategories = [];
while (selectedCategories.length < 4) {
var randomIndex = getRandomInt(1, categories.length - 1); // Skip header row
var category = categories[randomIndex];
if (!selectedCategories.includes(category)) {
selectedCategories.push(category);
}
}
// Shuffle words into the grid
var words = [];
selectedCategories.forEach(function (category) {
var categoryWords = category[1].split(',').map(function (word) { return word.trim(); });
while (words.length < selectedCategories.indexOf(category) * 4 + 4) {
var randomWordIndex = getRandomInt(0, categoryWords.length - 1);
var word = categoryWords[randomWordIndex];
if (!words.includes(word)) {
words.push(word);
}
}
});
// Shuffle words array to randomize placement in the grid
words = words.sort(() => Math.random() - 0.5);
// Place words in the grid
var wordIndex = 0;
for (var row = 3; row <= 6; row++) {
for (var col = 3; col <= 6; col++) {
gameSheet.getRange(row, col).setValue(words[wordIndex]);
wordIndex++;
}
}
// Reset correct count
PropertiesService.getUserProperties().setProperty('correctCount', 0);
}
function checkSelection() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Connections Game');
var selectedRange = sheet.getActiveRangeList(); // Use getActiveRangeList to handle non-contiguous selections
var selectedValues = [];
// Iterate over each range in the active range list
selectedRange.getRanges().forEach(function (range) {
selectedValues = selectedValues.concat(range.getValues().flat());
});
if (selectedValues.length !== 4) {
SpreadsheetApp.getUi().alert('Please select exactly four words.');
return;
}
var categoriesSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Category Words');
var dataRange = categoriesSheet.getDataRange();
var categories = dataRange.getValues();
var possibleCategories = {}; // To store all possible categories for each word
// Identify all possible categories for each selected word
selectedValues.forEach(function (word) {
word = word.toLowerCase();
possibleCategories[word] = [];
for (var row = 1; row < categories.length; row++) { // Skip header row
var wordsList = categories[row][1].toLowerCase().split(',').map(function (word) { return word.trim(); });
if (wordsList.includes(word)) {
possibleCategories[word].push(categories[row][0]);
}
}
});
// Find the common category across all selected words
var commonCategory = possibleCategories[selectedValues[0].toLowerCase()];
for (var i = 1; i < selectedValues.length; i++) {
var wordCategories = possibleCategories[selectedValues[i].toLowerCase()];
commonCategory = commonCategory.filter(function (category) {
return wordCategories.includes(category);
});
}
if (commonCategory.length === 1) {
// Highlight the selected cells in a random pastel color and apply strikethrough
var pastelColors = [
"#b7d8b7", // Soft Mint
"#b7c9d8", // Light Sky Blue
"#d8b7c9", // Pale Pink Purple
"#d8d0b7", // Light Khaki
"#c9b7d8", // Lavender
"#d0d8b7", // Pale Lime Green
"#b7d8c9", // Soft Aqua
"#d8b7b7", // Soft Pink
"#d8c9b7", // Pale Sand
"#c9d8b7", // Light Green
"#d5a6bd", // Muted Pink
"#fff2cc", // Pale Yellow
"#d9d2e9", // Pale Purple
"#b6d7a8", // Light Green
"#fce5cd", // Peach Cream
"#e6b8af", // Soft Coral
"#d0e0e3", // Pale Turquoise
"#f4cccc", // Pastel Red
"#ead1dc", // Pale Lavender Pink
"#cfe2f3", // Soft Blue
"#add8e6", // Light Blue
"#f0e68c", // Khaki
"#ffb6c1", // Light Pink
"#d8bfd8", // Thistle
"#dda0dd", // Plum
"#ffe4e1", // Misty Rose
"#ffebcd", // Blanched Almond
"#fafad2", // Light Goldenrod Yellow
"#ffe4b5", // Moccasin
"#ffdead", // Navajo White
"#f0e5c9", // Cream
"#faf0e6", // Linen
"#e6e6fa", // Lavender
"#fff5ee", // Seashell
"#f5f5dc", // Beige
"#fdfd96", // Pastel Yellow
"#a4c2f4", // Soft Blue
"#9fc5e8", // Sky Blue
"#6d9eeb", // Periwinkle Blue
"#c9daf8", // Lavender Blue
"#76a5af", // Soft Teal
"#92cddc", // Light Blue-Green
"#b4a7d6", // Light Purple
"#8e7cc3", // Lavender Purple
"#6fa8dc", // Cornflower Blue
"#8faabd", // Slate Gray Blue
"#e3eaa7", // Pastel Lime
"#d9e4fc", // Pale Sky Blue
"#c5e3f6", // Powder Blue
"#f7fcb9", // Soft Lemon
"#d8e4bc", // Pale Olive Green
"#cad2c5", // Sage Green
"#e4e4c5", // Light Moss
"#b8e0a2", // Pale Spring Green
"#a2c4c9", // Soft Cyan
"#ace1af", // Celadon Green
"#FFB3BA", // Light Salmon Pink
"#FFDFBA", // Light Peach
"#FFFFBA", // Light Butter Yellow
"#BAFFC9", // Mint Green
"#BAE1FF", // Baby Blue
];
var randomColor = pastelColors[Math.floor(Math.random() * pastelColors.length)];
selectedRange.getRanges().forEach(function (range) {
range.setBackground(randomColor);
range.setFontLine('line-through');
});
// Display the correct selection alert
var categoryName = commonCategory[0];
SpreadsheetApp.getUi().alert('Correct selection! Category: ' + categoryName);
// Display the category name and members in H2 and I2
var displaySheet = sheet;
var displayRange = displaySheet.getRange('H2:I5'); // Adjust as needed to fit all categories
var displayValues = displayRange.getValues();
var displayRow = displayValues.findIndex(row => !row[0]); // Find the first empty row in the display range
if (displayRow === -1) {
displayRow = 0; // If no empty row is found, start from the top (this can be adjusted if necessary)
}
displaySheet.getRange(displayRow + 2, 8).setValue(categoryName); // Set category name in column H
displaySheet.getRange(displayRow + 2, 9).setValue(selectedValues.join(', ')); // Set category members in column I
// Ensure all pending changes are applied before proceeding
SpreadsheetApp.flush();
// Update the count of correct selections
var userProperties = PropertiesService.getUserProperties();
var correctCount = parseInt(userProperties.getProperty('correctCount')) || 0;
correctCount += 1;
userProperties.setProperty('correctCount', correctCount);
// Check if all 16 words have been categorized
if (correctCount >= 4) {
var ui = SpreadsheetApp.getUi();
var response = ui.alert('Congratulations! You categorized all the words correctly. Do you want to play again?', ui.ButtonSet.YES_NO);
if (response == ui.Button.YES) {
userProperties.setProperty('correctCount', 0);
newGame();
}
}
} else {
SpreadsheetApp.getUi().alert('Incorrect selection. The words do not all belong to the same category.');
}
}
function showInstructions() {
var ui = SpreadsheetApp.getUi();
var instructions =
"Instructions:\n\n" +
"1. Select 4 words that you believe belong to the same category.\n" +
"2. Depending on your operating system, hold down the following key while clicking on the words:\n\n" +
" - Windows: Hold the 'Ctrl' (Control) key\n" +
" - Mac: Hold the 'Cmd' (Command) key\n" +
" - Chrome OS: Hold the 'Shift' key\n\n" +
"3. After selecting 4 words, click the 'Check' button to see if you are correct.\n\n" +
"Good luck and have fun!";
ui.alert(instructions);
}