In this article
  1. Before you start
  2. Why interviewers ask this
  3. Object-oriented game simulation from first principles
  4. Worked example
  5. Trade-offs and edge cases
  6. How to answer it in an interview
  7. Common mistakes
  8. Follow-up questions
  9. Sources

Before you start

Machine coding rounds, where a design-and-code task must run in one sitting, are where this shape appears; the machine coding rounds guide covers them.

Why interviewers ask this

A prompt such as "build a control system for managing aircraft takeoffs and landings at a busy airport" is reported by candidates, as are card games with Player, Card and Deck classes, Connect 4, a snake game and an infection spread. No public source says which company asks which, so treat them as examples of one shape: a small world, several kinds of thing, and rules that play out over time.

The interviewer is checking whether you can turn a vague story into classes, give each class one job, and keep the rules testable. A weak answer writes one long function with global lists. A strong answer names the objects, separates the loop from the rules, and says how the run can be repeated exactly. A Staff-level answer also names the trade-off: where a rule belongs, and what starves under it. The same habits are tested in low level design interview questions.

Object-oriented game simulation from first principles

Game loop
A game loop is a piece of code that runs again and again for as long as the simulation lasts, and on each turn advances every object in the world by one small slice of time before the next turn begins.
Tick
A tick is one turn of the game loop, treated as one indivisible unit of simulated time, so "three ticks" means three turns whatever the clock on the wall says.
Entity
An entity is an object in the simulated world that holds its own state and changes over time, such as an aircraft, a runway or a card player.

In plain words

Picture a board game played by a referee. The referee does not move the pieces by hand; each turn they say "everyone take your move," and each piece follows its own rules. The simulation is that referee, and every entity is a piece that knows how to move itself. The analogy breaks in one place. A real referee can glance at the whole board, but an object should ask only the objects it needs.

In one precise sentence, an object-oriented simulation is a collection of entities, each with state and an update method, advanced together by a loop that counts ticks. Robert Nystrom's game programming book says the loop's job is to "Decouple the progression of game time from user input and processor speed." For an interview, you need no screen at all: a loop that prints state is enough.

Step 1: Name the nouns as classes

Read the prompt and underline the nouns. For the airport, they are Aircraft, Runway and Airport. Each noun becomes a class that owns its data. An Aircraft holds an identifier, the tick it asked to land, whether it is urgent and its state: queued, landing or done. A Runway holds what it is serving and the tick when it becomes free. The Airport owns the runways and the waiting line.

Input: the problem statement. Output: a short list of classes and what each one stores. Say the rule out loud: data lives on the object that the data describes. You now know what exists in the world; the next step makes it move.

Step 2: Give each object an update method and run a tick loop

Each entity gets an update(tick) method that changes only its own state. A runway checks whether its current aircraft has finished and, if so, frees itself. The loop is a plain for over ticks: create arrivals, then call update on the airport, which calls it on each runway and hands free runways the next waiting aircraft.

Input: the current tick number. Output: changed state, never a return value you must collect. Because simulated time is a counter, the run does not depend on how fast the computer is, which is the point Nystrom makes about processor speed. Keep the order inside a tick fixed, such as arrivals, then updates, so two runs can be compared.

Step 3: Decide who acts next: the ordering rule

An ordering rule decides who acts or is served next, and every simulation needs exactly one fixed rule. In a card game or Connect 4 it is turn order, a rotating index over the players. In Snake or an infection spread it is a fixed update order over the entities. When some entities are more urgent than others, as in the airport, it is a priority queue.

A priority queue is a collection that always hands back its smallest item first, so the "smallest" key encodes who is served next. For the airport, Python's heapq module provides this on top of an ordinary list. Push a tuple whose first element is the urgency class (zero for urgent, one for routine) and whose second is an arrival counter. Urgent aircraft sort ahead, and equal urgency falls back to arrival order.

Input: an aircraft and its key. Output: the next aircraft to serve. The arrival counter matters: without it, two equal keys force the heap to compare aircraft objects, which raises an error. Step 4 fixes the last gap, repeatability.

Step 4: Seed the randomness so a run can be replayed

Arrivals are random, and a random run you cannot repeat is a run you cannot test. Create one random.Random(seed) object and pass it into the simulation. The Python documentation for the random module describes seed as initializing the generator, so the same seed gives the same sequence. A seeded generator makes every run repeatable. The same documentation says most seeding algorithms may change across Python versions while random() keeps its sequence for a given seed, so pin the Python version if replays must hold across machines. Never call the global generator from inside entities.

Input: a seed number. Output: an identical run each time. The check is easy to write: run the simulation twice with the same seed and compare the results, which is also the strongest test of the whole design. Event ordering of this kind returns in event and log processing problems.

