Skip to main content
Tweeted twitter.com/StackCodeReview/status/995794165807173633
edited tags
Link
200_success
  • 145.7k
  • 22
  • 192
  • 481
Source Link
Nathan
  • 410
  • 2
  • 8

Simple two player snake game

I've been working on a two player snake game in python. I would really appreciate any suggestions/general input that would help improve my coding.

"""
5-13-2018
Nathan van 't Hof
2 player snake game
players can move around using wasd (player 1) and ijkl (player 2)
eating apples: - will increase players length
"""

import random
import keyboard
import os
import colorama
import time

def get_apple(width, height, snake1, snake2):
    """
    find new random coordinate to place the apple
    """
    if len(snake1) + len(snake2) >= width*height:
        u = raw_input('You win!')
        quit()
    while True:
        apple = [random.randint(0, width - 1), random.randint(0, height-1)]
        if apple not in snake1 and apple not in snake2:
            return apple
        

def draw(game_field, i, key):
    """
    change a specific coordinate of the game field
    to a different type
    """
    game_field[i[0]][i[1]] = key
    return game_field


def move_snake(game_field, snake, typ):
    """
    move the snake one step
    """
    game_field = draw(game_field, snake[-2], typ)
    game_field = draw(game_field, snake[-1], 'O')
    return game_field


def change_pos(prev, width, height, dx, dy):
    """
    change the coordinate of the head of the snake
    """
    return [(prev[0]+dx)%width, (prev[1]+dy)%height]


def print_game(game_field):
    """
    print the game (in a readable format)
    """
    output = '.' * ((len(game_field)) * 2 + 1) + '\n'
    for i in game_field:
        output += '.' + ' '.join(i) + '.' + '\n'
    output += '.' * ((len(game_field)) * 2 + 1)
    # moves the marker to the top to prevent flikkering
    print('\033[H' + output)


def check_die(snake1, snake2):
    """
    check whether the snakes 'die'
    by letting the head bump into a tail/other head
    """
    dead = False
    if snake1[-1] == snake2[-1]:
        u = raw_input('Both snakes died')
        dead = True
    elif snake1[-1] in snake2 or snake1.count(snake1[-1]) >= 2:
        u = raw_input('Snake 1 died')
        dead = True
    elif snake2[-1] in snake1 or snake2.count(snake2[-1]) >= 2:
        u = raw_input('Snake 2 died')
        dead = True
    if dead:
        quit()


def check_movement(dx, dy, ch1, ch2, ch3, ch4):
    """
    check where the snake moves
    """
    if keyboard.is_pressed(ch1) and dx != -1 and dy != 0:
        return -1, 0
    if keyboard.is_pressed(ch2) and dx != 0 and dy != -1:
        return 0, -1
    if keyboard.is_pressed(ch3) and dx != 1 and dy != 0:
        return 1, 0
    if keyboard.is_pressed(ch4) and dx != 0 and dy != 1:
        return 0,1
    return dx, dy


def update_snake(new_pos, apple, game_field, snake1, snake2):
    snake1.append(new_pos)
    if new_pos == apple:
        apple = get_apple(width, height, snake1, snake2)
        game_field = draw(game_field, apple, '-')
    else:
        game_field = draw(game_field, snake1[0], ' ')
        del snake1[0]
    return snake1, apple, game_field

    
# init
width, height = 20, 20
snake1 = [[0,0],[0,1]]
snake2 = [[width/2, 0], [width/2 + 1, 0]]

apple = get_apple(width, height, snake1, snake2)
dx1, dy1 = 0, 1
dx2, dy2 = 0, 1

os.system('cls' if os.name == 'nt' else 'clear')
# this allows '\033[H' to work
colorama.init()

# draw inital positions of the field
game_field = [height*[' '] for i in range(width)]
for i in snake1:
    game_field = draw(game_field, i, 'x')
for i in snake2:
    game_field = draw(game_field, i, '+')

game_field = draw(game_field, snake1[-1], 'O')
game_field = draw(game_field, snake2[-1], 'O')
game_field = draw(game_field, apple, '-')

prev_time = time.time()
while True:
    try:
        fps = float(input('What framerate would you like to run at?'))
        break
    except:
        print('Please input a number')
        
os.system('cls' if os.name == 'nt' else 'clear')

while True:
    # check inputs from players
    dx1, dy1 = check_movement(dx1, dy1, 'w', 'a', 's', 'd')
    dx2, dy2 = check_movement(dx2, dy2, 'i', 'j', 'k', 'l')

    # update screen if enough time has passed
    if time.time() - prev_time > 1./fps:
        prev_time = time.time()
        print_game(game_field)
        new_pos1 = change_pos(snake1[-1], width, height, dx1, dy1)
        new_pos2 = change_pos(snake2[-1], width, height, dx2, dy2)
        
        # update snakes and playing field
        check_die(snake1, snake2)
        
        snake1, apple, game_field = update_snake(new_pos1, apple, game_field, snake1, snake2)
        snake2, apple, game_field = update_snake(new_pos2, apple, game_field, snake2, snake1)

        game_field = move_snake(game_field, snake1, 'x')
        game_field = move_snake(game_field, snake2, '+')