atulshanbhag

Snake.py

Apr 8th, 2017
140
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.31 KB | None | 0 0
  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3.  
  4. import sys
  5. import pygame
  6. from pygame.locals import *
  7. from random import randint
  8. from collections import deque
  9. from heapq import heappop, heappush
  10.  
  11. SCREEN = (300, 300)
  12. BLOCK_SIZE = 20
  13. COLS = SCREEN[0] / BLOCK_SIZE
  14. ROWS = SCREEN[1] / BLOCK_SIZE
  15. FREQUENCY = 30
  16. FPS = 30
  17. EXIT_TIME = 5000
  18. WHITE = 0xffffff
  19. RED = 0xff0000
  20. GREEN = 0x00ff00
  21. BLUE = 0x0000ff
  22. YELLOW = 0xffff00
  23. BLACK = 0x000000
  24. DIR = (0, 1)
  25. DIRS = [(0, 1), (0, -1), (1, 0), (-1, 0)]
  26. OPP_DIR = {
  27.     (0, 1): (0, -1),
  28.     (0, -1): (0, 1),
  29.     (1, 0): (-1, 0),
  30.     (-1, 0): (1, 0),
  31. }
  32.  
  33.  
  34. class Block(object):
  35.  
  36.     def __init__(self, screen, pos=(0, 0), color=GREEN):
  37.         self.screen = screen
  38.         self.pos = pos
  39.         self.rect_pos = (self.pos[0] * BLOCK_SIZE,
  40.                          self.pos[1] * BLOCK_SIZE)
  41.         self.val = self.pos[0] * ROWS + self.pos[1]
  42.         self.color = color
  43.  
  44.     def display(self):
  45.         pygame.draw.rect(self.screen, self.color, Rect(
  46.             self.rect_pos, (BLOCK_SIZE, BLOCK_SIZE)))
  47.         pygame.draw.rect(self.screen, BLACK, Rect(
  48.             self.rect_pos, (BLOCK_SIZE, BLOCK_SIZE)), 1)
  49.  
  50.     def set_color(self, color):
  51.         self.color = color
  52.  
  53.  
  54. class Snake(object):
  55.  
  56.     def __init__(self, screen, size=2, dr=(1, 0)):
  57.         self.screen = screen
  58.         self.body = deque()
  59.         self.size = size
  60.         self.dr = dr
  61.         for i in range(self.size):
  62.             self.body.append(Block(self.screen, pos=(i, 0)))
  63.         self.head = self.body[-1]
  64.         self.head.set_color(RED)
  65.         self.tail = self.body[0]
  66.         self.tail.set_color(BLUE)
  67.  
  68.     def display(self):
  69.         for block in self.body:
  70.             block.display()
  71.  
  72.     def is_collision(self, food):
  73.         return (self.head.val == food.val)
  74.  
  75.     def move(self, head):
  76.         self.head.set_color(GREEN)
  77.         self.head = head
  78.         self.head.set_color(RED)
  79.         self.body.append(self.head)
  80.         tail = self.body.popleft()
  81.         self.tail = self.body[0]
  82.         self.tail.set_color(BLUE)
  83.         return tail
  84.  
  85.     def update(self, tail, dr):
  86.         self.tail.set_color(GREEN)
  87.         self.tail = tail
  88.         self.tail.set_color(BLUE)
  89.         self.body.appendleft(self.tail)
  90.         self.head.set_color(RED)
  91.         self.dr = dr
  92.  
  93.     def shortest_path(self, food):
  94.         obs = deque([block.val for block in self.body])
  95.         pq = [(0, [self.head], self.dr, obs)]
  96.         vis = [False for _ in range(ROWS * COLS)]
  97.         vis[self.head.val] = True
  98.         flg = False
  99.  
  100.         while pq:
  101.             (pr, path, c_dr, obs) = heappop(pq)
  102.             u = path[-1]
  103.  
  104.             if u.val == food.val:
  105.                 return (path, c_dr, obs)
  106.  
  107.             flg = False
  108.             for d in DIRS:
  109.                 if d == OPP_DIR[c_dr]:
  110.                     continue
  111.  
  112.                 v = Block(screen, pos=(u.pos[0] + d[0], u.pos[1]
  113.                                        + d[1]))
  114.  
  115.                 if v.pos[0] < 0 or v.pos[0] >= COLS or v.pos[1] < 0 \
  116.                         or v.pos[1] >= ROWS or vis[v.val] or v.val in obs:
  117.                     continue
  118.  
  119.                 new_path = list(path)
  120.                 new_path.append(v)
  121.  
  122.                 h = heurestic(v, food)
  123.  
  124.                 new_obs = deque(obs)
  125.                 new_obs.popleft()
  126.                 new_obs.append(v.val)
  127.  
  128.                 heappush(pq, (h, new_path, d, new_obs))
  129.                 vis[v.val] = True
  130.                 flg = True
  131.  
  132.         if not flg:
  133.             return False
  134.  
  135.  
  136. def random_spawn(body=deque()):
  137.     food = Block(screen, pos=(randint(0, COLS - 1),
  138.                               randint(0, ROWS - 1)), color=YELLOW)
  139.     obs = [block.val for block in body]
  140.     while food.val in obs:
  141.         food = Block(screen, pos=(randint(0, COLS - 1),
  142.                                   randint(0, ROWS - 1)), color=YELLOW)
  143.     return food
  144.  
  145.  
  146. def heurestic(a, b):
  147.     return abs(a.pos[0] - b.pos[0]) + abs(a.pos[1] - b.pos[1])
  148.  
  149.  
  150. if __name__ == '__main__':
  151.     pygame.init()
  152.  
  153.     screen = pygame.display.set_mode(SCREEN, 0, 32)
  154.     pygame.display.set_caption('Snake !')
  155.     clock = pygame.time.Clock()
  156.  
  157.     snake = Snake(screen)
  158.     food = random_spawn()
  159.  
  160.     spath = snake.shortest_path(food)
  161.     if not spath:
  162.         print 'Game Over!'
  163.         pygame.time.wait(EXIT_TIME)
  164.         pygame.quit()
  165.         sys.exit()
  166.  
  167.     (path, dr, obs) = spath
  168.  
  169.     i = 0
  170.  
  171.     while True:
  172.         for event in pygame.event.get():
  173.             if event.type == QUIT:
  174.                 pygame.quit()
  175.                 sys.exit()
  176.  
  177.         screen.fill(BLACK)
  178.  
  179.         if snake.is_collision(food):
  180.             snake.update(tail, dr)
  181.  
  182.             food = random_spawn(snake.body)
  183.             snake.display()
  184.             food.display()
  185.             pygame.display.update()
  186.  
  187.             spath = snake.shortest_path(food)
  188.             if not spath:
  189.                 print 'Game Over!'
  190.                 pygame.time.wait(EXIT_TIME)
  191.                 pygame.quit()
  192.                 sys.exit()
  193.  
  194.             (path, dr, obs) = spath
  195.             i = 0
  196.  
  197.         else:
  198.             snake.display()
  199.             food.display()
  200.             pygame.display.update()
  201.  
  202.             tail = snake.move(path[i])
  203.             i += 1
  204.  
  205.         pygame.time.delay(FREQUENCY)
  206.         clock.tick(FPS)
Add Comment
Please, Sign In to add comment