Insights from Developing a Word Puzzle Game in Power Apps
Learn five powerful techniques—from single-screen control to offline data persistence—by following how I built an interactive word puzzle game.
Building a serious business application is one thing, but building a game in Power Apps pushes the platform to its limits in creative and technical ways. When I set out to create Word Weaver—a single-player puzzle where you tap adjacent letter tiles to form words, check them against an offline dictionary, and chase high scores—I uncovered several patterns that changed how I design everyday business apps. The constraints of mobile performance, data storage, and component reuse taught me lessons that apply far beyond the game screen.
Here are five insights from that project, presented as practical techniques you can adapt in your own Power Apps projects.
Insight 1: Contain All App Screens in a Single Power Apps Screen
Rather than creating multiple screens for the title, game board, results, and settings, I used a single screen and controlled visibility with a variable. This approach keeps common UI elements—background, navigation buttons, headers—in one place and avoids duplication.
I used a variable called appScreen to hold the current view name.
// In the Screen's OnVisible property (or a button OnSelect) Set(appScreen, "Title") // Later, change screen Set(appScreen, "Game") Set(appScreen, "Results")
Every control that should only appear on certain views uses the Visible property:
appScreen in ["Title", "Results"]
Why this matters: In a large app with many screens, keeping shared controls (logo, help icon, sound toggle) consistent becomes trivial. You also reduce context switching for users and lower the complexity of navigation logic.
Insight 2: Generate a Shuffled Tile Collection with One Line of Code
In Word Weaver, every new round places a fresh set of letters on a 4×5 grid. Instead of manually defining each tile, I created the entire letter pool with a single expression:
ClearCollect(
letterPool,
Shuffle(
Split("AABCDEEFGHIIJKLMNOOPQRSTUUVWXYZ", "")
)
)The result is a collection letterPool with 26 items, each containing a Result field with a single character. Shuffle randomises the order—perfect for determining which tile gets which letter.
To assign each tile its letter, I later loop through a second collection (tileData) that stores the grid positions:
// This runs once on game start
ForAll(
tileData, // contains Row, Col, and a sequential Index field
Patch(
tileData,
ThisRecord,
{Letter: Index(letterPool, Index).Result}
)
)The result is a fully populated grid where each tile has a unique letter from a shuffled pool.
Insight 3: Load an Offline Dictionary via Excel Import
Validating player words required a large dictionary stored locally so the game works without internet. Power Apps allows importing Excel tables as static data sources.
I prepared an Excel file with the dictionary split across multiple named tables (each ≤ 15,000 rows), then imported each table via Add data source > Import from Excel.
ClearCollect( colDictionary, DictA, DictB, DictC, DictD, DictE, DictF )
Because the collection lives entirely in device memory, you are not subject to SharePoint or SQL delegate limits. A 150,000+ row dictionary runs smoothly once loaded. The trade-off is initial load time—consider using smaller subsets during development.
Word validation then becomes a simple lookup:
If(
IsEmpty(Filter(colDictionary, Word = lower(playerWord))),
Notify("Word not found", NotificationType.Error),
Notify("Valid word!", NotificationType.Success)
)Since the Excel file is static, dictionary updates require manually re-importing the source. For frequently changing data, this method is not appropriate.
Insight 4: Components Paired with Collections for Dynamic Tiles
Every tile on the grid is an instance of a custom component called Tile. Each tile looks the same but shows different letter, value, and bonus information. By passing row and column coordinates as input properties, I let the component look up its own data from a collection.
The tiles are laid out in a 4×5 container (using a gallery or manual positioning), and each instance has these input properties defined:
Tile_Row: 3 Tile_Col: 2
Inside the component, I retrieve the corresponding record from the tileData collection:
LookUp( tileData, Row = Tile_Row And Col = Tile_Col, Letter )
The same component can also show its points value or a bonus indicator by adding separate LookUp properties. If the layout grows, you only update the component, not 20 identical formulas.
This pattern is identical to how you might build a data-driven dashboard where each card displays different metrics.
Insight 5: Persist High Scores Locally with SaveData/LoadData
The final piece of the puzzle was saving high scores on the device so players can compete against themselves even after closing the app. Power Apps provides the SaveData and LoadData functions for exactly this purpose.
When a player submits a new score, I update the colHighScores collection and save it:
Patch(
colHighScores,
Defaults(colHighScores),
{Name: txtPlayerName.Text, Score: currentScore}
);
SaveData(colHighScores, "WordWeaverHighScores")To retrieve the saved data on app start, I included this in the app’s OnStart:
LoadData(colHighScores, "WordWeaverHighScores", true)
SaveData stores the collection as a JSON file in the app’s sandboxed local storage. The data persists even when the device is restarted. The third parameter in LoadData (true) suppresses errors when no saved data exists yet.
Common mistake: Forgetting to call SaveData after every score change. Always test by closing and reopening the app to confirm persistence works.
Common Mistakes and Troubleshooting
- Too many screens from the start. Start with a single screen and add views only when visibility logic becomes too complex. It is easier to add screens later than to untangle 20 screens with duplicate controls.
- Shuffling repeatedly. Calling
Shuffleinside a gallery’sItemsproperty causes the order to change every time the gallery redraws. Always generate the shuffled collection once and store it. - Excel table limits. Each imported Excel table must have fewer than 15,000 rows. If your dictionary is larger, split it into multiple tables and combine them with
ClearCollect. - Component inputs not updating. Ensure input properties are set correctly on each component instance and that the collection fields match exactly (case-sensitive in some scenarios).
- SaveData not working. This function only works in Power Apps Mobile, not in a browser. Validate your app on a physical device or the Player app.
Final Recommendation
Building a game revealed patterns I now use in every serious app I create: single-screen layouts for apps with few views, collection generation for dynamic content, component/collection couples for repeated elements, and offline data storage for field workers. The constraints of a game—responsiveness, offline capability, and limited memory—force you to write cleaner, more efficient code.
If you want a hands‑on challenge, build your own word game using these five techniques. You will learn more about Power Apps concepts in one weekend than in weeks of traditional tutorials.
References
- Original article: 5 Things I Learned By Making A Power Apps Game by Matthew Devaney
- Import data from Excel: Microsoft Learn
- SaveData/LoadData functions: Microsoft Learn
- Custom components in Power Apps: Microsoft Learn (placeholder)