修复C语言地牢生成代码的房间重叠与无显示问题
Hey there! Let's dig into why your rooms aren't showing up and fix those overlapping issues once and for all. I spotted several key problems in your code that are causing these issues—let's break them down one by one:
1. makeRoom is modifying a copy, not your actual room array
Right now, your makeRoom function takes a room by value, which means it's working on a copy of the room you pass in. Any changes you make to aRoom inside the function won't affect the original rooms[i] in your array. That's why none of your rooms are getting populated—you're generating data that just gets discarded!
Fix: Change the function to take a pointer to a room instead, so you modify the original struct directly:
void makeRoom(room *aRoom) { int height = (rand() % (10 + 1 - 5)) + 5; int width = (rand() % (15 + 1 - 7)) + 7; // Add boundary checks to keep rooms inside the dungeon int randomY = rand() % (HEIGHT - height); // Ensure room fits vertically int randomX = rand() % (WIDTH - width); // Ensure room fits horizontally aRoom->top_left.y = randomY; aRoom->top_left.x = randomX; aRoom->top_right.y = randomY; aRoom->top_right.x = randomX + width; aRoom->bottom_left.y = randomY + height; aRoom->bottom_left.x = randomX; aRoom->bottom_right.y = randomY + height; aRoom->bottom_right.x = randomX + width; }
And when you call it, pass the address of the room in your array:
makeRoom(&rooms[counter]);
2. Overlap detection logic is broken (both in doOverlap and your placement loop)
First, the doOverlap function has inverted Y-axis logic
Since your dungeon's Y-axis increases downward (top of the terminal is y=0, bottom is y=HEIGHT-1), the condition for non-overlap on the Y-axis is wrong. Right now, your code returns false (no overlap) when l1.y < r2.y—but that's actually a case where rooms might overlap. The correct non-overlap conditions are:
- Room 1 is completely to the right of Room 2:
r1.x < l2.x - Room 1 is completely to the left of Room 2:
l1.x > r2.x - Room 1 is completely below Room 2:
l1.y > r2.y - Room 1 is completely above Room 2:
r1.y < l2.y
If none of these are true, the rooms overlap. Here's the fixed doOverlap:
bool doOverlap(point l1, point r1, point l2, point r2) { // Check if one room is to the left/right of the other if (r1.x < l2.x || l1.x > r2.x) { return false; } // Check if one room is above/below the other if (r1.y < l2.y || l1.y > r2.y) { return false; } // Otherwise, they overlap return true; }
Second, your placement loop only checks against the last placed room
Right now, you're only comparing each new room to rooms[counter], not all rooms you've already placed. That means you could still get overlaps with earlier rooms, and your counter logic is messed up (you increment counter even if the room overlaps).
Fix: Rewrite the loop to keep generating new rooms until you find one that doesn't overlap with any already placed rooms:
void createDungeon() { char dungeonGrid[HEIGHT][WIDTH]; room rooms[N]; int counter = 0; // Initialize dungeon to empty spaces for (int y = 0; y < HEIGHT; y++) { for (int x = 0; x < WIDTH; x++) { dungeonGrid[y][x] = ' '; } } // Generate N non-overlapping rooms while (counter < N) { room newRoom; makeRoom(&newRoom); // Check overlap with all already placed rooms bool overlaps = false; for (int i = 0; i < counter; i++) { if (doOverlap(newRoom.top_left, newRoom.bottom_right, rooms[i].top_left, rooms[i].bottom_right)) { overlaps = true; break; } } // If no overlap, add to the rooms array if (!overlaps) { rooms[counter] = newRoom; counter++; } } // Draw all rooms onto the dungeon grid (optimized version) for (int a = 0; a < N; a++) { for (int y = rooms[a].top_left.y; y <= rooms[a].bottom_left.y; y++) { for (int x = rooms[a].top_left.x; x <= rooms[a].top_right.x; x++) { dungeonGrid[y][x] = '.'; } } } // Print the dungeon for (int y = 0; y < HEIGHT; y++) { for (int x = 0; x < WIDTH; x++) { printf("%c", dungeonGrid[y][x]); } printf("\n"); } }
Notice that we also optimized the grid drawing—instead of checking every grid cell against every room, we directly iterate over each room's area and set the '.' characters. This is way more efficient!
3. Missing boundary checks for room placement
Your original code could generate rooms that go outside the dungeon's bounds (e.g., randomY + height > HEIGHT), which would cause parts of the room to be drawn outside the terminal or even lead to undefined behavior. The fixed makeRoom function adds checks to ensure rooms fit entirely within the dungeon.
Putting it all together
With these fixes, your code should now generate 10 non-overlapping rooms that show up correctly in the terminal. Let me recap the key changes:
- Pass room pointers to
makeRoomto modify the original structs - Fixed the
doOverlaplogic to handle the terminal's Y-axis correctly - Rewrote the placement loop to check against all existing rooms
- Added boundary checks to keep rooms inside the dungeon
- Optimized the grid drawing code
内容的提问来源于stack exchange,提问作者DsDude

