200行PYTHON代碼實現貪吃蛇

200行Python代碼實現貪吃蛇

話不多說,最後會給出全部的代碼,也可以從這裡Fork,正文開始;

目前實現的功能列表:

  1. 貪吃蛇的控制,通過上下左右方向鍵;
  2. 觸碰到邊緣、牆壁、自身則遊戲結束;
  3. 接觸到食物則食物消失,同時根據食物類型身體會變長;
  4. 目前長度顯示;
  5. 暫停、死亡界面;

運行動圖

代碼片段分析

各個部分繪製的代碼

# 遊戲背景以及最下方用於顯示文字的背景  def draw_background():      # white background      screen.fill(COLORS['white'])      pygame.draw.rect(screen,COLORS['black'],(-100,GAME_SIZE[1],3000,200),0)    # 繪製牆壁  def draw_wall():      for xy in wall_list:          pygame.draw.rect(screen,COLORS['darkgray'],(xy[0]-WALL_WIDTH/2,xy[1]-WALL_WIDTH/2,WALL_WIDTH,WALL_HEIGHT),0)    # 繪製蛇,包括頭和身體  def draw_snake():      head = snake_list[0]      pygame.draw.circle(screen,COLORS['darkred'],(head[0],head[1]),int(SNAKE_WIDTH/2),0)      for xy in snake_list[1:]:          pygame.draw.rect(screen,COLORS['darkred'],(xy[0]-SNAKE_WIDTH/2,xy[1]-SNAKE_WIDTH/2,SNAKE_WIDTH,SNAKE_HEIGHT),2)    # 繪製食物  def draw_food():      for xyz in food_list:          pygame.draw.rect(screen,FOOD_COLORS[xyz[2]-1],(xyz[0]-FOOD_WIDTH/2,xyz[1]-FOOD_WIDTH/2,FOOD_WIDTH,FOOD_HEIGHT),0)    # 繪製下方的身體長度記錄  def draw_context():      txt = FONT_M.render('Snake length: '+str(len(snake_list)-1),True,COLORS['lightblue'])      x,y = 10,GAME_SIZE[1]+(int((SIZE[1]-GAME_SIZE[1])/2))      y = int(y-FONT_M.size('Count')[1]/2)      screen.blit(txt,(x,y))    # 繪製暫停界面  def draw_pause():      s = pygame.Surface(SIZE, pygame.SRCALPHA)      s.fill((255,255,255,220))      screen.blit(s, (0,0))      txt = FONT_M.render('PAUSE',True,COLORS['darkgray'])      x,y = SIZE[0]/2,SIZE[1]/2      x,y = int(x-FONT_M.size('PAUSE')[0]/2),int(y-FONT_M.size('PAUSE')[1]/2)      screen.blit(txt,(x,y))    # 繪製死亡界面  def draw_dead():      s = pygame.Surface(SIZE, pygame.SRCALPHA)      s.fill((255,255,255,240))      screen.blit(s, (0,0))      txt = FONT_M.render('YOU DEAD',True,COLORS['black'])      x,y = SIZE[0]/2,SIZE[1]/2      x,y = int(x-FONT_M.size('YOU DEAD')[0]/2),int(y-FONT_M.size('YOU DEAD')[1]/2)      screen.blit(txt,(x,y))  

死亡與食物的碰撞檢查

