Python实现贪吃蛇大作战
貪吃蛇
初始版本
初始版本,只存在基本數據結構——雙向隊列。
游戲思路
貪吃蛇通過不斷得吃食物來增長自身,如果貪吃蛇碰到邊界或者自身則游戲失敗。
食物是綠色矩形來模擬,坐標為隨機數生成,定義一個蛇長變量,判斷蛇頭坐標和食物坐標是否接近,如果蛇頭接近食物,蛇長增加一個單位。
蛇結構體通過雙向隊列實現蛇的移動和增長。用pygame相應庫函數讀取鍵盤事件,每次事件發生都對應蛇頭的相應方向,例如按鍵盤下鍵貪吃蛇向下走。蛇的移動是通過在隊頭添加一個新的坐標,然后刪掉隊尾元素實現的。隊列的長度始終為蛇長變量的值。
得分變量為蛇長變量減去一個單位,初始化的時候蛇長就為1個單位長度,故而需要減1。
完整代碼
import pygame
import random
pygame.init()
# 以RGB的形式定義顏色
white = (255, 255, 255)
yellow = (255, 255, 102)
black = (0, 0, 0)
red = (213, 50, 80)
green = (0, 255, 0)
blue = (50, 153, 213)
# 設置窗體大小
dis_width = 800
dis_height = 600
dis = pygame.display.set_mode((dis_width, dis_height))
pygame.display.set_caption('貪吃蛇 KevenDuan1.0')
# 創建clock對象
clock = pygame.time.Clock()
# 蛇的寬度
snake_block = 15
# 蛇的速度
snake_speed = 15
# 從系統庫里獲取字體
font_style = pygame.font.SysFont("bahnschrift", 25)
score_font = pygame.font.SysFont("comicsansms", 35)
def Your_score(score):
value = score_font.render("Score: " + str(score), True, yellow)
# 在主surface里添加字體surface
dis.blit(value, [0, 0])
def our_snake(snake_block, snake_list):
for x in snake_list:
pygame.draw.rect(dis, black, [x[0], x[1], snake_block, snake_block])
def message(msg, color):
mesg = font_style.render(msg, True, color)
dis.blit(mesg, [dis_width // 2 - 180, dis_height // 2])
def gameLoop():
game_over = False
game_close = False
x1 = dis_width / 2
y1 = dis_height / 2
x1_change = 0
y1_change = 0
# 存放蛇的身體
snake_List = []
# 蛇的長度
Length_of_snake = 1
# 食物坐標隨機生成
foodx = round(random.randrange(snake_block, dis_width - snake_block, snake_block))
foody = round(random.randrange(snake_block, dis_height - snake_block, snake_block))
print(foodx, foody)
while not game_over:
while game_close == True:
dis.fill(blue)
message("Game over, press p again or q quit!", red)
Your_score(Length_of_snake - 1)
# 修改得分
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
game_over = True
game_close = False
if event.key == pygame.K_p:
gameLoop()
# 獲取事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_over = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT or event.key == pygame.K_a:
x1_change = -snake_block
y1_change = 0
elif event.key == pygame.K_RIGHT or event.key == pygame.K_d:
x1_change = snake_block
y1_change = 0
elif event.key == pygame.K_UP or event.key == pygame.K_w:
y1_change = -snake_block
x1_change = 0
elif event.key == pygame.K_DOWN or event.key == pygame.K_s:
y1_change = snake_block
x1_change = 0
if x1 >= dis_width or x1 < 0 or y1 >= dis_height or y1 < 0:
# 判斷為游戲失敗
game_close = True
x1 += x1_change
y1 += y1_change
dis.fill(blue)
pygame.draw.rect(dis, green, [foodx, foody, snake_block, snake_block])
snake_Head = []
snake_Head.append(x1)
snake_Head.append(y1)
snake_List.append(snake_Head)
# 貪吃蛇的移動
if len(snake_List) > Length_of_snake:
del snake_List[0]
# 判斷是否咬到自身
for x in snake_List[:-1]:
if x == snake_Head:
game_close = True
# 畫蛇出來
our_snake(snake_block, snake_List)
Your_score(Length_of_snake - 1)
# 更新畫面
pygame.display.update()
# 判斷蛇是否遲到食物
if foodx - 10 <= x1 <= foodx + 10 and foody - 10 <= y1 <= foody + 10:
foodx = round(random.randrange(snake_block, dis_width - snake_block, snake_block))
foody = round(random.randrange(snake_block, dis_height - snake_block, snake_block))
# print(foodx, foody)
Length_of_snake += 1
# 調節幀率來控制蛇的速度
clock.tick(snake_speed)
pygame.quit()
quit()
gameLoop()
代碼講解
使用的pygame和random兩個庫。Pygame是一種流行的Python游戲開發庫,它提供了許多功能,使開發人員可以輕松創建2D游戲。它具有良好的跨平臺支持,可以在多個操作系統上運行。random庫是用來獲取隨機數的,后面使用其獲取食物的隨機坐標。
import pygame
import random
初始化一些后期用到的參數,以及初始化pygame,創建clock時鐘對象。
# 初始化pygame
pygame.init()
# 以RGB的形式定義顏色
white = (255, 255, 255)
yellow = (255, 255, 102)
black = (0, 0, 0)
red = (213, 50, 80)
green = (0, 255, 0)
blue = (50, 153, 213)
# 設置窗體大小
dis_width = 800
dis_height = 600
dis = pygame.display.set_mode((dis_width, dis_height))
# 設置窗體的名稱
pygame.display.set_caption('貪吃蛇 KevenDuan1.0')
# 創建clock對象
clock = pygame.time.Clock()
# 蛇的寬度
snake_block = 15
# 蛇的速度
snake_speed = 15
# 從系統庫里獲取字體
font_style = pygame.font.SysFont("bahnschrift", 25)
score_font = pygame.font.SysFont("comicsansms", 35)
定義得分函數,實際上就是在畫面中添加字體。
def Your_score(score):
value = score_font.render("Score: " + str(score), True, yellow)
# 在主surface里添加字體surface
dis.blit(value, [0, 0])
定義蛇體函數,實際上就是遍歷蛇身隊列,依次在畫面中畫出矩形。
def our_snake(snake_block, snake_list):
for x in snake_list:
pygame.draw.rect(dis, black, [x[0], x[1], snake_block, snake_block])
定義文本函數,實際上就是在畫面中顯示文字。
def message(msg, color):
mesg = font_style.render(msg, True, color)
dis.blit(mesg, [dis_width // 2 - 180, dis_height // 2])
兩個循環結構一個判斷游戲是否結束一個判斷游戲是否需要退出。
while not game_over:
while game_close == True:
dis.fill(blue)
message("Game over, press p again or q quit!", red)
Your_score(Length_of_snake - 1)
# 修改得分
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
game_over = True
game_close = False
if event.key == pygame.K_p:
gameLoop()
獲取鍵盤事件改變蛇頭方向
# 獲取事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_over = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT or event.key == pygame.K_a:
x1_change = -snake_block
y1_change = 0
elif event.key == pygame.K_RIGHT or event.key == pygame.K_d:
x1_change = snake_block
y1_change = 0
elif event.key == pygame.K_UP or event.key == pygame.K_w:
y1_change = -snake_block
x1_change = 0
elif event.key == pygame.K_DOWN or event.key == pygame.K_s:
y1_change = snake_block
x1_change = 0
蛇的移動是通過在隊頭添加一個新的坐標,然后刪掉隊尾元素實現的。隊列的長度始終為蛇長變量的值。
x1 += x1_change
y1 += y1_change
dis.fill(blue)
pygame.draw.rect(dis, green, [foodx, foody, snake_block, snake_block])
snake_Head = []
snake_Head.append(x1)
snake_Head.append(y1)
snake_List.append(snake_Head)
# 貪吃蛇的移動
if len(snake_List) > Length_of_snake:
del snake_List[0]
# 判斷是否咬到自身
for x in snake_List[:-1]:
if x == snake_Head:
game_close = True
# 畫蛇出來
our_snake(snake_block, snake_List)
Your_score(Length_of_snake - 1)
# 更新畫面
pygame.display.update()
判斷蛇頭是否吃到食物,設置一定的范圍,防止出現永遠吃不到的bug
# 判斷蛇是否吃到食物
if foodx - 10 <= x1 <= foodx + 10 and foody - 10 <= y1 <= foody + 10:
foodx = round(random.randrange(snake_block, dis_width - snake_block, snake_block))
foody = round(random.randrange(snake_block, dis_height - snake_block, snake_block))
# print(foodx, foody)
Length_of_snake += 1
增加菜單功能
通過查閱資料,發現pygame_menu提供了比較完善的游戲菜單功能。我通過pip下載后,查閱了官方樣例代碼,這個菜單確實是比較精美的,正是我所需要給游戲添加的東西。
import pygame
import pygame_menu
pygame.init()
surface = pygame.display.set_mode((600, 400))
def set_difficulty(value, difficulty):
# Do the job here !
print(1)
pass
def start_the_game():
# Do the job here !
pass
menu = pygame_menu.Menu('Welcome', 600, 400,
theme=pygame_menu.themes.THEME_BLUE)
menu.add.text_input('Name :', default='kevenduan')
menu.add.selector('Difficulty :', [('Hard', 1), ('Easy', 2)], onchange=set_difficulty)
menu.add.button('Play', start_the_game)
menu.add.button('Quit', pygame_menu.events.EXIT)
menu.mainloop(surface)
最終版本
新功能
最終版本添加了游戲界面菜單,有查詢得分記錄的功能,以及可以選擇兩個難度。
查詢分數通過列表記錄后,通過排序來顯示得分前5的分數。
難度的控制是由蛇的速度來控制,由于咬到自身就游戲失敗有點坑,在這里刪除了。
完整代碼
import pygame
import random
import pygame_menu
score = [0, 0, 0, 0, 0]
pygame.init()
# 以RGB的形式定義顏色
white = (255, 255, 255)
yellow = (255, 255, 102)
black = (0, 0, 0)
red = (213, 50, 80)
green = (0, 255, 0)
blue = (50, 153, 213)
# 設置窗體大小
dis_width = 800
dis_height = 600
dis = pygame.display.set_mode((dis_width, dis_height))
pygame.display.set_caption('Snakes KevenDuan 1.0')
# 創建clock對象
clock = pygame.time.Clock()
# 蛇的寬度
snake_block = 15
# 蛇的速度
snake_speed = 15
# 從系統庫里獲取字體
font_style = pygame.font.SysFont("bahnschrift", 25)
score_font = pygame.font.SysFont("comicsansms", 35)
def Your_score(score):
value = score_font.render("Score: " + str(score), True, yellow)
# 在主surface里添加字體surface
dis.blit(value, [0, 0])
def our_snake(snake_block, snake_list):
for x in snake_list:
pygame.draw.rect(dis, black, [x[0], x[1], snake_block, snake_block])
def message(msg, color):
mesg = font_style.render(msg, True, color)
dis.blit(mesg, [dis_width // 2 - 150, dis_height // 2])
def gameLoop():
game_over = False
game_close = False
x1 = dis_width / 2
y1 = dis_height / 2
x1_change = 0
y1_change = 0
# 存放蛇的身體
snake_List = []
# 蛇的長度
Length_of_snake = 1
# 食物坐標隨機生成
foodx = round(random.randrange(snake_block, dis_width - snake_block, snake_block))
foody = round(random.randrange(snake_block, dis_height - snake_block, snake_block))
print(foodx, foody)
while not game_over:
while game_close == True:
dis.fill(blue)
score.append(Length_of_snake - 1)
message(f"Game Over! your score is {Length_of_snake - 1}", red)
Your_score(Length_of_snake - 1)
# 修改得分
pygame.display.update()
pygame.time.wait(2000)
# 顯示出菜單
menu.mainloop(dis)
# 獲取事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_over = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT or event.key == pygame.K_a:
x1_change = -snake_block
y1_change = 0
elif event.key == pygame.K_RIGHT or event.key == pygame.K_d:
x1_change = snake_block
y1_change = 0
elif event.key == pygame.K_UP or event.key == pygame.K_w:
y1_change = -snake_block
x1_change = 0
elif event.key == pygame.K_DOWN or event.key == pygame.K_s:
y1_change = snake_block
x1_change = 0
if x1 >= dis_width or x1 < 0 or y1 >= dis_height or y1 < 0:
# 判斷為游戲失敗
game_close = True
x1 += x1_change
y1 += y1_change
dis.fill(blue)
pygame.draw.rect(dis, green, [foodx, foody, snake_block, snake_block])
snake_Head = []
snake_Head.append(x1)
snake_Head.append(y1)
snake_List.append(snake_Head)
# 貪吃蛇的移動
if len(snake_List) > Length_of_snake:
del snake_List[0]
# 判斷是否咬到自身
# for x in snake_List[:-1]:
# if x == snake_Head:
# game_close = True
# 畫蛇出來
our_snake(snake_block, snake_List)
Your_score(Length_of_snake - 1)
# 更新畫面
pygame.display.update()
# 判斷蛇是否吃到食物
if foodx - 10 <= x1 <= foodx + 10 and foody - 10 <= y1 <= foody + 10:
foodx = round(random.randrange(snake_block, dis_width - snake_block, snake_block))
foody = round(random.randrange(snake_block, dis_height - snake_block, snake_block))
# print(foodx, foody)
Length_of_snake += 1
# 調節幀率來控制蛇的速度
clock.tick(snake_speed)
pygame.quit()
quit()
def set_difficulty(value, difficulty):
# Do the job here !
global snake_speed
if snake_speed == 15: snake_speed = 30
else: snake_speed = 15
def start_the_game():
# Do the job here !
gameLoop()
def rank():
# flag = True
while True:
dis.fill(blue)
score.sort()
print(score)
mesg1 = font_style.render(f"Your highest score is {score[-1]}", True, yellow)
dis.blit(mesg1, [dis_width // 2 - 150, dis_height // 2 - 30])
mesg2 = font_style.render(f"Ranking of scores:{score[-1:-6:-1]}", True, yellow)
dis.blit(mesg2, [dis_width // 2 - 190, dis_height // 2 + 10])
pygame.display.update()
pygame.time.wait(3000)
menu.mainloop(dis)
# menu.add.button('Quit', pygame_menu.events.EXIT)
# for event in pygame.event.get():
# if event.type == pygame.QUIT:
# flag = True
menu = pygame_menu.Menu('Welcome to my game', 800, 600,
theme=pygame_menu.themes.THEME_BLUE)
menu.add.text_input('Author :', default='KevenDuan')
menu.add.selector('Difficulty :', [('Easy', 1), ('Hard', 2)], onchange=set_difficulty)
menu.add.button('Yours socres', rank)
menu.add.button('Play', start_the_game)
menu.add.button('Quit', pygame_menu.events.EXIT)
menu.mainloop(dis)
總結
以上是生活随笔為你收集整理的Python实现贪吃蛇大作战的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++ Qt开发:标准Dialog对话框
- 下一篇: 乔布斯还在吗