Four steps turn a story into a repeatable simulationRow flow of four stages: classes name the objects, a tick loop updates them, an ordering rule decides who acts next, and a seeded random source makes every run repeatable.ClassesAircraft,RunwayTick loopupdate eachobjectOrdering ruleturns or prioritySeedsame run againDiagram: Interview Clozo, CC BY 4.0 ·interview.clozo.ai/blog/object-oriented-game-simulations.html

Four steps build the whole simulation: objects, a tick loop, an ordering rule and a seeded random source.CC BY 4.0 — source: Object-oriented game simulations, step by step: an airport example
Step-by-step description
  1. Nouns become classes that own their state.
  2. The loop calls each update method.
  3. Turn order or urgency decides who acts next.
  4. A seeded generator makes runs repeatable.
  • Classes name the objects, and each object owns its own state.
  • A tick loop calls the update method of each object.
  • An ordering rule decides who acts or is served next.
  • A seeded generator makes every run repeatable.

Knowing it is half the job. Saying it is the other half.

Interview Clozo is an AI interview copilot for real interview rounds: it hears the question and puts a strong answer on your screen, and you say it in your own words. See the features or how it works.

Start Free Trial →

Worked example

The airport below is illustrative: each tick, one aircraft asks to land with probability 0.3, one request in ten is urgent, a landing occupies a runway for three ticks, and the run lasts 600 ticks with seed 7.1 The core of the code is short.

import heapq, random

class Airport:
    def __init__(self, runways, use_priority):
        self.runways = [Runway() for _ in range(runways)]
        self.queue, self.seq = [], 0
        self.use_priority = use_priority

    def request(self, plane):
        urgency = 0 if (plane.urgent and self.use_priority) else 1
        heapq.heappush(self.queue, ((urgency, self.seq), plane))
        self.seq += 1

    def update(self, tick):
        for r in self.runways:
            r.update(tick)                  # free itself when finished
        for r in self.runways:
            if r.current is None and self.queue:
                _, plane = heapq.heappop(self.queue)
                r.assign(plane, tick)
One runway with urgent-first ordering cuts an urgent aircraft's average wait from 14.43 to 1.12 ticks, while a second runway cuts it to 0.12.
Setup (illustrative, 600 ticks, seed 7)Average wait, allAverage wait, urgentLongest queue
One runway, first come first served14.49 ticks14.43 ticks12
One runway, urgent first14.40 ticks1.12 ticks12
Two runways, first come first served0.14 ticks0.12 ticks1

All three runs saw 202 arrivals.1 Urgent-first order cuts an urgent aircraft's average wait to 1.12 ticks.1 With one runway, arrivals every 3.33 ticks on average meet a three-tick service: the runway is busy 90% of the time (0.3 × 3 = 0.9),1 so long lines form. Priority ordering barely changes the overall average, 14.49 against 14.40, because the total work is unchanged: it moves waiting from urgent aircraft onto routine ones. A second runway removes most waiting. Repeating the one-runway run with the same seed gave identical results, and seed 8 gave a different run: 154 arrivals and an average wait of 3.59 ticks.1

Urgent-first ordering cuts an emergency wait to about one tickBar chart of the average wait of an urgent aircraft in a 600-tick simulation: 14.43 ticks with one runway and first-come order, 1.12 with urgent-first order, and 0.12 with two runways.Average urgent wait (ticks)0510151 rwy FIFO1 rwy urgent2 rwy FIFOSetup14.431.120.12Diagram: Interview Clozo, CC BY 4.0 ·interview.clozo.ai/blog/object-oriented-game-simulations.html
Ordering the queue by urgency cuts an emergency's wait from 14.43 to 1.12 ticks without adding a runway.CC BY 4.0 — source: Object-oriented game simulations, step by step: an airport example
Text description of the diagram
  • An urgent aircraft waits 14.43 ticks with one runway and first-come order.
  • Urgent-first order cuts an urgent aircraft's average wait to 1.12 ticks.
  • Two runways cut an urgent aircraft's average wait to 0.12 ticks.

Trade-offs and edge cases

Priority ordering can starve routine aircraft: if urgent requests keep arriving, the routine ones wait without limit. Fix it by raising an aircraft's priority as its wait grows, or by capping the number of consecutive urgent services. Say the risk aloud before the interviewer does.

Update in place or into a new buffer is a further choice. In a grid simulation such as an infection spread or the Game of Life, writing the next state into the grid you are reading lets one change spread several cells in a single tick, so the result depends on loop order. Compute the next state into a second grid and swap the two at the end of the tick (double buffering).