# 矩形覆蓋檢查作為碰撞檢測,思路是取反,即取所有不會覆蓋的情況的反即可  def rect_cover(rect1,rect2):      left1 = int(rect1[0])      right1 = int(rect1[0]+rect1[2])      up1 = int(rect1[1])      down1 = int(rect1[1]+rect1[3])      left2 = int(rect2[0])      right2 = int(rect2[0]+rect2[2])      up2 = int(rect2[1])      down2 = int(rect2[1]+rect2[3])        if not (right2<=left1 or left2>=right1 or down2<=up1 or up2>=down1):          return True      return False    # 檢查是否碰到食物  def check_food():      # 頭與食物      first = snake_list[0]      snake_head_rect = (first[0]-SNAKE_WIDTH/2,first[1]-SNAKE_WIDTH/2,SNAKE_WIDTH,SNAKE_HEIGHT)      for i in range(len(food_list)):          xyz = food_list[i]          food_rect = (xyz[0]-FOOD_WIDTH/2,xyz[1]-FOOD_WIDTH/2,FOOD_WIDTH,FOOD_HEIGHT)          if rect_cover(snake_head_rect,food_rect):              add_body(xyz[2])              del food_list[i]              return True      return False    # 檢查是否碰到邊緣、牆壁或者自己的身體  def check_dead():      first = snake_list[0]      snake_head_rect = (first[0]-SNAKE_WIDTH/2,first[1]-SNAKE_WIDTH/2,SNAKE_WIDTH,SNAKE_HEIGHT)      # 頭與邊緣      if first[0] < 0 or first[0] > GAME_SIZE[0] or first[1] < 0 or first[1] > GAME_SIZE[1]:          return True      # 頭與牆壁      for xy in wall_list:          wall_rect = (xy[0]-WALL_WIDTH/2,xy[1]-WALL_WIDTH/2,WALL_WIDTH,WALL_HEIGHT)          if rect_cover(snake_head_rect,wall_rect):              return True      # 頭與自身      for xy in snake_list[1:]:          body_rect = (xy[0]-SNAKE_WIDTH/2,xy[1]-SNAKE_WIDTH/2,SNAKE_WIDTH,SNAKE_HEIGHT)          if rect_cover(snake_head_rect,body_rect):              return True      return False  

更新食物以及增加蛇的身體長度

def add_food():      while(True):          xyz = [random.choice(X_LIST),random.choice(Y_LIST),random.choice([1,2,3,4])]          if xyz not in wall_list:              food_list.append(xyz)              break  def add_body(length=1):      for c in range(length):          # 尾巴加一節          last2,last1 = snake_list[-2],snake_list[-1]          if last2[0]==last1[0]: # 豎著的兩段              if last2[1]>last1[1]: # 朝下                  snake_list.append([last1[0],last1[1]-SNAKE_WIDTH])              else:                  snake_list.append([last1[0],last1[1]+SNAKE_WIDTH])          else: # 橫着的兩段              if last2[0]>last1[0]: # 朝右                  snake_list.append([last1[0]-SNAKE_WIDTH,last1[1]])              else:                  snake_list.append([last1[0]+SNAKE_WIDTH,last1[1]])  

蛇的自動移動

# 通過按鍵判斷當前蛇的朝向  if event.key == K_LEFT:      if head in ['up','down']:          head = 'left'  elif event.key == K_RIGHT:      if head in ['up','down']:          head = 'right'  elif event.key == K_UP:      if head in ['left','right']:          head = 'up'  elif event.key == K_DOWN:      if head in ['left','right']:          head = 'down'    # 通過朝向判斷蛇的下一個位置  first = snake_list[0]  snake_list[1:] = snake_list[:-1]  if head == 'up':      snake_list[0] = [first[0],first[1]-SNAKE_WIDTH]  elif head == 'down':      snake_list[0] = [first[0],first[1]+SNAKE_WIDTH]  elif head == 'left':      snake_list[0] = [first[0]-SNAKE_WIDTH,first[1]]  elif head == 'right':      snake_list[0] = [first[0]+SNAKE_WIDTH,first[1]]  

全部代碼

