Spot it!
🎲

Spot it!

Author
Stephen Wu
Published
February 17, 2026
Tags
Projects
Many years ago, I stumbled upon a children’s board game called Spot it (a.k.a Dobble).
notion image
The game is simple and fun, designed for children ages 6 and up.
 
There’s a deck of cards with 8 symbols on each card. Every deck has one symbol in common with every other card.
notion image
 
There are a few variants of the game, my go-to is:
  1. Put one card face-down in the middle of all the players.
  1. Deal the remaining deck evenly to all players as face-down stacks
  1. Everyone flips their stack face-up and someone flips the center card face-up.
  1. Everyone looks at their face-up card and the center card.
    1. The moment anybody sees a matching symbol with the center card, they should say it out loud and place their card onto the center.
    2. That placed card is now the new center card.
    3. Repeat.
  1. The person who empties their deck first gets 1st, next gets 2nd, and so on.
 
This project is my version of the game, with a practice mode, timed mode, and a visualizer to explain the math.

The math

To me, the most interesting aspect of this game is the math behind it.
 
Given a deck of n=8 symbols that meets the constraints:
  1. Each card has n symbols on them
  1. Each card has one symbol in common with every other card
  1. Each symbol must be used an equal number of times.
How many S total symbols and C total cards are there?
 
Or, in tweet form:
 
 
If you’re interested in the solutions, here’s three:

Solution 1: Incremental Deck Construction

Let’s take an incremental approach where we build up the set of cards, and backtrack as needed.
Step 0: Normalize the representation
One of the first steps of problems like this is to turn this representation into something easier to work with. Let’s use numbers to represent symbols:
⚓ -> 1 🍎 -> 2 🍼 -> 3 💣 -> 4 🌵 -> 5 ... and so on
And let’s use array notation to represent a set of symbols in a card, e.g. [1,2,3], naming each card #1, #2, etc.
 
Let’s skip constraint (3: Each symbol must be used an equal number of times) for now, and only worry about (1) & (2):
  1. Each card has n symbols on them
  1. Each card has one symbol in common with every other card

Step 1: Start with a base
Let’s begin with card #1, and say card #1 has the set [1,2,3,4,5,6,7,8].
We can then naturally say card #2 has [1,9,10,11,12,13,14,15] , as it needs to share a card with set #1.
We’ve now arrived at the most basic solution: 15 symbols + 2 cards.
But of course, we can do better!
The next card needs to match with both of the existing cards, meaning it needs to have either [1] or items from both [2,3,4,5,6,7,8] and [9,10,11,12,13,14,15].
If we’re matching with the [1], let’s then say the next card is [1,16,17,18,19,20,21,22].
You may realize that we can then keep adding matches this way, we just take [1] and add the next 7 numbers that haven’t been seen yet!

Step 2: The “infinite” solution
Cheeky solvers may attempt the solutionInfinity symbols + Infinity cards.
#1: [1,2,3,4,5,6,7,8] #2: [1,9,10,11,12,13,14,15] #3: [1,16,17,18,19,20,21,22] ... #N+1: [1,2+7N,3+7N,4+7N,5+7N,6+7N,8+7N] ... ad infinitum
But this isn’t a valid solution, because we don’t actually meet constraint (3): Each symbol must be used an equal number of times.
With infinite symbols, and therefore infinite cards, it’s impossible to make a card that matches with every other card.
Therefore, we have to stop the incrementation at some point in which it no longer becomes possible to make any new cards.

Step 3: Getting to 8 cards
With some thinking, you may realize that you can no longer make any more cards with [1] after once we’ve done this 8 times.
#1: [1,2,3,4,5,6,7,8] #2: [1,9,10,11,12,13,14,15] #3: [1,16,17,18,19,20,21,22] #4: [1,23,24,25,26,27,28,29] #5: [1,30,31,32,33,34,35,36] #6: [1,37,38,39,40,41,42,43] #7: [1,44,45,46,47,48,49,50] #8: [1,51,52,53,54,55,56,57]
Why is it finished after 8 times?
  • Well, because if you use [1], then you must fill the card with totally new symbols ([58,59,60,61,62,63,64])
  • If you don’t use [1], you then must use a symbol from every of the other 8 cards.
    • But if you had [1,58,59,60,61,62,63,64], then this attempt to make a new card of 8 is now impossible, because we started with any other number than 1, e.g. [2], you’d then need to add 7 new not-1 symbols from every other card. But now there are ≥8 sets, all with distinct symbols, so this is impossible.
Therefore we now have an upper bound on the # of symbols: 57 and our first 8 cards.

