4-B: 2048
Learning Targets
I can create and initialize 2D arrays of primitives.
I can traverse 2D arrays using nested loops in both row-major and column-major order.
I can implement algorithms that operate on entire rows or columns.
I can manipulate array contents by shifting, merging, or transforming values.
From Pictures to Grids
In the PicLab project, you worked with 2D arrays of Pixel objects to manipulate images. Each pixel had a location (row, column) and properties like color. Now we're going to work with 2D arrays of primitives—specifically integers—to represent game boards, data tables, and other grid-based structures.
The concepts are similar:
PicLab: A 2D array where each cell holds a Pixel object
Grid games: A 2D array where each cell holds an integer representing game state
The difference? Instead of calling methods on Pixel objects, we'll be performing calculations and comparisons directly on integer values.
Understanding 2D Arrays
A 2D array is like a table with rows and columns. Think of a classroom seating chart, a chess board, or a spreadsheet—any time you have data organized in a grid, a 2D array is a natural fit.
Declaration and Initialization
Here's how you create a 2D array:
// Create a 4x4 grid of integers, all initialized to 0
int[][] grid = new int[4][4];
// You can also initialize with values
int[][] scores = {
{90, 85, 88, 92},
{78, 91, 84, 87},
{95, 89, 93, 90}
};Important terminology:
grid.lengthgives you the number of rows (3 in the scores example)grid[0].lengthgives you the number of columns (4 in the scores example)grid[row][col]accesses the element at that position
Visualizing 2D Arrays
Let's say you have this array:
To access the value 30, you'd use numbers[2][3].
Think of it this way: The first index is "which row?" and the second index is "which seat in that row?"
Traversing 2D Arrays
The most fundamental skill with 2D arrays is visiting every cell. You do this with nested loops.
Row-Major Traversal
This is the most common pattern—go through each row, and for each row, visit every column:
Pattern: Outer loop controls rows, inner loop controls columns.
Column-Major Traversal
Sometimes you need to process by columns instead. For example, finding the highest score in each subject:
Pattern: Outer loop controls columns, inner loop controls rows.
This is crucial: Notice how the indices swap. When traversing by column, scores[row][col] still uses row first, but your outer loop is the column counter.
Common 2D Array Patterns
Finding Values
Let's say you want to find if a specific value exists in the grid:
Or find the location of the maximum value:
Collecting Matching Cells
Sometimes you need to find all cells that meet certain criteria. For example, finding all empty cells in a game board:
Pattern: Use an ArrayList to accumulate results, storing coordinates as int[] arrays.
Operating on Rows vs Columns
Many grid-based algorithms need to process entire rows or columns as units. This is where things get interesting.
Processing a Single Row
Let's say you want to shift all non-zero values in a row to the left:
Example: [0, 3, 0, 5, 0, 2] becomes [3, 5, 2, 0, 0, 0]
Processing a Single Column
The same operation on a column requires careful index management:
Notice the difference: When working with rows, col changes but row is fixed. When working with columns, row changes but col is fixed.
Processing All Rows or Columns
Once you can process a single row or column, you can loop through all of them:
Advanced Pattern: Merging Adjacent Values
A common requirement in grid games is merging adjacent equal values. Here's how you might merge adjacent matching numbers in a row:
Example: [2, 2, 4, 4, 0, 0] becomes [4, 8, 0, 0, 0, 0]
This pattern of compress → process → compress is very common in grid manipulation algorithms.
Putting It All Together
When working with 2D arrays in games or simulations, you typically:
Initialize the grid with starting values
Implement row/column operations as helper methods
Apply operations based on user input or game rules
Check win/loss conditions by traversing the grid
Update display by traversing and rendering
The key skills are:
Traversing correctly (row-major vs column-major)
Keeping indices straight (row first, then column)
Operating on rows vs columns (which index is fixed?)
Using helper methods to break complex operations into steps
2048 Project
You're now ready to build a fully functional 2048 game! In this project, you'll:
Manage a 4x4 grid of integers representing tiles
Implement sliding and merging logic for all four directions (up, down, left, right)
Add random tiles after each move
Check for win conditions (reaching 2048) and game over (no valid moves)
Handle complex array manipulation with multiple passes
The game combines everything you've learned about 2D arrays:
Creating and initializing grids
Traversing by rows and columns
Operating on entire rows or columns
Checking conditions across the board
Modifying arrays in place
You'll get a GitHub Classroom link to set up the project. The repository includes a complete game GUI, and your job is to implement the core game logic. The README provides detailed guidance on each method you need to write, along with the algorithms and patterns to use.
This is one of the most satisfying projects in the course—when your move methods work correctly and you see the tiles sliding and merging on screen, you'll have built a real, playable game using fundamental CS concepts!
Good luck! 🎮
Last updated
Was this helpful?