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

200行PYTHON代码实现贪吃蛇的更多相关文章

  1. 20行JS代码实现贪吃蛇

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. 200行Python代码实现2048

    200行Python代码实现2048 一.实验说明 1. 环境登录 无需密码自动登录,系统用户名shiyanlou 2. 环境介绍 本实验环境采用带桌面的Ubuntu Linux环境,实验中会用到桌面 ...

  3. 用200行Python代码“换脸”

    介绍 本文将介绍如何编写一个只有200行的Python脚本,为两张肖像照上人物的“换脸”. 这个过程可分为四步: 检测面部标记. 旋转.缩放和转换第二张图像,使之与第一张图像相适应. 调整第二张图像的 ...

  4. python 之路,200行Python代码写了个打飞机游戏!

    早就知道pygame模块,就是没怎么深入研究过,恰逢这周未没约到妹子,只能自己在家玩自己啦,一时兴起,花了几个小时写了个打飞机程序. 很有意思,跟大家分享下. 先看一下项目结构 "" ...

  5. 小游戏:200行python代码手写2048

    #-*- coding: utf-8 -*- import curses from random import randrange, choice from collections import de ...

  6. (转)python 之路,200行Python代码写了个打飞机游戏!

    原文:https://www.cnblogs.com/alex3714/p/7966656.html

  7. Python制作AI贪吃蛇,很多很多细节、思路都写下来了!

    前提:本文实现AI贪吃蛇自行对战,加上人机对战,读者可再次基础上自行添加电脑VS电脑和玩家VS玩家(其实把人机对战写完,这2个都没什么了,思路都一样) 实现效果: 很多人学习python,不知道从何学 ...

  8. 20行Python代码爬取王者荣耀全英雄皮肤

    引言王者荣耀大家都玩过吧,没玩过的也应该听说过,作为时下最火的手机MOBA游戏,咳咳,好像跑题了.我们今天的重点是爬取王者荣耀所有英雄的所有皮肤,而且仅仅使用20行Python代码即可完成. 准备工作 ...

  9. 一个 11 行 Python 代码实现的神经网络

    一个 11 行 Python 代码实现的神经网络 2015/12/02 · 实践项目 · 15 评论· 神经网络 分享到:18 本文由 伯乐在线 - 耶鲁怕冷 翻译,Namco 校稿.未经许可,禁止转 ...

随机推荐

  1. Java 8 Optional 良心指南,建议收藏

    想学习,永远都不晚,尤其是针对 Java 8 里面的好东西,Optional 就是其中之一,该类提供了一种用于表示可选值而非空引用的类级别解决方案.作为一名 Java 程序员,我真的是烦透了 Null ...

  2. 2019-2020-2 20174318张致豪《网络对抗技术》Exp1 PC平台逆向破解

    Exp1_PC平台逆向破解 前期准备 一.逆向及Bof基础实践说明 1.1 实践目标 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数 ...

  3. c++中比较好用的黑科技

    切入正题,上黑科技 一.黑科技函数(常用的我就不写了,例如sort函数) 1.next_permutation(a+1,a+1+n) a[1-n]全排列 2.reverse(a+1,a+1+n) 将a ...

  4. nes 红白机模拟器 第4篇 linux 手柄驱动支持

    小霸王学习机的真实手柄,实测CPU 占用 80% 接线图: 手柄读时序: joypad.c 驱动: 普通的字符设备驱动. #include <linux/module.h> #includ ...

  5. Core + Vue 后台管理基础框架3——后端授权

    1.前言 但凡业务系统,授权是绕不开的一环.见过太多只在前端做菜单及按钮显隐控制,但后端裸奔的,觉着前端看不到,系统就安全,掩耳盗铃也好,自欺欺人也罢,这里不做评论.在.NET CORE中,也见过不少 ...

  6. 结题报告--P2441角色属性树

    题目:点此 题目描述 绪萌同人社是一个有趣的组织,该组织结构是一个树形结构.有一个社长,直接下属一些副社长.每个副社长又直接下属一些部长……. 每个成员都有一个萌点的属性,萌点属性是由一些质数的萌元素 ...

  7. Fortify Audit Workbench 笔记 Access Control: Database

    Abstract 如果没有适当的 access control,就会执行一个包含用户控制主键的 SQL 指令,从而允许攻击者访问未经授权的记录. Explanation Database access ...

  8. Fortify Audit Workbench 笔记 Cross-Site Scripting-Persistent

    Cross-Site Scripting: Persistent Abstract 向 Web 浏览器发送非法数据会导致浏览器执行恶意代码. Explanation Cross-Site Script ...

  9. 基于微信小程序的租房小程序

    乐直租全国租房小程序前端 房源分钟上传,可快捷联系房东的小程序. 该小程序操作简单,布局清新,欢迎 start ~ 传送门:Github 扫码体验: pages: 首页 index 选择发布页 bef ...

  10. java网络编程——多线程数据收发并行

    基本介绍与思路 收发并行 前一篇博客中,完成了客户端与服务端的简单TCP交互,但这种交互是触发式的:客户端发送一条消息,服务端收到后再回送一条.没有做到收发并行.收发并行的字面意思很容易理解,即数据的 ...