Inheritance versus composition is the other common fork. A Boeing subclass of Aircraft fixes behavior when the object is created. Composition, where an aircraft holds a movement part or a state object, lets you swap behavior while it runs. Keep inheritance shallow.

Composition swaps behavior at runtime, inheritance fixes it at creationTable comparing inheritance and composition for simulation entities by when behavior is chosen, how code is shared and the main risk.QuestionInheritanceCompositionWhen is behaviorchosenAt creationAny timeHow code is sharedParent classSmall partsMain riskDeep class treesMore wiringDiagram: Interview Clozo, CC BY 4.0 ·interview.clozo.ai/blog/object-oriented-game-simulations.html
Composition changes behavior by swapping a part at runtime; inheritance fixes it when the object is created.CC BY 4.0 — source: Object-oriented game simulations, step by step: an airport example
Text description of the diagram
  • Inheritance fixes behavior when the object is created.
  • Composition lets you swap a part while it runs.

Other edge cases: two events in the same tick need a fixed order; an aircraft that is landing must not be re-queued; takeoffs share the runway resource and can use the same queue with a different state; and a variable real-time step makes runs differ between machines, which a counted tick avoids. For a data-structure-heavy variant of the same discipline, see the in-memory database assessment and the least recently used (LRU) cache in Python.

How to answer it in an interview

Interviewer asks

How would you build a control system for aircraft takeoffs and landings?

A strong answer

I start by naming the nouns: Aircraft, Runway and Airport, each a class that owns its own state. The airport owns a priority queue of waiting aircraft and a loop that advances time in ticks. Each tick, every runway updates itself, then free runways take the next aircraft. I order the queue by urgency first and arrival order second, so an emergency does not wait behind routine traffic. I pass in a seeded random generator so a test can replay a run exactly. The trade-off is that urgent traffic can starve routine flights, so I would cap anyone's wait.

The spoken structure: name the classes, describe one tick, state the ordering rule, then give the testing and starvation points.

Common mistakes

  • "I'll keep every aircraft in one big list and loop over it with if statements." (wrong) That hides the rules in one place nobody can test. (right) "Each class owns its state and an update method; the loop only calls them."
  • "I'll draw the runway on screen first." (wrong) Rendering is not the problem being tested. (right) "A headless loop that prints state each tick is enough to show the design."
  • "Arrivals use the global random function." (wrong) The run cannot be replayed. (right) "I inject a seeded random.Random and test that the same seed gives the same result."
  • "A normal queue is fine." (wrong) Urgent aircraft wait behind everyone. (right) "I use a priority queue keyed by urgency, then arrival counter."

Follow-up questions

How do you build a control system for managing aircraft takeoffs and landings at a busy airport?

Model Aircraft, Runway and Airport as classes, run a tick loop, and give the airport a priority queue of waiting aircraft. Add a state field (queued, landing, taxiing, done) so each aircraft knows what it may do next.

How do you make a simulation repeatable so you can test it?

Count time in ticks, fix the order of work inside a tick, and use one seeded random generator passed into the simulation. Then compare two runs with the same seed.

How would you simulate a card game with Player, Card and Deck classes?

Give Deck a seeded shuffle, give Player a hand and a play_turn method, and let a Game object loop over rounds until a winning condition holds. The structure is the same as the airport: objects own state, one loop advances them.

How do you stop low-priority objects from waiting forever?

Age them: raise a waiting object's priority with each tick it waits, or limit consecutive high-priority services. Name the policy and say what it costs the urgent objects.

How would you implement Connect 4?

Write a Board class with a 6×7 grid and a drop(col) method that returns the row where the piece lands. After each drop, check for four in a row by scanning the four directions (horizontal, vertical and both diagonals) from the last move only. A turn-order index over the two players is the ordering rule.

Which data structure would you use for a Snake game?

Use a deque for the body, so each move pushes the new head and pops the tail in O(1) time, plus a set of occupied cells so a self-collision check is O(1). When the snake eats, skip the tail pop for that tick. A fixed update order (move, then check collision, then spawn food) is the ordering rule.

Key takeaways
  • An object-oriented game simulation is entities with state and update methods, advanced by a tick loop.
  • Name the nouns as classes and keep each object's data on that object.
  • One fixed ordering rule decides who acts next: turn order, update order, or a priority queue keyed by urgency then arrival counter.
  • Seed one random generator and pass it in so every run can be replayed.
  • Priority moves waiting around; only more capacity or less work removes it.

Sources

  1. Game Loop, Game Programming Patterns — Robert Nystrom (gameprogrammingpatterns.com), 26 Oct 2026
  2. heapq: Heap queue algorithm, Python documentation — Python Software Foundation, 26 Oct 2026
  3. random: Generate pseudo-random numbers, Python documentation — Python Software Foundation, 26 Oct 2026