Free Pascal退出码201含义及贪吃蛇游戏异常退出问题排查
Hey there! Let's tackle this exit code 201 issue first—in Free Pascal, exit code 201 is a Range Check Error. This means your program is trying to access a value outside the allowed range of a variable or array (like accessing an array index that doesn't exist). Let's walk through the problems in your code and fix them step by step.
Key Issues Causing the Crash
1. Uninitialized l (Snake Length) Variable
Your l variable (which tracks the snake's length) is declared but never given an initial value. In Pascal, uninitialized variables hold random garbage values. When your game starts, if l is 0 (a common random value for uninitialized bytes), movement procedures like up/down will try to access s[0]—but your snake array s is defined as array[1..1000] of ran, so index 0 is out of bounds. This directly triggers the 201 error when you press a key.
2. Flawed Self-Collision Check in die Function
Right now, your collision check only runs if the snake is at least 5 segments long, and only checks segments 5 to l. This means the snake can collide with its own segments 2-4 without dying, and the logic will fail if l is less than 5 (or uninitialized).
3. Unreliable Initial Key Handling
In the first procedure, you only set k if a key is pressed at startup. If the user doesn't press a key immediately, k remains uninitialized, and calling ingame(k) will pass a random value to auto(), leading to unexpected behavior or crashes.
4. Double Movement in ingame Procedure
Your current ingame logic moves the snake repeatedly until a key is pressed, then moves it again after reading the key. This creates inconsistent movement speed and can lead to unexpected collisions.
Fixes to Apply
1. Initialize the Snake Length
Add an initial value for l to ensure it starts at 1 (since the snake begins with one segment). You can do this in the first procedure:
procedure first; var k:integer; begin l := 1; // Initialize snake length to 1 draw; fa1; sts; // Wait for the user's first key press instead of skipping it while not keypressed do; k:=getkey; ingame(k); end;
2. Fix the Self-Collision Check
Update the die function to check for collisions with all body segments once the snake is longer than 1 segment:
function die:boolean; begin die:=false; // Check wall collision (unchanged) if (s[1].x=1) or (s[1].x=100) or (s[1].y=1) or (s[1].y=25) then die:=true; // Check collision with any body segment (starting from segment 2) if l>=2 then for i:=2 to l do if (s[1].x=s[i].x) and (s[1].y=s[i].y) then die:=true; end;
3. Refactor the ingame Procedure for Smooth Movement
Rewrite ingame to handle direction changes and movement consistently, plus add a small delay to control the snake's speed:
procedure ingame(var t:integer); // Use var to update direction across loops var d:boolean; begin repeat // Check for new key presses to change direction if keypressed then t:=getkey; // Move snake in the current direction auto(t); // Check if snake died d:=die; if d then break; // Check if snake ate food eat; // Add delay to slow down movement (adjust value to change speed) delay(100); until d; end;
4. Optional: Add Range Checks (For Debugging)
If you want to catch these issues earlier, you can enable range checking in Free Pascal by adding the -Cr compiler flag. This will give you more detailed error messages about where the out-of-bounds access is happening.
Why These Fixes Work
- Initializing
lensures you never access invalid array indices likes[0]. - The updated collision check properly handles all snake lengths and prevents self-collision bugs.
- The refactored
ingameprocedure creates smooth, consistent movement and properly handles direction changes. - Waiting for the first key press eliminates uninitialized
kvalues at startup.
After applying these changes, your game should no longer crash with exit code 201, and the core gameplay will work as expected.
内容的提问来源于stack exchange,提问作者Nam Anh

