Inside Shopee Candy: Building a Scalable Match‑3 H5 Game Architecture
This article walks through the origin, architecture, and tooling of Shopee Candy, a multi‑region match‑3 H5 game, detailing the Algorithm SDK, animation system, map editor, score runner, replayer, and future plans for configurability, performance, anti‑cheat, and AI‑driven level design.
Project Overview
Shopee Candy is a multi‑region casual H5 match‑3 game that rewards players with platform coins and coupons. The game limits the number of moves per level and generates special elements based on elimination patterns. It launched in June 2020 on iOS and Android.
System Architecture
Algorithm SDK
The Algorithm SDK encapsulates all core elimination logic, scoring and level progression, and is completely decoupled from the animation and business layers.
Map
Manages level maps and element objects in three layers (top, middle, bottom) so that new special elements can be added without breaking existing logic.
export default class Grid {
public middle: CellModel;
public upper: Upper;
public bottom: Bottom;
constructor(info: ICellInfo) {
const { type } = info;
this.upper = new Upper(/* ... */);
this.middle = new CellModel(/* ... */);
this.bottom = new Bottom(/* ... */);
}
}Operator
Acts as the bridge between external input (swap, double‑click) and the algorithm, converting user actions into IAnimationData for the animation system.
// Element swap
export function exchange(startPos, endPos): IAnimationData {
// ...logic process
// returns animation data
}
// Element double‑click
export function doubleClick(pos): IAnimationData {
// ...logic process
// returns animation data
}Logic Processing
Performs solvability checks, elimination, drop calculations and other core operations. To avoid frame drops during intensive loops, the logic is split into asynchronous segments and data is sent to the animation system ahead of time.
Unit Testing
Because the algorithm library is isolated, it can be unit‑tested without UI. Tests verify that identical board states produce the same score, element counts and step counts regardless of operation order.
describe('BOMB', () => {
it('Exchange each other should be the same crush', () => {
const source = { row: 0, col: 3 };
const target = { row: 1, col: 3 };
const wrapper = mapDecorator(operator);
const data1 = wrapper({ key: CRUSH_TYPE.BOMB }, source, target);
const data2 = wrapper({ key: CRUSH_TYPE.BOMB }, target, source);
expect(JSON.stringify(data1.map)).to.equal(JSON.stringify(data2.map));
expect(data1.score).to.equal(data2.score).to.equal(150);
expect(data1.passStep).to.equal(data2.passStep).to.equal(14);
});
});Animation System
Separating animation from the algorithm yields high cohesion, low coupling, improved efficiency and flexibility (e.g., bonus skipping).
High cohesion, low coupling
High efficiency
High flexibility
Design
Algorithm emits animation data which is placed into a queue and processed recursively until empty. A Strategy pattern selects the appropriate animation handler based on element type.
const animStrategyCfg = new Map([
[AElement, AStrategy],
[BElement, BStrategy],
[CElement, CStrategy],
]);
function getStrategy(elementType) {
return animStrategyCfg.get(elementType);
}
function executeStrategy(elementType) {
const strategy = getStrategy(elementType);
return strategy.execute();
}Promise‑based animation methods replace nested callbacks, allowing clear async/await flow.
async function animation() {
await tweenA.promise();
await tweenB.promise();
await tweenC.promise();
await sleep.promise();
}Development Tools
Map Editor
Provides drag‑and‑drop level configuration with keyboard shortcuts. Enforces element coexistence rules (mutual, exclusive, global exclusive) via a relationship table fetched from the server.
Score Runner
Automates difficulty testing by constructing a graph of all possible player actions, traversing it to compute maximum and minimum possible scores. A “smartness” strategy prunes low‑value branches, improving performance.
Statistical analysis of average pass rates across thousands of levels reduces manual validation time for level designers.
Replayer
Records random seeds to enable deterministic replay of Score Runner simulations, supporting verification of algorithm correctness, reconnection handling and post‑mortem analysis with minimal storage.
Future Directions
Configurable development for new elements to lower implementation cost.
Performance optimizations for low‑end devices.
Operation‑behavior verification services to prevent cheating.
Machine‑learning models trained on Score Runner data to auto‑generate levels.
Shopee Tech Team
How to innovate and solve technical challenges in diverse, complex overseas scenarios? The Shopee Tech Team will explore cutting‑edge technology concepts and applications with you.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
