How to implement circular buffers and infinite scrolling without "Index Out of Bounds" errors.
One of the most common patterns in game development and systems programming is the "Circular Array" (or Ring Buffer).
You see this everywhere:
- Carousels: Clicking "Previous" on the first image shows the last image.
- Game Maps: Pac-Man exiting the left side of the screen and appearing on the right.
- Data Streams: Overwriting old data in a fixed-size audio buffer.
The most efficient way to handle this is using Modular Arithmetic. However, if you are moving between Python and C-style languages (C, C++, Java, C#), there is a trap waiting for you.
Here is how to wrap arrays efficiently and safely.
The Concept: The Infinite Loop
Imagine you have an array of 5 items.
['A', 'B', 'C', 'D', 'E']
Indices: 0, 1, 2, 3, 4We want to treat this array as a circle. If we are at index 4 and move right (increment), we should arrive at 0. If we are at 0 and move left (decrement), we should arrive at 4.
The Naive Approach (Conditional Checks)
A beginner might write this using if statements:
// Moving Right
index++;
if (index >= 5) {
index = 0;
}
// Moving Left
index--;
if (index < 0) {
index = 4;
}Why this is suboptimal: It introduces "branching" (if/else logic) which can be slower on low-level hardware, and it is verbose. It gets even messier if you want to jump multiple steps at once (e.g., index - 50).
The Better Approach: Modular Arithmetic
Instead of checking bounds, we can use the modulo operator (%) to mathematically constrain the index within the array size.
Moving Forward (Positive Steps)
Moving forward is easy in almost every language:
// Current index is 4 (the end)
// Move forward 1 step
next_index = (4 + 1) % 5;
// Result: 0 (Correct)Moving Backward (The Trap)
If we want to move backward from 0, the math changes depending on your language.
In Python:
# Python
prev_index = (0 - 1) % 5
# Result: 4 (Correct - wraps to the end)In C, Java, or C#:
// C / Java
int prev_index = (0 - 1) % 5;
// Result: -1 (CRASH - Index out of bounds)This happens because C uses "Truncated Division" (rounding toward 0), which preserves the negative sign. Python uses "Floored Division" (rounding down), which wraps the value.
The Universal Formula
To implement robust, error-free array wrapping in C-style languages, you need a formula that handles negative numbers correctly.
You cannot rely on % alone. You must use this standard idiom:
int wrap_index(int index, int size) {
return ((index % size) + size) % size;
}How it Works
Let's trace wrap_index(-1, 5):
index % size→-1 % 5= -1 (The raw negative remainder).+ size→-1 + 5= 4 (Lifts it into the positive range).% size→4 % 5= 4 (Keeps positive numbers inside bounds).
This works for any input. If you jump back 50 steps (-50), the formula will correctly wrap it around the circle multiple times and land on the correct valid index.
Summary
When implementing circular logic:
- Avoid
if/elsechecks for wrapping; they are brittle. - Use Modulo (
%) for efficiency. - Beware of Negative Numbers in C/Java/C#.
- Use the formula
((i % n) + n) % nto ensure you never get a negative index.