Many years ago, I stumbled upon a childrenâs board game called Spot it (a.k.a Dobble).
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.
Â
There are a few variants of the game, my go-to is:
- Put one card face-down in the middle of all the players.
- Deal the remaining deck evenly to all players as face-down stacks
- Everyone flips their stack face-up and someone flips the center card face-up.
- Everyone looks at their face-up card and the center card.
- The moment anybody sees a matching symbol with the center card, they should say it out loud and place their card onto the center.
- That placed card is now the new center card.
- Repeat.
- 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:
- Each card has n symbols on them
- Each card has one symbol in common with every other card
- 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):
- Each card has n symbols on them
- 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 solution
Infinity 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 and16is 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]swe 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+0from the previous card set (e.g. is3started with9, then4starts with9
- 2nd index is
[16,17,18,19,20,21,22]on a loop, with+1from the previous card set (e.g. if3started with17, then4starts with18
- 3rd index is
[23,24,25,26,27,28,29]on a loop, with+2from 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.
Â
Â
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 + 1points (symbols)
- There are
n² + n + 1lines (cards)
- Each line contains
n + 1points
- Each point lies on
n + 1lines
- 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)
- Custom themed shadcn/ui
- Built primarily with Cursor agent (gpt 5.2 + opus 4.5) including using Cursorâs native browser actions to test the app


