Snake 🐍

The questions below are due on Monday October 12, 2026; 11:59:00 PM.
 
You are not logged in.

Please Log In for full access to the web site.
Note that this link will take you to an external site (https://shimmer.mit.edu) to authenticate, and then you will be redirected back to this page.

Now we're going to take our roaming snake from the lab and turn all this into a game. Open your project from lab3 -- we'll be building on it.

This postlab has 1 checkoff and 1 code file upload. Please make sure to complete these in order to get full credit!

1) Collision Detection

In Snake, there are two things the snake can collide with:

  • food (good)
  • itself (bad)

So, we need to detect these collisions.

1.1) Snake "Collision" with Food (Yum)

On every time-step, we want to check if the snake's movement (implemented in updateSnake()) results in it eating food.

Implement snakeAteFood(), which is defined in main.c. It has two arguments:

  • uint8_t *snake_body: A pointer to the snake's body array.
  • uint8_t food: The variable holding the current location of the food.

The function should compare the coordinates of the snake's head and the food, and:

  • return a 1 if they are the same, indicating that the snake ate the food, or
  • return a 0 if they are not the same.

Once you have that working, copy your implementation and paste it into snakeAteFood() in your code skeleton (in main.c).

If you take a look at the starter code, snakeAteFood() is called from the main loop of your program, after your call to updateSnake().

Two things should happen in your main loop when the snake eats food.

  • Another piece of food should be generated (we implemented this for you).
  • The snake's length should increase by 1.

Update app_main() so that the snake grows if snakeAteFood returns 1. Add your code in the place of the following comment:

// TODO: "Grow" snake

Check Yourself 1: Check Yourself
Now, the snake should grow in length by 1 if it "eats" the food on the board. Test this out for yourself.

1.2) Snake Collision with Itself (Ouch)

One of the two ways a player can lose the game is if the snake collides with itself. As the snake grows in size, this becomes more of a possibility.

Implement snakeCollisionCheck(), which is defined in main.c. It takes 1 argument:

  • struct Snake *snake: The struct representing the snake.

snakeCollisionCheck should:

  1. Compare the location of the snake's head with every other location in the body of the snake.
  2. If any of the locations match, then the function should return 1, indicating that the snake has run into itself. Otherwise, the function should return 0, indicating that all is good.

Once you've got that working, copy over your implementation into the snakeCollisionCheck() in your code skeleton.

Now, if you flash this, your game should work like a normal snake game! Enjoy! :) But we're not done yet.

2) Reset

2.1) pinRead Modification

Before proceeding with this section, we ask that you make a small change to your pinRead function. Open the 6190.h file located in your lab3 src folder and change the following line from:

int *input_val = (int*) GPIO_IN_ADDR;

to:

volatile int *input_val = (volatile int*) GPIO_IN_ADDR;

The rest of your pinRead function (and 6190.h file) should remain unchanged.

We use the volatile keyword in C to stop the compiler from optimizing away accesses to variables it assumes won't change during the current program execution. Declaring input_val as volatile tells the compiler that the value stored at GPIO_IN_ADDR can change without any intervention from our program (which we know to be true since pressing BTNF changes the value stored at GPIO_IN_ADDR without executing any code).

In postlab3, this modification prevents the compiler from optimizing away consecutive calls to pinRead(BTNF) under the false assumption that nothing in the system could change its return value over time 1. So the volatile keyword guarantees that the program will read an updated value from memory every time pinRead is called, hence returning the correct, updated, value when BTNF is pressed.

Once you've implemented the above change, move on to implement the resetting logic described in section 2.2! Feel free to ask course staff if you have any additional questions.

2.2) Reset Logic

Add code to your app_main() function that will restart the game if the user presses BTNF while the game is over.

So pressing BTNF should ONLY reset the game if it is over, and it should do nothing if pressed otherwise.

We must specify where the snake and the food should be when the game restarts.

  • The snake should be (1) length-3, (2) moving to the left, and (3) the snake's head should be at position (5, 3), with the rest of the snake trailing behind it. This is how we initialized the snake to begin with.
  • The food should be randomly generated using generateFood().

3) Choose Your Own Adventure!

Since this is the last C-focused lab for a while, we wanted to give you the opportunity to implement something a bit more open-ended. Choose one of the options from the list below to improve your snake game. Be prepared to (1) explain your approach and implementation and (2) demonstrate that your improvement works as expected.

  1. If the snake travels out-of-bounds, the game should end.
  2. Add a PAUSE button to the game (this will require adding another input to your system).
  3. The snake should move faster each time it eats food (energy!!), and it should move slower on each time-step that it moves and does not eat food (it needs fuel). The game should end if the snake moves slower than once per second.
  4. Keep track of the score throughout the game (feel free to define the score however you would like, as long as it's increasing), then have the score scroll across the LED array at the end of the game. (Optional: to further extend this, keep track of the high score between games).
  5. When the game ends, the snake should decay (one LED should turn off every 200ms) until it's no longer visible.

4) Code Submission

Make sure to submit your main.c and 6190.h files in a zip file named None_postlab3.zip.

To create the zip file, you can select the folders/files you want, right click, and look for the option to compress these files.

Alternatively, you can run one of the following commands in the terminal:

If you're on MacOS or Linux or Command Prompt:

zip None_postlab3.zip src/6190.h src/main.c

or for Windows Powershell users,

Compress-Archive -Path src/main.c,src/6190.h -DestinationPath None_postlab3.zip

Submit your main.c and 6190.h files here as a zip file. Name the file None_postlab3.zip for this assignment.
 No file selected

5) Checkoff

Checkoff:
Show your working snake game (and your improvement to it)! Make sure you implemented the game reset logic as specificied in section 2. Then enjoy the game you worked so hard on!


 
Footnotes

1This wasn't an issue in previous labs/postlabs because of the code infrastructure surrounding button presses, but the issue could arise now depending on your implementation of the game reset logic (to say a little without giving away too much), hence the changes. (click to return to text)