Snake Game Python Code

Python

import random
import curses

def main(stdscr):
    curses.curs_set(0)
    curses.start_color()
    # Define color pairs: (pair_number, foreground, background)
    curses.init_pair(1, curses.COLOR_GREEN, curses.COLOR_BLACK)   # Snake
    curses.init_pair(2, curses.COLOR_RED, curses.COLOR_BLACK)     # Food
    curses.init_pair(3, curses.COLOR_WHITE, curses.COLOR_BLUE)    # Background/border
    curses.init_pair(4, curses.COLOR_YELLOW, curses.COLOR_BLACK)  # Score
    curses.init_pair(5, curses.COLOR_MAGENTA, curses.COLOR_BLUE)  # Wall

    while True:
        sh, sw = stdscr.getmaxyx()
        win = curses.newwin(sh, sw, 0, 0)
        win.keypad(1)
        win.timeout(100)

        snk_x = sw // 4
        snk_y = sh // 2
        snake = [
            [snk_y, snk_x],
            [snk_y, snk_x - 1],
            [snk_y, snk_x - 2]
        ]
        # Food never on wall
        food = [random.randint(2, sh - 3), random.randint(2, sw - 3)]
        win.bkgd(' ', curses.color_pair(3))  # Set background color
        win.addch(food[0], food[1], '◆', curses.color_pair(2) | curses.A_BOLD)

        direction = 'd'  # Start moving right
        score = 0
        game_over = False

        while not game_over:
            win.clear()
            win.bkgd(' ', curses.color_pair(3))  # Redraw background

            # Modern border using box-drawing characters
            horizontal = '─'
            vertical = '│'
            tl = '┌'
            tr = '┐'
            bl = '└'
            br = '┘'
            for x in range(1, sw-2):
                win.addch(0, x, horizontal, curses.color_pair(5) | curses.A_BOLD)
                win.addch(sh-2, x, horizontal, curses.color_pair(5) | curses.A_BOLD)
            for y in range(1, sh-2):
                win.addch(y, 0, vertical, curses.color_pair(5) | curses.A_BOLD)
                win.addch(y, sw-2, vertical, curses.color_pair(5) | curses.A_BOLD)
            win.addch(0, 0, tl, curses.color_pair(5) | curses.A_BOLD)
            win.addch(0, sw-2, tr, curses.color_pair(5) | curses.A_BOLD)
            win.addch(sh-2, 0, bl, curses.color_pair(5) | curses.A_BOLD)
            win.addch(sh-2, sw-2, br, curses.color_pair(5) | curses.A_BOLD)

            # Score bar
            score_str = f' Score: {score} '
            score_x = (sw - len(score_str)) // 2
            win.addstr(0, score_x, score_str, curses.color_pair(4) | curses.A_BOLD)

            # Draw food (never on wall)
            win.addch(food[0], food[1], '◆', curses.color_pair(2) | curses.A_BOLD)

            # Draw snake (head is brighter)
            for idx, part in enumerate(snake):
                if idx == 0:
                    win.addch(part[0], part[1], '●', curses.color_pair(4) | curses.A_BOLD)
                else:
                    win.addch(part[0], part[1], '●', curses.color_pair(1) | curses.A_BOLD)
                # Shadow effect (optional, only if space allows)
                if part[1]+1 < sw-2 and part[0]+1 < sh-2:
                    win.addch(part[0]+1, part[1]+1, '.', curses.color_pair(3))

            next_key = win.getch()
            if next_key != -1:
                try:
                    char = chr(next_key).lower()
                except:
                    char = ''
                # Prevent reverse direction
                if (char == 'w' and direction != 's'):
                    direction = 'w'
                elif (char == 's' and direction != 'w'):
                    direction = 's'
                elif (char == 'a' and direction != 'd'):
                    direction = 'a'
                elif (char == 'd' and direction != 'a'):
                    direction = 'd'

            # Calculate new head
            new_head = [snake[0][0], snake[0][1]]
            if direction == 's':
                new_head[0] += 1
            if direction == 'w':
                new_head[0] -= 1
            if direction == 'd':
                new_head[1] += 1
            if direction == 'a':
                new_head[1] -= 1

            # Check for collision
            if (new_head[0] in [0, sh-2] or
                new_head[1] in [0, sw-2] or
                new_head in snake):
                # Modern Game Over box
                box_w = 32
                box_h = 5
                box_y = sh//2 - box_h//2
                box_x = sw//2 - box_w//2
                for i in range(box_h):
                    for j in range(box_w):
                        win.addch(box_y+i, box_x+j, ' ', curses.color_pair(3))
                msg = f" GAME OVER! FINAL SCORE: {score} "
                win.addstr(box_y+2, box_x + (box_w-len(msg))//2, msg, curses.color_pair(4) | curses.A_BOLD)
                win.refresh()
                curses.napms(1800)
                game_over = True
                break

            snake.insert(0, new_head)
            if snake[0] == food:
                score += 1
                win.timeout(max(40, 60 - score * 2))
                while True:
                    # Food never on wall
                    food = [random.randint(2, sh - 3), random.randint(2, sw - 3)]
                    if food not in snake:
                        break
            else:
                tail = snake.pop()

        # Play again prompt
        win.clear()
        win.bkgd(' ', curses.color_pair(3))
        win.border(0)
        prompt = "Play again? (y/n): "
        win.addstr(sh//2, sw//2 - len(prompt)//2, prompt, curses.color_pair(4) | curses.A_BOLD)
        win.refresh()
        while True:
            choice = win.getch()
            if choice in [ord('y'), ord('Y')]:
                break  # Restart the game loop
            elif choice in [ord('n'), ord('N')]:
                return  # Exit the game
                curses.wrapper(main)
            
Responsive Design
Copy to Clipboard
Syntax Highlighted
Scrollable Code