# Snake game in Python

I am a biologist. Some time ago, I wanted to learn to program, and since I am fascinated by the 4th dimension and I was fascinated by the rotatation of hypercubes and hypersphere, so I decided to understand it better, and thanks to the work of Steve Hollasch, I understood that humans cannot "see" the 4th dimension, only project it in the 3 dimensional world.

Anyway, after finding the function to project the 4th dimension, I wanted to do something interactive with it, something where one can learn where and how the object moves in a 4 dimensional space. So I came up with the idea of a simple game: Snake.

snake4d

Can you please comment on the code here?

__author__ = "Mauro Pellanda"
__credits__ = ["Mauro Pellanda"]
__version__ = "1.1.0"
__maintainer__ = "Mauro Pellanda"
__email__ = "pmauro@ethz.ch"
__status__ = "Devlopment"

''' In this file is contained the snake definition'''

def get_random_color():
return "#%02x%02x%02x" % (random.randrange(0,255), random.randrange(0,255), random.randrange(0,255))

from vec import *
import time

class Snake:

def __init__(self):
self.p_list = [] #store the polygon of the snake
self.score = 0 #score
self.score2 = 0 #number of cube taken
self.time = 0. #boh
self.color = [0, 255, 0] #color
self.color_var = "up" #Variable to circulary change color

def create_cube(self,point):
'''This function return the polygon coordinates in a
determined postion defined by point'''
#calculate coordinates
v = V4(.4,.4,.4,.4)
higher = sum4(point,v)
lower = sub4(point,v)
c = cube4d(lower,higher)
#calculate the color
if self.color_var == "up":
self.color += 20
if self.color > 255-21:
self.color_var = "down"
elif self.color_var == "down":
self.color -= 20
if self.color < 21:
self.color_var = "up"
color_tuple = (self.color,self.color,self.color)
c.color = "#%02x%02x%02x" % color_tuple
#add the tag for the canvas (not used in this version)
c.tag = "snake"
return c

def initialize_snake(self):
'''it initialize the snake at the original position with 4 cubes'''
self.__init__()
size = 4
for x in range(size+1):
point = V4(0,-(size-x),0,0)
self.p_list.append(self.create_cube(point))

def move(self,dir):
'''check if is a valid move in that direction, the snake cannot go
in opposite direction'''
no_move = False
if dir == "UP" and self.head_dir != "DOWN":
dir_v = V4(0,1,0,0)
elif dir == "DOWN" and self.head_dir != "UP":
dir_v = V4(0,-1,0,0)
elif dir == "LEFT" and self.head_dir != "RIGHT":
dir_v = V4(-1,0,0,0)
elif dir == "RIGHT" and self.head_dir != "LEFT":
dir_v = V4(1,0,0,0)
elif dir == "FW" and self.head_dir != "RW":
dir_v = V4(0,0,1,0)
elif dir == "RW" and self.head_dir != "FW":
dir_v = V4(0,0,-1,0)
elif dir == "IN" and self.head_dir != "OUT":
dir_v = V4(0,0,0,-1)
elif dir == "OUT" and self.head_dir != "IN":
dir_v = V4(0,0,0,1)
else:
no_move = True

if not no_move:
#move the snake, and append a new polygon in the new position,
#take off the polygon from the tail, the snake is stored in the
self.p_list.pop(0)

1. Are the comments useful to understand what I did?
2. Do you have any suggestions about the programming style and/or the algorithms?

__author__ = "Mauro Pellanda"
__credits__ = ["Mauro Pellanda"]
__version__ = "1.1.0"
__maintainer__ = "Mauro Pellanda"
__email__ = "pmauro@ethz.ch"
__status__ = "Devlopment"

''' In this file is contained the snake definition'''


For this to be recognized as a docstring I think it needs to be the first thing in a file.

def get_random_color():
return "#%02x%02x%02x" % (random.randrange(0,255), random.randrange(0,255), random.randrange(0,255))

from vec import *
import time


imports are typically placed before function definitions

class Snake:


If you are working python 2.x, I recommend you make your classes inherit from object. That way they are new style classes.

    def __init__(self):


Using a string for something like this is a little odd. I suggest a boolean value or an integer.

        self.p_list = [] #store the polygon of the snake
self.score = 0 #score
self.score2 = 0 #number of cube taken
self.time = 0. #boh
self.color = [0, 255, 0] #color


I'd make color a tuple. Lists are for storing, well lists, not related items like colors. I know you do this so you can modify it. But I'd create new tuples everytime I changed the color.

        self.color_var = "up" #Variable to circulary change color


Agains strings are odd unless its actually text. It'll take slightly longer to compare strings then say ints or bools.

    def create_cube(self,point):
'''This function return the polygon coordinates in a
determined postion defined by point'''


Typically, the first ''' and final ''' are placed on a line by themselves for multiline docstrings

        #calculate coordinates
v = V4(.4,.4,.4,.4)
higher = sum4(point,v)
lower = sub4(point,v)
c = cube4d(lower,higher)
#calculate the color
if self.color_var == "up":
self.color += 20
if self.color > 255-21:
self.color_var = "down"
elif self.color_var == "down":
self.color -= 20
if self.color < 21:
self.color_var = "up"
color_tuple = (self.color,self.color,self.color)


You can just do color_tuple = tuple(self.color)

        c.color = "#%02x%02x%02x" % color_tuple


You've duplicated the tuple to string logic here and in the random color function. I suggest refactoring so they share it.

        #add the tag for the canvas (not used in this version)
c.tag = "snake"
return c

def initialize_snake(self):
'''it initialize the snake at the original position with 4 cubes'''
self.__init__()


Don't ever do that. __init__ is called when the object is built. You shouldn't call it later. Python will let you, but nobody expects you to do it and you are liable to confuse people.

        size = 4
for x in range(size+1):
point = V4(0,-(size-x),0,0)
self.p_list.append(self.create_cube(point))

def move(self,dir):
'''check if is a valid move in that direction, the snake cannot go
in opposite direction'''
no_move = False
if dir == "UP" and self.head_dir != "DOWN":
dir_v = V4(0,1,0,0)
elif dir == "DOWN" and self.head_dir != "UP":
dir_v = V4(0,-1,0,0)
elif dir == "LEFT" and self.head_dir != "RIGHT":
dir_v = V4(-1,0,0,0)
elif dir == "RIGHT" and self.head_dir != "LEFT":
dir_v = V4(1,0,0,0)
elif dir == "FW" and self.head_dir != "RW":
dir_v = V4(0,0,1,0)
elif dir == "RW" and self.head_dir != "FW":
dir_v = V4(0,0,-1,0)
elif dir == "IN" and self.head_dir != "OUT":
dir_v = V4(0,0,0,-1)
elif dir == "OUT" and self.head_dir != "IN":
dir_v = V4(0,0,0,1)
else:
no_move = True


Chains of elifs are a sign to look for a better solution. For example, you could have a dictionary mapping directionts to opposites and vectors. Then you'd just have to fetch from the dictionary.

        if not no_move:


Double negative, consider inverting the logic on no_move so it becomes moved.

            #move the snake, and append a new polygon in the new position,
#take off the polygon from the tail, the snake is stored in the