Disclaimer:
I am not a VBA expert and some portions of this code may not follow the standard coding practices. It is what it is.
Assumptions:
I assume you have some experience with Excel VBA and its infrastructure (how to view project, general knowledge of the coding syntax etc…)
Credits:
Ken, Developer of Excel Snake Game | Snake Game Video | Reddit Source
Other Notes:
I don’t plan to explain everything about this game (as it would just be too long). I hope to provide a sequence of events in order to help you replicate it and improve on it further for your interest and knowledge.
The entire game is free for download from this link. The gameplay can be viewed from this link
I would never have imagined creating this game without viewing Ken’s Excel Snake game. If you guys have not seen his game I highly recommend looking at it (it’s brilliant!).
I directly copied two key components from his Snake game which I modified to suit this game (oh no!). The two components are the key press actions (using the left, right, up and down arrow keys) and the timer function (controlled time loops). These two components essentially make up this game and can be used to re-create any video game which involves motion/movement. These 2 components have already been explained in this video hence I will not focus on them.
As per all my articles I will first breakdown this game into their individual components, and then describe each component as best as I can.
The breakdown of the game is as follows;
Game Setup
- Generating a random map & position to start from
Game Play
- Maneuvering the vehicle using Left & Right arrow keys
- Speeding Up & Slowing down using the Up & Down arrow keys
- Hitting Traffic & Hitting the Bonus Car
- Generating Traffic
- Generating the Bonus Yellow Car
- Increase speed as score increases
Game Setup
Generating a random map & position to start from
This is a fairly straightforward step. I have set up 4 random traffic variations as seen in the image below

