官方api调用有点慢,只实现了一些基础功能。
import pygame
import random
import requests
import time
from openai import OpenAI
# 初始化参数
WIDTH, HEIGHT = 400, 400
GRID_SIZE = 20
client = OpenAI(api_key="sk-2af2*********", base_url="https://api.deepseek.com")
# 在文件顶部添加导入
import openai
import threading
from queue import Queue
# 在全局参数部分修改
CONVERSATION_HISTORY = [] # 重命名为对话历史
MAX_HISTORY = 10 # 增加历史记录容量
def get_direction_from_api(snake, food, direction, conversation_history):
"""修改提示生成部分"""
head = snake[0]
# 新增方向元组定义
directions = [(0, -1), (0, 1), (-1, 0), (1, 0)] # 上、下、左、右
# 构建障碍物检测提示
obstacles = []
for distance in range(1, 6):
check_pos = (
head[0] + direction[0] * distance * GRID_SIZE,
head[1] + direction[1] * distance * GRID_SIZE
)
if (check_pos in snake[1:] or
not (0 <= check_pos[0] < WIDTH and 0 <= check_pos[1] < HEIGHT)):
obstacles.append(str(distance))
# 构建食物检测提示
food_dir = ""
if food[0] > head[0]: food_dir = "right"
elif food[0] < head[0]: food_dir = "left"
elif food[1] > head[1]: food_dir = "down"
elif food[1] < head[1]: food_dir = "up"
# 修复处:处理初始静止状态
current_dir = "未移动" if direction == (0,0) else ['up','down','left','right'][directions.index(direction)]
prompt = f"当前方向:{current_dir}。"
prompt += f"前方障碍在距离:{','.join(obstacles)}格。" if obstacles else "前方无近距离障碍。"
prompt += f"食物位于你的{food_dir}方,距离X轴{abs(food[0]-head[0])//GRID_SIZE}格,Y轴{abs(food[1]-head[1])//GRID_SIZE}格。"
# 添加碰撞历史到提示
if conversation_history:
prompt += f"\n最近{MAX_HISTORY}条对话记录:\n" + "\n".join(
[f"{i+1}. {msg}" for i, msg in enumerate(conversation_history[-MAX_HISTORY:])]
)
try:
response = client.chat.completions.create(
model="deepseek-reasoner",
messages=[{
"role": "user",
"content": prompt + "\n请用单个方向词(up/down/left/right)回答"
}],
timeout=300
)
print(f"[API请求] {prompt}")
print(f"[API响应] {response}")
choice = response.choices[0].message.content.strip().lower()
return {
"up": (0, -1), "down": (0, 1),
"left": (-1, 0), "right": (1, 0)
}.get(choice, direction)
except openai.APIError as e:
print(f"OpenAI API错误: {e}")
return direction
def reset_game():
"""重置游戏状态"""
return {
'snake': [(WIDTH//2, HEIGHT//2)],
'food': (random.randrange(0, WIDTH, GRID_SIZE),
random.randrange(0, HEIGHT, GRID_SIZE)),
'direction': (0, 0),
'last_api_call': time.time(),
'growth_pending': 0
}
# 在import区域新增
import threading
from queue import Queue
# 在全局参数新增
direction_queue = Queue()
api_requesting = False # API请求状态标志
def get_direction_async(snake, food, direction, conversation_history):
"""异步获取方向"""
global api_requesting
try:
new_dir = get_direction_from_api(snake, food, direction, conversation_history)
direction_queue.put(new_dir)
finally:
api_requesting = False
def game_loop():
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()
game_state = reset_game()
collision_history = []
global api_requesting # 新增全局变量声明
while True:
# 事件处理
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
return
# 修改API调用部分为异步
if not api_requesting and (time.time() - game_state['last_api_call'] > 0.5):
api_requesting = True
threading.Thread(target=get_direction_async, args=(
game_state['snake'],
game_state['food'],
game_state['direction'],
CONVERSATION_HISTORY[-MAX_HISTORY:] if CONVERSATION_HISTORY else [] # 修复参数
)).start()
game_state['last_api_call'] = time.time()
# 处理方向队列中的新方向
# 修改后的移动逻辑
if not direction_queue.empty():
game_state['direction'] = direction_queue.get()
# 执行单步移动
new_head = (
game_state['snake'][0][0] + game_state['direction'][0] * GRID_SIZE,
game_state['snake'][0][1] + game_state['direction'][1] * GRID_SIZE
)
# 碰撞检测
if (new_head in game_state['snake'] or
not (0 <= new_head[0] < WIDTH and 0 <= new_head[1] < HEIGHT)):
print("撞到障碍物!停止移动")
# 停止移动并保持当前状态
game_state['direction'] = (0, 0)
game_state['last_api_call'] = time.time()
continue # 跳过后续移动逻辑
# 移动蛇并处理食物
game_state['snake'].insert(0, new_head)
if new_head == game_state['food']:
game_state['food'] = (random.randrange(0, WIDTH, GRID_SIZE),
random.randrange(0, HEIGHT, GRID_SIZE))
while game_state['food'] in game_state['snake']:
game_state['food'] = (random.randrange(0, WIDTH, GRID_SIZE),
random.randrange(0, HEIGHT, GRID_SIZE))
game_state['growth_pending'] += 1
else:
if game_state['growth_pending'] > 0:
game_state['growth_pending'] -= 1
else:
game_state['snake'].pop()
# 移动后立即停止并重置方向
game_state['direction'] = (0, 0)
game_state['last_api_call'] = time.time()
# 保持API调用持续进行(原0.5秒间隔限制移除)
if not api_requesting:
api_requesting = True
threading.Thread(target=get_direction_async, args=(
game_state['snake'],
game_state['food'],
game_state['direction'],
CONVERSATION_HISTORY[-MAX_HISTORY:] if CONVERSATION_HISTORY else [] # 修复参数
)).start()
# 绘制界面
screen.fill((0,0,0))
for segment in game_state['snake']: # 修复snake引用
pygame.draw.rect(screen, (0,255,0),
(segment[0], segment[1], GRID_SIZE-1, GRID_SIZE-1))
pygame.draw.rect(screen, (255,0,0),
(game_state['food'][0], game_state['food'][1], GRID_SIZE-1, GRID_SIZE-1)) # 修复food引用
pygame.display.flip()
clock.tick(10)
if __name__ == "__main__":
game_loop()