下面是代码分享一下:
空格键停止,回车键开始。
"""贪吃蛇"""
import random
import sys
import time
import copy
import pygame
from pygame.locals import *
from collections import deque
SCREEN_WIDTH = 800 # 屏幕宽度
SCREEN_HEIGHT = 480 # 屏幕高度
SIZE = 20 # 小方格大小
LINE_WIDTH = 3 # 网格线宽度
# 游戏区域的坐标范围
SCOPE_X = (0, SCREEN_WIDTH // SIZE - 1)
SCOPE_Y = (2, SCREEN_HEIGHT // SIZE - 1)
# 食物的分值及颜色
# FOOD_STYLE_LIST = [(10, (255, 100, 100)), (20, (100, 255, 100)), (30, (100, 100, 255))]
FOOD_STYLE_LIST = [(10, (255, 0, 0)), (20, (0, 255, 0)), (30, (0, 0, 255)), (100, (255, 255, 0))]
# 幸运食物出现概率(蛇身减一,速度不增加)
FOOD_LUCK=(0,7)
# LIGHT = (100, 100, 100)
DARK = (200, 200, 200) # 蛇的颜色
BLACK = (0, 0, 0) # 网格线颜色
RED = (200, 30, 30) # 红色,GAME OVER 的字体颜色
BGCOLOR = (40, 40, 60) # 背景色
def print_text(screen, font, x, y, text, fcolor=(255, 255, 255)):
imgText = font.render(text, True, fcolor)
screen.blit(imgText, (x, y))
# 初始化蛇
def init_snake():
snake = deque()
snake.append((2, SCOPE_Y[0]))
# snake.append((1, SCOPE_Y[0]+1)), snake.append((1, SCOPE_Y[0])), snake.append((1, SCOPE_Y[0]+2))
snake.append((1, SCOPE_Y[0]))
snake.append((0, SCOPE_Y[0]))
return snake
def create_food(snake):
food_x = random.randint(SCOPE_X[0], SCOPE_X[1])
food_y = random.randint(SCOPE_Y[0], SCOPE_Y[1])
while (food_x, food_y) in snake:
# 如果食物出现在蛇身上,则重来
food_x = random.randint(SCOPE_X[0], SCOPE_X[1])
food_y = random.randint(SCOPE_Y[0], SCOPE_Y[1])
return food_x, food_y
def get_food_style():
if random.randint(FOOD_LUCK[0],FOOD_LUCK[1])==FOOD_LUCK[1]:
return FOOD_STYLE_LIST[3]
else:
return FOOD_STYLE_LIST[random.randint(0, 2)]
def main():
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) #pygame创建窗口
pygame.display.set_caption('贪吃蛇') #窗口名称
font1 = pygame.font.SysFont('SimHei', 16) # 得分的字体
font_ypos = 12 #位置
font2 = pygame.font.Font(None, 72) # GAME OVER 的字体
fwidth, fheight = font2.size('GAME OVER')
# 如果蛇正在向右移动,那么快速点击向下向左,由于程序刷新没那么快,向下事件会被向左覆盖掉,导致蛇后退,直接GAME OVER
# b 变量就是用于防止这种情况的发生
b = True
# 蛇
snake = init_snake()
# 食物
food = create_food(snake)
food_style = get_food_style()
# 方向
pos = (1, 0) #(左-1 右1,上-1 下1)
game_over = True
start = False # 是否开始,当start = True,game_over = True 时,才显示 GAME OVER
score = 0 # 得分
orispeed =0.5 # 原始速度
speed = orispeed
luck_times=0
last_move_time = None
last_draw_time = None
pause = False # 暂停
BG_r = 40 #手动背景调整
BG_g = 40
BG_b = 60
BG_auto=True
REC_score=[]
REC_save=False
while True:
for event in pygame.event.get():
if event.type == QUIT: #关闭窗口事件直接退出
sys.exit()
elif event.type == KEYDOWN: #处理按键事件
if event.key == K_RETURN: #处理回车键事件
if game_over:
start = True #游戏开始
game_over = False
b = True
snake = init_snake()
food = create_food(snake)
food_style = get_food_style()
pos = (1, 0)
# 得分
score = 0
REC_save=True
REC_score.append(score)
last_move_time = time.time()
last_draw_time = last_move_time
luck_times = 0
elif event.key == K_SPACE: #处理空格键事件 暂停和继续
if not game_over:
pause = not pause
elif event.key in (K_w, K_UP):
# 这个判断是为了防止蛇向上移时按了向下键,导致直接 GAME OVER
if b and not pos[1]:
pos = (0, -1)
b = False
elif event.key in (K_s, K_DOWN):
if b and not pos[1]:
pos = (0, 1)
b = False
elif event.key in (K_a, K_LEFT):
if b and not pos[0]:
pos = (-1, 0)
b = False
elif event.key in (K_d, K_RIGHT):
if b and not pos[0]:
pos = (1, 0)
b = False
elif event.key in (K_r,K_g,K_b): #背景色调整 L键控制开关(R,G,B)键控制3原色
if event.key==K_r:
BG_r=BG_r+5
if BG_r>=125:
BG_r=40
elif event.key==K_g:
BG_g=BG_g+5
if BG_g>=125:
BG_g=40
elif event.key==K_b:
BG_g=BG_b+5
if BG_b>=125:
BG_b=40
elif event.key==K_l:
BG_auto=not BG_auto
# 填充背景色
if BG_auto:
screen.fill(BGCOLOR)
else:
screen.fill((BG_r,BG_g,BG_b))
# 画网格线 竖线
for x in range(SIZE, SCREEN_WIDTH, SIZE):
pygame.draw.line(screen, BLACK, (x, SCOPE_Y[0] * SIZE), (x, SCREEN_HEIGHT), LINE_WIDTH)
# 画网格线 横线
for y in range(SCOPE_Y[0] * SIZE, SCREEN_HEIGHT, SIZE):
pygame.draw.line(screen, BLACK, (0, y), (SCREEN_WIDTH, y), LINE_WIDTH)
if not game_over:
curTime = time.time()
if curTime - last_move_time > speed: #控制移动速度speed值越小,刷新越快
if not pause:
b = True
last_move_time = curTime
next_s = (snake[0][0] + pos[0], snake[0][1] + pos[1]) #按方向读取下一个前进位
if next_s == food:
# 吃到了食物
snake.appendleft(next_s)
score += food_style[0]
if REC_save: #记录得分
REC_score.pop()
REC_score.append(score)
if food_style[0] == FOOD_STYLE_LIST[3][0] and len(snake) > 3:
snake.pop()
snake.pop()
luck_times+=1
else:
speed = orispeed - 0.03 * (score // 100-luck_times)
food = create_food(snake)
food_style = get_food_style()
else:
if SCOPE_X[0] <= next_s[0] <= SCOPE_X[1] and SCOPE_Y[0] <= next_s[1] <= SCOPE_Y[1] \
and next_s not in snake: #判断下一步是否越界和碰到自己
snake.appendleft(next_s)
snake.pop() #没吃到食物,前进一步
else:
game_over = True
# 画食物
if not game_over:
# 避免 GAME OVER 的时候把 GAME OVER 的字给遮住了
if food_style[0] == FOOD_STYLE_LIST[3][0]:
curTime = time.time()
if curTime-last_draw_time>0.01: #闪烁时间
pygame.draw.rect(screen, food_style[1], (food[0] * SIZE, food[1] * SIZE, SIZE, SIZE), 0)
last_draw_time=curTime
else:
pygame.draw.rect(screen, food_style[1], (food[0] * SIZE, food[1] * SIZE, SIZE, SIZE), 0)
# 画蛇
for s in snake:
pygame.draw.rect(screen, DARK, (s[0] * SIZE + LINE_WIDTH, s[1] * SIZE + LINE_WIDTH,
SIZE - LINE_WIDTH * 2, SIZE - LINE_WIDTH * 2), 0)
print_text(screen, font1, 30, font_ypos, f'速度: {score//100-luck_times}')
print_text(screen, font1, 630, font_ypos, f'得分: {score}')
if game_over:
if start:
print_text(screen, font2, (SCREEN_WIDTH - fwidth) // 2, (SCREEN_HEIGHT - fheight) // 2, 'GAME OVER', RED)
TMP_score=copy.deepcopy(REC_score)
TMP_score.sort()
TMP_score.reverse()
if len(REC_score):
print_text(screen, font1, 230, font_ypos, f'最高得分: {TMP_score[0]}')
print_text(screen, font1, 430, font_ypos, f'当前排名: {TMP_score.index(REC_score[len(REC_score)-1])+1}')
else:
print_text(screen, font1, 230, font_ypos, f'最高得分: {score}')
print_text(screen, font1, 430, font_ypos, f'当前排名: {score}')
pygame.display.update()
if __name__ == '__main__':
main()
下面是运行效果:
代码可以直接复制
如果有啥问题可以问我看到一定会回复大家,如果大家喜欢可以作者点赞和关注
大家的支持是我创作下去的最大动力