When “New Game” is selected, a random number between 1 and 4 is generated in order to select which variation to use. This is simply pasted on the game play area. The position of the Player’s vehicle is made an ActiveCell and the countdown begins. This code can be viewed by selecting “Module1” and subroutine “New Game”. This code can be seen below;
Randomize
StartPos = Int(1 + Rnd * (4 - 1 + 1))
If StartPos = 1 Then
Range("W4:AC37").Copy
Current = 1
ElseIf StartPos = 2 Then
Range("AE4:AK37").Copy
Current = 2
ElseIf StartPos = 3 Then
Range("AM4:AS37").Copy
Current = 2
ElseIf StartPos = 4 Then
Range("AU4:BA37").Copy
Current = 1
End If
Range("D4").PasteSpecial
Application.CutCopyMode = False
Range("Q13") = 0
NextPos = Int((2 - 1 + 1) * Rnd + 1)
If StartPos = 1 Then
Range("E34").Select
ElseIf StartPos = 2 Then
Range("I34").Select
ElseIf StartPos = 3 Then
Range("E34").Select
ElseIf StartPos = 4 Then
Range("I34").Select
End If
Game Play
We can now move to the next subroutine, “Movement”. The following three section are grouped together in a single code below.
- Maneuvering the vehicle using the Left & Right arrow key
- Speed Up & Slowing Down
- Hitting Traffic & Hitting Bonus Car
If ActiveCell.Offset(-1, 0).Interior.Color = RGB(0, 0, 0) Then
If Range("Q9") > Range("Q13") Then
MsgBox ("Oh No! You Crashed!" & vbNewLine & vbNewLine & "Your final score is: " & Range("Q13")), vbInformation
Else
MsgBox ("Wow!, New High Score!" & vbNewLine & vbNewLine & "Your final score is: " & Range("Q13")), vbInformation
Range("Q9") = Range("Q13")
End If
End
ElseIf ActiveCell.Offset(-1, 0).Interior.Color = RGB(255, 215, 100) Then
Range("Q13") = Range("Q13") + 50
Range(ActiveCell.Offset(-3, -1), ActiveCell.Offset(-1, 1)).Interior.Color = RGB(255, 255, 255)
Else
TimerMax = Timer() + TimeDelay
Do While Timer() < TimerMax
If GetAsyncKeyState(vbKeyLeft) = KeyPressed Then
If ActiveCell.Column = 9 Then
Sleep 2
If Range("E34").Interior.Color = RGB(0, 0, 0) Or Range("E35").Interior.Color = RGB(0, 0, 0) _
Or Range("E33").Interior.Color = RGB(0, 0, 0) Then
Range("H34:J37").Cut Destination:=Range("D34")
Range("E34").Select
If Range("Q9") > Range("Q13") Then
MsgBox ("Oh No! You Crashed!" & vbNewLine & vbNewLine & "Your final score is: " & Range("Q13")), vbInformation
Else
MsgBox ("Wow!, New High Score!" & vbNewLine & vbNewLine & "Your final score is: " & Range("Q13")), vbInformation
Range("Q9") = Range("Q13")
End If
End
ElseIf Range("E34").Interior.Color = RGB(255, 215, 100) Or Range("E35").Interior.Color = RGB(255, 215, 100) _
Or Range("E33").Interior.Color = RGB(255, 215, 100) Then
Range("D32:F35").Interior.Color = RGB(255, 255, 255)
If Range("E31").Interior.Color = RGB(255, 215, 100) Then
Range("D31:F31").Interior.Color = RGB(255, 255, 255)
End If
Range("H34:J37").Cut Destination:=Range("D34")
Range("E34").Select
Range("Q13") = Range("Q13") + 50
Else
Range("H34:J37").Cut Destination:=Range("D34")
Range("E34").Select
End If
End If
ElseIf GetAsyncKeyState(vbKeyRight) = KeyPressed Then
If ActiveCell.Column = 5 Then
Sleep 2
If Range("I34").Interior.Color = RGB(0, 0, 0) Or Range("I35").Interior.Color = RGB(0, 0, 0) _
Or Range("I33").Interior.Color = RGB(0, 0, 0) Then
Range("D34:F37").Cut Destination:=Range("H34")
Range("I34").Select
If Range("Q9") > Range("Q13") Then
MsgBox ("Oh No! You Crashed!" & vbNewLine & vbNewLine & "Your final score is: " & Range("Q13")), vbInformation
Else
MsgBox ("Wow!, New High Score!" & vbNewLine & vbNewLine & "Your final score is: " & Range("Q13")), vbInformation
Range("Q9") = Range("Q13")
End If
End
ElseIf Range("I34").Interior.Color = RGB(255, 215, 100) Or Range("I35").Interior.Color = RGB(255, 215, 100) _
Or Range("I33").Interior.Color = RGB(255, 215, 100) Then
Range("H32:J35").Interior.Color = RGB(255, 255, 255)
If Range("I31").Interior.Color = RGB(255, 215, 100) Then
Range("H31:J31").Interior.Color = RGB(255, 255, 255)
End If
Range("D34:F37").Cut Destination:=Range("H34")
Range("I34").Select
Range("Q13") = Range("Q13") + 50
Else
Range("D34:F37").Cut Destination:=Range("H34")
Range("I34").Select
End If
End If
ElseIf GetAsyncKeyState(vbKeyUp) = KeyPressed Then
If ActiveCell.Column = 5 Or ActiveCell.Column = 9 Then
Sleep 2
TimeDelay = 0.005
End If
ElseIf GetAsyncKeyState(vbKeyDown) = KeyPressed Then
If ActiveCell.Column = 5 Or ActiveCell.Column = 9 Then
Sleep 2
LastTimeDelay = (0.1 * (0.8 ^ SpeedCount))
If LastTimeDelay < 0.005 Then
LastTimeDelay = 0.005
End If
TimeDelay = LastTimeDelay
End If
End If
Loop
Maneuvering the vehicle using the Left & Right arrow keys
In order to maneuver the vehicle, you would first need to know its current position in order to ensure the player does not exceed the boundaries.
This is determined by checking the column position of the ActiveCell. The player’s vehicle can either be in column 5 or column 9 (as there are only 2 lanes).
If for example the current position of the vehicle is column 5, and the left arrow key is selected, the code will first check the current position of the vehicle. If the vehicle is in column 5, no changes would occur as the vehicle cannot move beyond this boundary. If however the current position was in column 9, the vehicle would shift to the left and the ActiveCell would change its position to accommodate this.
Vice versa for the right arrow key.
Speed up & Slowing down using the Up & Down arrow keys
Ken’s excel game has a variable called D1 which he adjusts in order to speed up the Snake. I have renamed this variable as TimeDelay. The TimeDelay variable simply acts as a delay between each loop allowing you to control the speed.
In the case of this game, the vehicle is sped up simply by reducing the TimeDelay variable. The up and down arrow keys are used to enable this. The smaller the TimeDelay, the faster vehicle moves.
Hitting Traffic & Hitting the Bonus Car
In order to check if the vehicle is hitting a black car or a yellow car, the cells above and to the left/right side need to be checked after every loop.
In order to explain the code behind a rear-crash, the position of the cars during the rear-collision with traffic must be seen. I have attached an image below