Step 4: Finding more intersections
Now let’s see if we can confirm the 8 cards we have, and justify the 8 matches-per card and 57 symbols, or if we have to backtrack.
Let’s now try [2]. Remember, we need to add a non-1 symbol from every other card, so that gets us to: [2,9,16,23,30,37,44,51], if we add each first valid number.
#9: [2,9,16,23,30,37,44,51]
As we continue in [2]s, let’s once again add the next valid number.
Because we have [2,9,16,23,30,37,44,51] in card #9, then we need to add [10,17,24,31,38,45,52] next to avoid conflicts.
This gets us to
#10: [2,10,17,24,31,38,45,52]
Repeat the process for the remaining 2s, and now we have:
#11: [2,11,18,25,32,39,46,53] #12: [2,12,19,26,33,40,47,54] #13: [2,13,20,27,34,41,48,55] #14: [2,14,21,28,35,42,49,56] #15: [2,15,22,29,36,43,50,57]
And you’ll note that all these are just incrementing every number after [2] as well to avoid conflicts!
And we’ve completed our first 15 cards, with both [1] and [2] represented 8 times, and each other number represented 2 times.

Step 4: Continuing the pattern
Next up, let’s do the [3]s, with a similar idea, adding each of the first allowed numbers to the set.
  • First we have [3] and our first possible number to add is [9] , because card #1 prevents 4 through 9.
  • Then we have [3,9] and our next number is [17], since [10-15] is blocked by card #2 and 16 is blocked by card #9.
  • Then we have [3,9,17] and our next number is [25] , since [18-22] are blocked by card #3 and [23] is blocked by card #9 and [24] is blocked by card #10.
  • Eventually we get to… [3,9,17,25,33,41,49,57] and just like the [2]s we can keep incrementing again, but we also have a bit of a loop effect going on too.
