Pygame列表(链表)简单实现贪吃蛇

Pygame列表(链表)简单实现贪吃蛇_第1张图片

主要算法:

创建一个二维矩阵映射到屏幕上的像素,逻辑在该矩阵中实现

移动通过4个矢量完成,矢量储存在列表中按照 上右下左 的顺序排列(顺时针90度),

当前矢量以0-3的数字表达,这样进行加二除余可以实现判断180度方向无效

蛇身以列表方式表达,每次游戏循环时在列表头部插入一个蛇头,如果没有吃到东西则把蛇尾去掉

关于按键太快会导致撞到自己:

        pygame在检测到2个按键的时候有可能会把矢量反向

解决方法:

        每一帧只计算一个按键

操作:

        WSAD 方向

        在游戏结束之后按R重新开始

import pygame as pg
import time
import random
 

class Tile():
    def __init__(self,x,y): #主要是储存数据和绘制图形
        self.x,self.y = x,y
        self.connected = [0,0,0,0] # up,right,down,left 0 for not connected
        self.tile_size = [(game_size[0]-100)/grid_size[0],(game_size[1]-100)/grid_size[1]]
        self.rectangle = (self.x*self.tile_size[0]+50,self.y*self.tile_size[1]+50,self.tile_size[0],self.tile_size[1])
        self.tile_type = 0 # 0 => empty, 1 => snake, 2 => fruit
 
    def draw(self,color = (0,0,0)): #x,y represents the tile coordinates
        pg.draw.rect(screen,tile_color[self.tile_type],self.rectangle)   #绘制节点
 

def generate_fruit():
    global fruit
 
    x,y = random.randint(0,grid_size[0]),random.randint(0,grid_size[1])
    while matrix[y][x].tile_type != 0:
        x,y = random.randint(0,grid_size[0]),random.randint(0,grid_size[1])
    fruit = matrix[y][x]
    fruit.tile_type = 2
 
def initialize():
    global score
    global game_lost
    global fruit
    global matrix
    global snake
    global step_score
 
    game_lost = False
    score = 0
    step_score = 200
    matrix = []
    for y in range(grid_size[1]+1):
        temp = []
        for x in range(grid_size[0]+1):
            temp.append(Tile(x,y))
        matrix.append(temp)
    x,y = random.randint(0,grid_size[0]),random.randint(0,grid_size[1])
    snake = [matrix[y][x]]
    snake[0].tile_type = 1
    generate_fruit()
 
def calculation():
    global game_lost
    global score
    global step_score
 
    head = snake[0]
    x,y = head.x,head.y
    dx,dy = vectors[current_vector]
    if x+dx not in range(grid_size[0]+1) or y+dy not in range(grid_size[1]+1):
        return True
    if matrix[y+dy][x+dx].tile_type == 1:
        return True
    if matrix[y+dy][x+dx].tile_type == 2:
        score += step_score
        step_score = 200
        generate_fruit()
    else:
        snake[-1].tile_type = 0
        snake.pop(-1)
    snake.insert(0,matrix[y+dy][x+dx])
    snake[0].tile_type = 1
 
if __name__ != '__main__': #八股专用
    exit()

#================================initialize parameter===================================
tile_color = [(0,0,0),(0,255,0),(255,0,0)]
vector_ref = {pg.K_w:0,pg.K_d:1,pg.K_s:2,pg.K_a:3} #starting up, clockwise
vectors = [[0,-1],[1,0],[0,1],[-1,0]]
current_vector = random.randint(0,3)
screen_size = [1200,800]
game_size = [800,800]
grid_size = [20,20]
dt = 0
 
screen = pg.display.set_mode(screen_size)
pg.init()
 
font = pg.font.Font('freesansbold.ttf', 32)
initialize()
high_score = 0
#================================game loop==============================================
run = True
while run:
    replay = False
    t_start = time.time()
    screen.fill((255,255,255))
    
    step_score -= 1
    high_score = score if score > high_score else high_score
    events = pg.event.get()
    for event in events:
        if event.type == pg.QUIT:
            run = False
            pg.quit()
        if event.type == pg.KEYDOWN:
            if event.key in vector_ref:
                target_vector = vector_ref[event.key]
                if (target_vector+2)%4 != current_vector:
                    current_vector = target_vector
                break
            if event.key == pg.K_r:
                replay = True
    
    if game_lost:
        if replay:
            initialize()
    else:
        game_lost = calculation()
        for y in range(len(matrix)):
            for x in range(len(matrix[y])):
                matrix[y][x].draw()
        score_text = font.render(f'score: {score}', True, (0,0,0), (255,255,255))
        screen.blit(score_text,(850,200))
        high_score_text = font.render(f'high score: {high_score}', True, (0,0,0), (255,255,255))
        screen.blit(high_score_text,(850,300))
        if dt != 0:
            time_text = font.render(f'fps:{1/(dt)}', True, (0,0,0), (255,255,255))
            screen.blit(time_text,(850,100))
        pg.display.update()
    time.sleep(0.1)
    dt = time.time()-t_start

你可能感兴趣的:(Pygame,pygame,python,算法,链表)