You would notice that during the crash, the cell directly above the ActiveCell is black. Once this is understood, this becomes a fairly straightforward approach. If the cell above is black, the vehicle has crashed.
In the case of a side collision (i.e shifting from the right to the left lane and vice versa), it has to be looked a little differently.
The first thing to note is that IF the vehicle is on the left hand side, the center line of the traffic on the right side would be in column “I”.
IF the vehicle is on the right hand side, the center line of the traffic on the left side would be in column “E”.

A bit of trial and error was needed from my end in order determine at which point I should perform the check.
The idea is to ensure that IF the left/right arrow key is pressed, the 3 center cells of either column “I” or “E” are not black. If it is black, the vehicle will crash on key press.
The same procedure is performed in order to check if the player’s vehicle has collided with the bonus vehicle (yellow vehicle), but in this case, the Player gets an extra 50 points.
Generating Traffic
There are two events taking place in this step.
The first event is the movement of traffic during gameplay. The second event is adding new traffic as the game is ongoing.
The movement of traffic is handled by a simple process of cut and paste :P. Fairly straightforward right?
The cut and paste process is broken into 3 sections;

As seen from the above image, the first step moves the range of cell to the right one cell down. The second step shifts the top region one cell down and the final step simply changes the bottom region to white colour. The code is attached below.
If ActiveCell.Column = 5 Then
Range("G33:K39").Cut Destination:=Range("G34")
Range("C3:K32").Cut Destination:=Range("C4")
Range("C38:K39").Interior.Color = RGB(255, 255, 255)
ElseIf ActiveCell.Column = 9 Then
Range("C33:G38").Cut Destination:=Range("C34")
Range("C3:K32").Cut Destination:=Range("C4")
Range("C38:K39").Interior.Color = RGB(255, 255, 255)
End If
We can now move onto the next event.
A point to remember when new traffic cars are being added during the gameplay;
- When generating traffic on the opposite lane, there must be sufficient space between the left and right traffic vehicles to switch lanes. If the next car being generated is on the same side, the above requirement is not necessary.
In short, when a vehicle is placed, there has to be 5 cell spaces (if the next vehicle is on the same side) OR 10 cell spaces (if the next vehicle is on the opposite side) before the next vehicle is added.
We first start by generating a random number between 1 and 2.
A count system is used to allow the traffic to move down before the next car is added in order to place these vehicles in their relevant positions.
If the first vehicle has a random number of 1 and the next random number is also 1. The count will only be 5 (i.e, the length of the vehicle plus one extra cell above). This will provide 1 space between each vehicle.
If the next random number is 2, the count would be 10. This will provide enough gap to maneuver between the 2 cars.

