AI memory match game cards: 8 pairs, one style, deck built in code
Make a memory-match deck with the image API: eight subjects in one style via a reference image, then duplicate, shuffle and lay out the deck in Pillow.

A memory-match deck needs eight different pictures in one visual style, each one used twice, plus a single card back. Generate the eight pictures once with the image API, pass the first approved picture as input_references to keep the style, and let code do the rest: duplicate every picture, shuffle, and lay the sheet out in Pillow. The model never has to draw the same animal twice, which is where decks usually look inconsistent.
Pairs have to be pixel-identical to be fair, so duplicating the file is the correct move. Asking a model for two copies produces two near-misses, and a child will spot the difference. This recipe uses a reference for style and code for exact pairs.
Eight subjects, one style anchor
Approve one picture first and call it the anchor. Then request the other seven with the anchor as a reference and a prompt that changes only the subject. GPT Image 2.5 accepts up to 16 references, so there is room to add a second anchor if the style drifts (Sume Image API docs).
Ask for a square image with a plain background and bold shapes, so each picture sits inside a card with room for a border. Keep the style words identical across calls and change only the subject word.
import os, requests
H = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"}
STYLE = "flat children's book illustration, thick outline, soft colors, plain cream background, no text"
def card(subject, anchor_url=None):
body = {"model": "openai/gpt-image-2.5", "aspect_ratio": "1:1", "quality": "medium",
"prompt": f"{subject}, centered. {STYLE}"}
if anchor_url:
body["input_references"] = [{"type": "image_url", "image_url": {"url": anchor_url}}]
body["prompt"] = f"Same style as the reference image. {body['prompt']}"
r = requests.post("https://api.sume.com/v1/images", headers=H, json=body, timeout=120)
r.raise_for_status()
if r.status_code == 202:
raise RuntimeError("queued: poll the job status_url")
return r.json()["data"][0]["url"]
anchor = card("a smiling red fox")
print("anchor:", anchor)
print([card(s, anchor) for s in ("a sleepy owl", "a green frog", "a blue whale")])Duplicate, shuffle, lay out
Once you have eight files, the deck is a data problem. Double the list, shuffle with a fixed seed so you can reproduce a layout, and paste the tiles into a 4 by 4 grid. A card back is drawn once in code: a solid colour with a simple border, which stays crisp at any print size.
The demo below fabricates eight coloured tiles so it runs without the generated files; point paths at your downloads for the real deck.
import random
from PIL import Image, ImageDraw
def deck_sheet(paths, out, cell=256, cols=4, seed=7):
tiles = [Image.open(p).convert("RGB").resize((cell, cell)) for p in paths] * 2
random.Random(seed).shuffle(tiles)
rows = len(tiles) // cols
sheet = Image.new("RGB", (cols * cell, rows * cell), "white")
for i, t in enumerate(tiles):
sheet.paste(t, ((i % cols) * cell, (i // cols) * cell))
sheet.save(out)
back = Image.new("RGB", (cell, cell), "#2f5d8a")
ImageDraw.Draw(back).rectangle([12, 12, cell - 13, cell - 13], outline="#f4e3b2", width=6)
back.save("card-back.png")
return sheet.size
if __name__ == "__main__":
paths = []
for i in range(8):
Image.new("RGB", (300, 300), (30 * i, 255 - 25 * i, 90 + 10 * i)).save(f"t{i}.png")
paths.append(f"t{i}.png")
print(deck_sheet(paths, "deck.png"))Checks before you print
Hold the eight pictures side by side and make sure no two could be confused at card size. A fox and a red dog will be, so choose subjects that differ in shape and colour. Print one test sheet before ordering a deck.
For keeping a style across a set of images, see one anchor icon, then references. For a sheet of variants from a single call, see the contact sheet recipe.
Sources
Related posts
More in Use cases
- AI postcard via API: 3:2 front art, address side drawn in code
Make a postcard front at 3:2 with GPT Image 2.5 custom pixels, then draw the back with message, address lines and a stamp box in Pillow. Code runs as written.
- AI shopping referrals up 693%: a Sume output schema for listing copy
Adobe data in KTVZ has AI referrals to US retail up 693.4% in Nov-Dec 2025. Bind a headline, hero image and alt-text schema so each video returns typed JSON.
- Four shoppable videos per ASIN: demo, how-to, lifestyle, unboxing
Amazon allows up to 4 shoppable videos per ASIN for sellers with a professional account and three months of history. A four-clip plan batched on Sume.
- Amazon allows four shoppable videos per ASIN: eligibility and plan
Amazon allows up to four shoppable videos per ASIN for professional sellers with three months of history. A demo, how-to, lifestyle and unboxing plan.
Written by Sume