It was another cold winter Sunday, too cold for fishing, too cozy to be productive. I needed a challenge. Something silly but satisfying.
Twenty years ago I dabbled in Flash game development. A few of those games are still floating around internet archives somewhere, quietly embarrassing me. So I thought — why not build a game in Power Apps? Sure, in 2024 you can vibe-code something like this in minutes with AI. But where's the fun in that?
Here's my step-by-step journey building a fully working classic Minesweeper in Power Apps. Fast, rough, and absolutely not something your boss should see running on your SharePoint portal.
The Rules in a Nutshell
You have a grid hiding a set number of mines.
- Click a cell to reveal it.
- Hit a mine? Game over.
- Safe? It shows a number representing how many neighbouring cells contain mines.
- The Goal: Reveal all safe cells without going kaboom 💥.
Setup
Fire up the Power Apps portal and create a blank canvas app. For this demo we're hardcoding a 3×3 grid — keeping it simple and sane.
Here's all we need UI-wise:
- A vertical Gallery with
Wrap Count = 3andTemplate Size = 100 - Delete all default template controls and drop in a single square Button — this will be our cell
- One more Button on the main screen for starting and resetting the game — this is also where all our logic lives
That's it. Minimal controls, maximum fun. Let's get to work.
The Game Logic — Three Steps
Let's break the logic into three parts:
- Build the grid
- Plant the mines
- Calculate neighbour mine counts
Step 1 — Build the Grid
We need a collection of objects, one per cell, each storing everything we need to know about that cell.
Pop this into your Start Button's OnSelect property:
// 1. Create the game grid
ClearCollect(
colGameField,
ForAll(
Sequence(9), // 9 cells for a 3x3 grid
{
ID: Value,
IsMine: false, // is this cell a mine?
IsRevealed: false, // has the player clicked it?
AdjacentMineCount: 0, // how many mines are nearby?
PosX: Mod(Value - 1, 3) + 1, // X position: 1, 2, 3
PosY: Int((Value - 1) / 3) + 1 // Y position: 1, 2, 3
}
)
);
Don't forget to set your Gallery's Items property to colGameField.
Go ahead, hit the Start button. Marvel at your 9 beautiful empty cells. Take a moment. You deserve it.
Step 2 — Plant the Mines
I decided to set the number of mines to grid size + 1, so 4 mines for a 3×3 grid. The strategy: shuffle all cell IDs, grab the first 4, and tell them "sorry, you're a wizard... oi, a mine now."
// 2. Mine n+1 cells randomly
ClearCollect(
RandomMineIDs,
FirstN(Shuffle(Sequence(9)), 4)
);
UpdateIf(
colGameField,
ID in RandomMineIDs.Value,
{IsMine: true}
);
You won't see much yet since all cells are hidden. But if you're curious (read: impatient), temporarily add a Label to the gallery template with Text = ThisItem.IsMine. Hit Start a few times and watch the mines shuffle around randomly. Fun, right? Now remove the label — no cheating.
Step 3 — Calculate Neighbour Mine Counts
This is the meaty part. There are two ways to approach this:
Check every safe cell and count mines around it
Check every mine and increment its neighbour's counters
I went with option two — it's likely more efficient on larger grids. Here's the idea:
a) Find all mines (we have X/Y coordinates, so this is easy)
b) Find all 8 neighbours around each mine
c) If a neighbour is in bounds and not a mine, increment its AdjacentMineCount by 1
// 3. Calculate adjacent mine counts
ForAll(
Filter(colGameField, IsMine = true), // loop through all mines
ForAll(
Filter(
ForAll(
Sequence(9, 0), // 0-8 to generate 3x3 offset grid
{
NX: PosX + (Mod(Value, 3) - 1),
NY: PosY + (RoundDown(Value / 3, 0) - 1)
}
),
// exclude: the mine itself, out-of-bounds cells, and other mines
!(NX = PosX && NY = PosY) &&
NX > 0 && NX < 4 &&
NY > 0 && NY < 4 &&
LookUp(colGameField, PosX = NX && PosY = NY).IsMine = false
),
Patch(
colGameField,
LookUp(colGameField, PosX = NX && PosY = NY),
{AdjacentMineCount: LookUp(colGameField, PosX = NX && PosY = NY).AdjacentMineCount + 1}
)
)
)
The clever trick here: Starting
Sequencefrom 0 and usingMod(Value, 3) - 1gives us offsets of -1, 0, +1 for both X and Y — covering all 8 neighbours plus the cell itself, which we then filter out. Neat!
Want to test? Add a label with Text = ThisItem.AdjacentMineCount. Notice how mined cells show 0 — because we excluded them from incrementing. Once you're done admiring your work, clean up the label.
Making Cells Clickable
Almost there! Select the Button inside your gallery template and set these two properties:
OnSelect — reveal the cell on click (but only if it hasn't been revealed yet):
If(!ThisItem.IsRevealed, Patch(colGameField, ThisItem, {IsRevealed: true}))
Text — show what's under the cell:
If(ThisItem.IsRevealed && ThisItem.IsMine, "💥",
If(ThisItem.IsRevealed, Text(ThisItem.AdjacentMineCount), "❓"))
Mined cell? 💥. Safe cell? Shows the neighbour count. Unrevealed? ❓. Clean and simple.
Play It!
Hit Start and start clicking. Watch the numbers appear, find the mines, try not to explode. Click Start again for a fresh game.
Yes, there's no penalty for hitting a mine yet. No flagging. No timer. No mine counter. The board is tiny. But you know what? It works. And that's a win.
What's Next?
After sitting with it a little longer, I did add all the missing pieces — bigger board, flagging, timer, mine counter, and a proper game-over screen. The full version is actually good enough to drop on a SharePoint portal.
Just... maybe don't show your boss. 🙂
Built on a cold Sunday instead of going fishing. Zero regrets.
What do you think — should Power Apps game development be a thing? Drop a comment below!








Top comments (1)
I think it's a good thing to develop games in an environment that is about zero suitable to do so. It's fun to do and since it was not meant for game development, you learn a lot. I work in a niche language, Progress 4GL (database language) and have developed several games, like minesweeper, arkanoid and sokoban