Generating a Bonus Car
The placement of the bonus vehicle is incorporated in the traffic code above. Instead of a black car, a yellow car is placed after a certain count has been achieved.
The appearance of a yellow car indicates an increase in speed (almost like a level up)
The code for the above 2 sections can be seen below;
Count3 = Count3 + 1
If Current = 1 Then
If NextPos = 1 Then
If Count3 > 4 Then
If BonusCount > LastBonusCount Then
Range("W39:Y42").Copy
Range("D4").PasteSpecial
Application.CutCopyMode = False
Current = NextPos
Randomize
NextPos = Int(1 + Rnd * (2 - 1 + 1))
Count3 = 0
If Range("E34").Interior.Color = RGB(255, 0, 0) Then
Range("E34").Select
ElseIf Range("E34").Interior.Color = RGB(170, 210, 140) Then
Range("E34").Select
ElseIf Range("E34").Interior.Color = RGB(0, 175, 240) Then
Range("E34").Select
Else
Range("I34").Select
End If
LastBonusCount = LastBonusCount + 1
Else
Range("W4:Y7").Copy
Range("D4").PasteSpecial
Application.CutCopyMode = False
Current = NextPos
Randomize
NextPos = Int(1 + Rnd * (2 - 1 + 1))
Count3 = 0
If Range("E34").Interior.Color = RGB(255, 0, 0) Then
Range("E34").Select
ElseIf Range("E34").Interior.Color = RGB(170, 210, 140) Then
Range("E34").Select
ElseIf Range("E34").Interior.Color = RGB(0, 175, 240) Then
Range("E34").Select
Else
Range("I34").Select
End If
End If
End If
ElseIf NextPos = 2 Then
If Count3 > 9 Then
If BonusCount > LastBonusCount Then
Range("W39:Y42").Copy
Range("H4").PasteSpecial
Application.CutCopyMode = False
Current = NextPos
Randomize
NextPos = Int(1 + Rnd * (2 - 1 + 1))
Count3 = 0
If Range("E34").Interior.Color = RGB(255, 0, 0) Then
Range("E34").Select
ElseIf Range("E34").Interior.Color = RGB(170, 210, 140) Then
Range("E34").Select
ElseIf Range("E34").Interior.Color = RGB(0, 175, 240) Then
Range("E34").Select
Else
Range("I34").Select
End If
LastBonusCount = LastBonusCount + 1
Else
Range("W4:Y7").Copy
Range("H4").PasteSpecial
Application.CutCopyMode = False
Current = NextPos
Randomize
NextPos = Int(1 + Rnd * (2 - 1 + 1))
Count3 = 0
If Range("E34").Interior.Color = RGB(255, 0, 0) Then
Range("E34").Select
ElseIf Range("E34").Interior.Color = RGB(170, 210, 140) Then
Range("E34").Select
ElseIf Range("E34").Interior.Color = RGB(0, 175, 240) Then
Range("E34").Select
Else
Range("I34").Select
End If
End If
End If
End If
ElseIf Current = 2 Then
If NextPos = 1 Then
If Count3 > 9 Then
If BonusCount > LastBonusCount Then
Range("W39:Y42").Copy
Range("D4").PasteSpecial
Application.CutCopyMode = False
Current = NextPos
Randomize
NextPos = Int(1 + Rnd * (2 - 1 + 1))
Count3 = 0
If Range("E34").Interior.Color = RGB(255, 0, 0) Then
Range("E34").Select
ElseIf Range("E34").Interior.Color = RGB(170, 210, 140) Then
Range("E34").Select
ElseIf Range("E34").Interior.Color = RGB(0, 175, 240) Then
Range("E34").Select
Else
Range("I34").Select
End If
LastBonusCount = LastBonusCount + 1
Else
Range("W4:Y7").Copy
Range("D4").PasteSpecial
Application.CutCopyMode = False
Current = NextPos
Randomize
NextPos = Int(1 + Rnd * (2 - 1 + 1))
Count3 = 0
If Range("E34").Interior.Color = RGB(255, 0, 0) Then
Range("E34").Select
ElseIf Range("E34").Interior.Color = RGB(170, 210, 140) Then
Range("E34").Select
ElseIf Range("E34").Interior.Color = RGB(0, 175, 240) Then
Range("E34").Select
Else
Range("I34").Select
End If
End If
End If
ElseIf NextPos = 2 Then
If Count3 > 4 Then
If BonusCount > LastBonusCount Then
Range("W39:Y42").Copy
Range("H4").PasteSpecial
Application.CutCopyMode = False
Current = NextPos
Randomize
NextPos = Int(1 + Rnd * (2 - 1 + 1))
Count3 = 0
If Range("E34").Interior.Color = RGB(255, 0, 0) Then
Range("E34").Select
ElseIf Range("E34").Interior.Color = RGB(170, 210, 140) Then
Range("E34").Select
ElseIf Range("E34").Interior.Color = RGB(0, 175, 240) Then
Range("E34").Select
Else
Range("I34").Select
End If
LastBonusCount = LastBonusCount + 1
Else
Range("W4:Y7").Copy
Range("H4").PasteSpecial
Application.CutCopyMode = False
Current = NextPos
Randomize
NextPos = Int(1 + Rnd * (2 - 1 + 1))
Count3 = 0
If Range("E34").Interior.Color = RGB(255, 0, 0) Then
Range("E34").Select
ElseIf Range("E34").Interior.Color = RGB(170, 210, 140) Then
Range("E34").Select
ElseIf Range("E34").Interior.Color = RGB(0, 175, 240) Then
Range("E34").Select
Else
Range("I34").Select
End If
End If
End If
End If
End If
Increase Speed as Score Increases
The final portion of this game is increasing the difficulty of the game. This is easily achieved by adjusting the TimeDelay as you progress with your score.
Count2 = Count2 + 1
If Count2 = 7 Then
Count2 = 0
Range("Q13") = Range("Q13") + 1
End If
Count = Count + 1
If Count = n Then
SpeedCount = SpeedCount + 1
BonusCount = BonusCount + 1
TimeDelay = TimeDelay * 0.8
Count = 0
If TimeDelay < 0.05 Then
n = Application.WorksheetFunction.Round((n * 1.2), -1)
End If
If TimeDelay < 0.005 Then
TimeDelay = 0.005
End If
End If
New things I would consider if I were to re-build this game?
Why limit this game to a 2 lane traffic system? Maybe a 4 lane traffic system with multiple bonus vehicles (slow time down/speed time up) would be more interesting?
I hope someone out there would use this as a means to generate something new and different. Whether it works or not is irrelevant, it’s more of the experience. These are just fun projects to kill time and help you build challenges to overcome.