import sys,random    import pygame  from pygame.color import THECOLORS as COLORS  from pygame.locals import *      def draw_background():      # white background      screen.fill(COLORS['white'])      pygame.draw.rect(screen,COLORS['black'],(-100,GAME_SIZE[1],3000,200),0)    def draw_wall():      for xy in wall_list:          pygame.draw.rect(screen,COLORS['darkgray'],(xy[0]-WALL_WIDTH/2,xy[1]-WALL_WIDTH/2,WALL_WIDTH,WALL_HEIGHT),0)    def draw_snake():      head = snake_list[0]      pygame.draw.circle(screen,COLORS['darkred'],(head[0],head[1]),int(SNAKE_WIDTH/2),0)      for xy in snake_list[1:]:          pygame.draw.rect(screen,COLORS['darkred'],(xy[0]-SNAKE_WIDTH/2,xy[1]-SNAKE_WIDTH/2,SNAKE_WIDTH,SNAKE_HEIGHT),2)    def draw_food():      for xyz in food_list:          pygame.draw.rect(screen,FOOD_COLORS[xyz[2]-1],(xyz[0]-FOOD_WIDTH/2,xyz[1]-FOOD_WIDTH/2,FOOD_WIDTH,FOOD_HEIGHT),0)    def draw_context():      txt = FONT_M.render('Snake length: '+str(len(snake_list)-1),True,COLORS['lightblue'])      x,y = 10,GAME_SIZE[1]+(int((SIZE[1]-GAME_SIZE[1])/2))      y = int(y-FONT_M.size('Count')[1]/2)      screen.blit(txt,(x,y))    def draw_pause():      s = pygame.Surface(SIZE, pygame.SRCALPHA)      s.fill((255,255,255,220))      screen.blit(s, (0,0))      txt = FONT_M.render('PAUSE',True,COLORS['darkgray'])      x,y = SIZE[0]/2,SIZE[1]/2      x,y = int(x-FONT_M.size('PAUSE')[0]/2),int(y-FONT_M.size('PAUSE')[1]/2)      screen.blit(txt,(x,y))    def draw_dead():      s = pygame.Surface(SIZE, pygame.SRCALPHA)      s.fill((255,255,255,240))      screen.blit(s, (0,0))      txt = FONT_M.render('YOU DEAD',True,COLORS['black'])      x,y = SIZE[0]/2,SIZE[1]/2      x,y = int(x-FONT_M.size('YOU DEAD')[0]/2),int(y-FONT_M.size('YOU DEAD')[1]/2)      screen.blit(txt,(x,y))    def rect_cover(rect1,rect2):      left1 = int(rect1[0])      right1 = int(rect1[0]+rect1[2])      up1 = int(rect1[1])      down1 = int(rect1[1]+rect1[3])      left2 = int(rect2[0])      right2 = int(rect2[0]+rect2[2])      up2 = int(rect2[1])      down2 = int(rect2[1]+rect2[3])        if not (right2<=left1 or left2>=right1 or down2<=up1 or up2>=down1):          return True      return False    def add_food():      while(True):          xyz = [random.choice(X_LIST),random.choice(Y_LIST),random.choice([1,2,3,4])]          if xyz not in wall_list:              food_list.append(xyz)              break  def add_body(length=1):      for c in range(length):          # 尾巴加一節          last2,last1 = snake_list[-2],snake_list[-1]          if last2[0]==last1[0]: # 豎著的兩段              if last2[1]>last1[1]: # 朝下                  snake_list.append([last1[0],last1[1]-SNAKE_WIDTH])              else:                  snake_list.append([last1[0],last1[1]+SNAKE_WIDTH])          else: # 橫着的兩段              if last2[0]>last1[0]: # 朝右                  snake_list.append([last1[0]-SNAKE_WIDTH,last1[1]])              else:                  snake_list.append([last1[0]+SNAKE_WIDTH,last1[1]])    def check_food():      # 頭與食物      first = snake_list[0]      snake_head_rect = (first[0]-SNAKE_WIDTH/2,first[1]-SNAKE_WIDTH/2,SNAKE_WIDTH,SNAKE_HEIGHT)      for i in range(len(food_list)):          xyz = food_list[i]          food_rect = (xyz[0]-FOOD_WIDTH/2,xyz[1]-FOOD_WIDTH/2,FOOD_WIDTH,FOOD_HEIGHT)          if rect_cover(snake_head_rect,food_rect):              add_body(xyz[2])              del food_list[i]              return True      return False    def check_dead():      first = snake_list[0]      snake_head_rect = (first[0]-SNAKE_WIDTH/2,first[1]-SNAKE_WIDTH/2,SNAKE_WIDTH,SNAKE_HEIGHT)      # 頭與邊緣      if first[0] < 0 or first[0] > GAME_SIZE[0] or first[1] < 0 or first[1] > GAME_SIZE[1]:          return True      # 頭與牆壁      for xy in wall_list:          wall_rect = (xy[0]-WALL_WIDTH/2,xy[1]-WALL_WIDTH/2,WALL_WIDTH,WALL_HEIGHT)          if rect_cover(snake_head_rect,wall_rect):              return True      # 頭與自身      for xy in snake_list[1:]:          body_rect = (xy[0]-SNAKE_WIDTH/2,xy[1]-SNAKE_WIDTH/2,SNAKE_WIDTH,SNAKE_HEIGHT)          if rect_cover(snake_head_rect,body_rect):              return True      return False    if __name__ == "__main__":      # init pygame      pygame.init()        # contant      GAME_SIZE = [900,900]      SIZE = [GAME_SIZE[0],GAME_SIZE[1]+100]      FONT_S = pygame.font.SysFont('Times', 50)      FONT_M = pygame.font.SysFont('Times', 90)      DIRECTION = ['up','right','down','left']      X_LIST = [x for x in range(GAME_SIZE[0])]      Y_LIST = [y for y in range(GAME_SIZE[1])]      FOOD_COLORS = ((46,139,87),(199,21,133),(25,25,112),(255,215,0))        # wall      wall_list = [[100,200],[600,500],[350,200],[500,800]]      WALL_WIDTH,WALL_HEIGHT = 30,30        # food      food_list = [(150,200,1),(300,500,1),(740,542,1),(300,600,1),(700,600,1)]      FOOD_WIDTH,FOOD_HEIGHT = 14,14        # create screen 500*500      screen = pygame.display.set_mode(SIZE)        # variable parameter      snake_list = [[100+12*4,100],[100+12*3,100],[100+12*2,100],[100+12*1,100],[100,100]]      SNAKE_WIDTH,SNAKE_HEIGHT = 12,12      snake_v = 0      count_time = 0        # level      frame = 0.05      level = 1        # main loop      running = True      pause = False      dead = False      head = 'right'      while running:          for event in pygame.event.get():              if event.type == pygame.QUIT:                  running = False                  break              elif event.type == pygame.MOUSEBUTTONDOWN:                  pause = not pause              elif event.type == pygame.KEYUP:                  if event.key == K_LEFT:                      if head in ['up','down']:                          head = 'left'                  elif event.key == K_RIGHT:                      if head in ['up','down']:                          head = 'right'                  elif event.key == K_UP:                      if head in ['left','right']:                          head = 'up'                  elif event.key == K_DOWN:                      if head in ['left','right']:                          head = 'down'            # update data          if not pause and not dead:              count_time += frame*level              first = snake_list[0]              snake_list[1:] = snake_list[:-1]              if head == 'up':                  snake_list[0] = [first[0],first[1]-SNAKE_WIDTH]              elif head == 'down':                  snake_list[0] = [first[0],first[1]+SNAKE_WIDTH]              elif head == 'left':                  snake_list[0] = [first[0]-SNAKE_WIDTH,first[1]]              elif head == 'right':                  snake_list[0] = [first[0]+SNAKE_WIDTH,first[1]]            # background          draw_background()          # tunnel          draw_wall()          # choose item          draw_snake()          # food          draw_food()          # point          draw_context()          # pause          if not dead and pause:              draw_pause()          # dead          if dead:              draw_dead()          # flip          pygame.display.flip()            # pause 20ms          pygame.time.delay(int(frame/level*1000))            # check win or not          dead = check_dead()            if check_food():              add_food()        pygame.quit()  

再貼一下這個倉庫的鏈接

小遊戲集合倉庫

最後

大家可以到我的Github上看看有沒有其他需要的東西,目前主要是自己做的機器學習項目、Python各種腳本工具、有意思的小項目以及Follow的大佬、Fork的項目等:
https://github.com/NemoHoHaloAi