Building SetCardGame: A New Take on Classic Set With Modern Cloud Architecture
Welcome to an in-depth exploration of my project, SetCardGame—a fresh take on a card game, powered by a next-generation serverless architecture.
🃏 The Game: Rules at a Glance
- Objective: Minimize your points.
- Dealing: Each player gets 6 cards, the dealer gets 7 and goes first.
- Card Values:
- 2–10: face value
- J/Q/K: 10 points
- Ace: 1 point
- Sets:
- Same Number: 3+ cards of any suit
- Series, Same Suit: 3+ sequential cards of one suit
- Turns:
- Draw from deck or discard pile (top)
- Max hand size is 6
- Round End:
- If your hand is ≤5 points, you may close the round—all reveal cards.
- Others can make additional sets from revealed cards to reduce points.
- Elimination:
- Go over 52 points over rounds and you’re out.
- Last player standing wins.
🏗️ Architecture: Why SetCardGame Is Uniquely Modern
1. Cloud-Enabled, Not Dependent
SetCardGame uses AWS Lambda or an equivalent only as a relay—never as the authority on game state. Clients sync between each other; infra can be swapped or scaled painlessly.
// Pseudocode: Lambda relay handler
exports.handler = async (event) => {
forwardToRoom(event.roomId, event.message, event.userId);
};
// Each move references prior state hash
type Move = {
previousHash: string;
action: string; // e.g. "draw", "play set"
player: string;
payload: object;
timestamp: number;
};
function makeMove(prevHash, action, player, payload) {
const move = { previousHash: prevHash, action, player, payload, timestamp: Date.now() };
move.hash = computeHash(move);
return move;
}
Clients cross-validate all moves in the log.
3. No Database, No Backend Lock-In
The entire game state is determined from a move log (array of moves). No DB to migrate or maintain—you can switch cloud providers at will.
Client A <-> Relay <-> Client B
4. Sync, Replay, Recovery Baked In
If you drop a connection, simply reload the move log and replay moves to restore the game.
function computeGameStateFromMoves(moves) {
let state = initGameState();
for (const move of moves) {
state = applyMove(state, move);
}
return state;
}
5. Elegant Startup: Seeded Deck
Game creator generates a random seed and shares it with all players (in the first move).
Everyone shuffles the deck using the deterministic seed.
// Pseudocode: Creating/reproducing a shuffled deck
function createDeck(seed) {
const deck = allCards();
const rng = seededRandom(seed);
return shuffle(deck, rng);
}