#16: [3,9,17,25,33,41,49,57] #17: [3,10,18,26,34,42,50,51] #18: [3,11,19,27,35,43,44,52] #19: [3,12,20,28,36,37,45,53] #20: [3,13,21,29,30,38,46,54] #21: [3,14,22,23,31,39,47,55] #22: [3,15,16,24,32,40,48,56]
We continue this process for the remaining numbers, which is a tad tedious until you see the underlying “looping” pattern:
#23: [4,9,18,27,36,38,47,56] #24: [4,10,19,28,30,39,48,57] #25: [4,11,20,29,31,40,49,51] #26: [4,12,21,23,32,41,50,52] #27: [4,13,22,24,33,42,44,53] #28: [4,14,16,25,34,43,45,54] #29: [4,15,17,26,35,37,46,55]
Zooming out, you’ll start to see the patterns:
  • 1st index is [9,10,11,12,13,14,15] on a loop, with +0 from the previous card set (e.g. is 3 started with 9, then 4 starts with 9
  • 2nd index is [16,17,18,19,20,21,22] on a loop, with +1 from the previous card set (e.g. if 3 started with 17, then 4 starts with 18
  • 3rd index is [23,24,25,26,27,28,29] on a loop, with +2 from the previous card set
  • 4th index is [30,31,32,33,34,35,36] on a loop, with +3
  • 5th index is [37,38,39,40,41,42,43] on a loop, with +4
  • 6th index is [44,45,46,47,48,49,50] on a loop, with +5
  • 7th index is [51,52,53,54,55,56,57] on a loop, with +6

And we can then construct the whole deck with this pattern:
#1: [1,2,3,4,5,6,7,8] #2: [1,9,10,11,12,13,14,15] #3: [1,16,17,18,19,20,21,22] #4: [1,23,24,25,26,27,28,29] #5: [1,30,31,32,33,34,35,36] #6: [1,37,38,39,40,41,42,43] #7: [1,44,45,46,47,48,49,50] #8: [1,51,52,53,54,55,56,57] #9: [2,9,16,23,30,37,44,51] #10: [2,10,17,24,31,38,45,52] #11: [2,11,18,25,32,39,46,53] #12: [2,12,19,26,33,40,47,54] #13: [2,13,20,27,34,41,48,55] #14: [2,14,21,28,35,42,49,56] #15: [2,15,22,29,36,43,50,57] #16: [3,9,17,25,33,41,49,57] #17: [3,10,18,26,34,42,50,51] #18: [3,11,19,27,35,43,44,52] #19: [3,12,20,28,36,37,45,53] #20: [3,13,21,29,30,38,46,54] #21: [3,14,22,23,31,39,47,55] #22: [3,15,16,24,32,40,48,56] #23: [4,9,18,27,36,38,47,56] #24: [4,10,19,28,30,39,48,57] #25: [4,11,20,29,31,40,49,51] #26: [4,12,21,23,32,41,50,52] #27: [4,13,22,24,33,42,44,53] #28: [4,14,16,25,34,43,45,54] #29: [4,15,17,26,35,37,46,55] #30: [5,9,19,29,32,42,45,55] #31: [5,10,20,23,33,43,46,56] #32: [5,11,21,24,34,37,47,57] #33: [5,12,22,25,35,38,48,51] #34: [5,13,16,26,36,39,49,52] #35: [5,14,17,27,30,40,50,53] #36: [5,15,18,28,31,41,44,54] #37: [6,9,20,24,35,39,50,54] #38: [6,10,21,25,36,40,44,55] #39: [6,11,22,26,30,41,45,56] #40: [6,12,16,27,31,42,46,57] #41: [6,13,17,28,32,43,47,51] #42: [6,14,18,29,33,37,48,52] #43: [6,15,19,23,34,38,49,53] #44: [7,9,21,26,31,43,48,53] #45: [7,10,22,27,32,37,49,54] #46: [7,11,16,28,33,38,50,55] #47: [7,12,17,29,34,39,44,56] #48: [7,13,18,23,35,40,45,57] #49: [7,14,19,24,36,41,46,51] #50: [7,15,20,25,30,42,47,52] #51: [8,9,22,28,34,40,46,52] #52: [8,10,16,29,35,41,47,53] #53: [8,11,17,23,36,42,48,54] #54: [8,12,18,24,30,43,49,55] #55: [8,13,19,25,31,37,50,56] #56: [8,14,20,26,32,38,44,57] #57: [8,15,21,27,33,39,45,51]
You can even have ChatGPT write a solver to ensure all constraints are met:
✅ All sets have 8 numbers. ✅ All sets share exactly 1 number in common with every other card. ✅ All numbers are represented exactly 8 times.

Solution 2: Projective plane

Folks familiar with projective planes may immediately recognize that this problem can be exactly framed as a finite projective plane.
 
 
A finite projective plane of order n is a geometric structure that satisfies:
  • Set of points and lines
  • Any two points only have one line that passes through them
  • Any two lines only have one point in common.
 
Sound familiar? The last property is exactly our constraint that any two cards share exactly one symbol.
 
 
A projective plane of order 3
A projective plane of order 3
Each point above represents a symbol, and each different colored line represents a card that contains the symbols the line intersects with.
 
The properties of this plane is that:
  • There are n² + n + 1 points (symbols)
  • There are n² + n + 1 lines (cards)
  • Each line contains n + 1 points
  • Each point lies on n + 1 lines
  • Any two lines intersect at exactly one point
 
 
For Spot It! with 8 symbols per card, we have n + 1 = 8, so n = 7. Or, a full Spot It deck with 8 symbols/card is exactly a projective plane of order 7.
 
Plugging into the formula:
  • Symbols: n² + n + 1 = 49 + 7 + 1 = 57
  • Cards: n² + n + 1 = 57
  • Symbols per card: n + 1 = 8
  • Cards per symbol: n + 1 = 8
 
The general formula:
Symbols per card
Total symbols
Total cards
3 (n=2)
7
7
4 (n=3)
13
13
5 (n=4)
21
21
6 (n=5)
31
31
8 (n=7)
57
57
9 (n=8)
73
73
You’ll note here that the number of symbols always equals the number of cards.
 
Brendan Conley describes this solution more clearly in his article The Math of Spot it.

Solution 3: Proof by algebra

Let = symbols per card (here: ).
Let = how many cards each symbol appears on (same for every symbol).
Let = total number of cards.
Let = total number of symbols.
 
Step 1: Count cards using one fixed card
 
Pick one card.
  • It has symbols.
  • Each symbol on it appears on other cards.
  • Those groups of cards can’t overlap (otherwise some card would share 2 symbols with this card)
 
So the number of other cards is exactly:
Therefore:
With :
 
Step 2: Double count symbol appearances
 
Count total “symbol appearances” in the whole deck two ways:
  • Each card has symbols → appearances
  • Each of symbols appears times → appearances
 
So:
With :
 
Step 3: Fisher-style bound
 
Key bound: you can’t have more cards than symbols in this setup.
 
Proof by contradiction:
  • Suppose .
  • Then implies .
  • Suppose . Fix a card and choose a symbol . Then appears on at least other cards.
  • Each of those other cards must contain additional symbols not on .
  • Moreover, no two of those cards can share any of these “extra” symbols. If they did, those two cards would share both and that extra symbol, contradicting the rule that any two cards intersect in exactly one symbol.
  • Therefore the cards containing require at least distinct symbols outside , so
  • But we also have (from Step 1) and (from Step 2), hence
  • Combining gives
    • so . In particular, is impossible.
  • Therefore .
  • (You can also see Solution 1, step 3 for a similar explanation to this bound.)
 
Step 4: Derive the maximum
 
Combine:
So: . Or, in other words, we cannot have more than 8 cards for any symbol.
 
Maximize by taking the biggest allowed :
 
Then solve for from :
 
Final answer:
 

The app

Some details about the app:
  • React + Vite, hosted on Vercel (free)
I liked the playful, illustrated nature of the OpenMoji set, designed by students in Germany.
I liked the playful, illustrated nature of the OpenMoji set, designed by students in Germany.