貪吃蛇python代碼分析(python貪吃蛇最簡單代碼)

本文目錄一覽:

100行Python代碼,輕鬆完成貪吃蛇小遊戲?

你是想讓我們向你提問題?你這個放錯地方了,應該發布到自己的博客或論壇上面才對

如何用Python寫一個貪吃蛇AI

首先,讓我們羅列一些問題: (像頭腦風暴那樣,想到什麼就寫下來即可)

蛇和食物間有路徑直接就去吃,不可取。那該怎麼辦?

如果蛇去吃食物後,布局是安全的,是否就直接去吃?(這樣最優嗎?)

怎樣定義布局是否安全?

蛇和食物之間如果沒有路徑,怎麼辦?

最短路徑是否最優?(這個明顯不是了)

那麼,如果布局安全的情況下,最短路徑是否最優?

除了最短路徑,我們還可以怎麼走?S形?最長?

怎麼應對蛇身越來越長這個問題?

食物是隨機出現的,有沒可能出現無解的布局?

暴力法(brute force)能否得到最優序列?(讓貪吃蛇儘可能地多吃食物)

只要去想,問題還挺多的。這時讓我們以面向過程的思想,帶著上面的問題,

把思路理一理。一開始,蛇很短(初始化長度為1),它看到了一個食物, 使用 BFS 得到矩形中每個位置到達食物的最短路徑長度。在沒有蛇身阻擋下,

就是曼哈頓距離。然後,我要先判斷一下,貪吃蛇這一去是否安全。 所以我需要一條虛擬的蛇,它每次負責去探路。如果安全,才讓真正的蛇去跑。

當然,虛擬的蛇是不會繪製出來的,它只負責模擬探路。那麼, 怎麼定義一個布局是安全的呢? 如果你把文章開頭那張動態圖片中蛇的銷魂走位好好的看一下,

會發現即使到最後蛇身已經很長了,它仍然沒事一般地走出了一條路。而且, 是跟著蛇尾走的!嗯,這個其實不難解釋,蛇在運動的過程中,消耗蛇身,

蛇尾後面總是不斷地出現新的空間。蛇短的時候還無所謂,當蛇一長, 就會發現,要想活下來,基本就只能追著蛇尾跑了。在追著蛇尾跑的過程中,

再去考慮能否安全地吃到食物。(下圖是某次 BFS 後,得到的一個布局, 0 代表食物,數字代表該位置到達食物的距離,+號代表蛇頭,*號代表蛇身,

-號代表蛇尾,#號代表空格,外面的一圈#號代表圍牆)

# # # # # # #

# 0 1 2 3 4 #

# 1 2 3 # 5 #

# 2 3 4 – 6 #

# 3 + * * 7 #

# 4 5 6 7 8 #

# # # # # # #

經過上面的分析,我們可以將布局是否安全定義為蛇是否可以跟著蛇尾運動, 也就是蛇吃完食物後,蛇頭和蛇尾間是否存在路徑,如果存在,我就認為是安全的。

OK,繼續。真蛇派出虛擬蛇去探路後,發現吃完食物後的布局是安全的。那麼,

真蛇就直奔食物了。等等,這樣的策略好嗎?未必。因為蛇每運動一步, 布局就變化一次。布局一變就意味著可能存在更優解。比如因為蛇尾的消耗,

原本需要繞路才能吃到的食物,突然就出現在蛇眼前了。所以,真蛇走一步後, 更好的做法是,重新做 BFS。然後和上面一樣進行安全判斷,然後再走。

接下來我們來考慮一下,如果蛇和食物之間不存在路徑怎麼辦? 上文其實已經提到了做法了,跟著蛇尾走。只要蛇和食物間不存在路徑, 蛇就一直跟著蛇尾走。同樣的,由於每走一步布局就會改變, 所以每走一步就重新做 BFS 得到最新布局。

好了,問題又來了。如果蛇和食物間不存在路徑且蛇和蛇尾間也不存在路徑,

怎麼辦?這個我是沒辦法了,選一步可行的路徑來走就是了。還是一個道理, 每次只走一步,更新布局,然後再判斷蛇和食物間是否有安全路徑;

沒有的話,蛇頭和蛇尾間是否存在路徑;還沒有,再挑一步可行的來走。

上面列的好幾個問題里都涉及到蛇的行走策略,一般而言, 我們會讓蛇每次都走最短路徑。這是針對蛇去吃食物的時候,

可是蛇在追自己的尾巴的時候就不能這麼考慮了。我們希望的是蛇頭在追蛇尾的過程中,

儘可能地慢。這樣蛇頭和蛇尾間才能騰出更多的空間,空間多才有得發展。 所以蛇的行走策略主要分為兩種:

1. 目標是食物時,走最短路徑

2. 目標是蛇尾時,走最長路徑

那第三種情況呢?與食物和蛇尾都沒路徑存在的情況下, 這個時候本來就只是挑一步可行的步子來走,最短最長關係都不大了。

至於人為地讓蛇走S形,我覺得這不是什麼好策略,最初版本中已經分析過它的問題了。 (當然,除非你想使用最最無懈可擊的那個版本,就是完全不管食物,

讓蛇一直走S,然後在牆邊留下一條過道即可。這樣一來, 蛇總是可以完美地把所有食物吃完,然後佔滿整個空間,可是就很 boring 了。

沒有任何的意思)

上面還提到一個問題:因為食物是隨機出現的,有沒可能出現無解的局面? 答案是:有。我運行了程序,然後把每一次布局都輸出到 log,發現會有這樣的情況:

# # # # # # #

# * * * * * #

# * * – 0 * #

# * * # + * #

# * * * * * #

# * * * * * #

# # # # # # #

其中,+號是蛇頭,-號是蛇尾,*號是蛇身,0 是食物,#號代表空格,外面一圈# 號代表牆。這個布局上,食物已經在蛇頭面前了,可是它能吃嗎?不能! 因為它吃完食物後,長度加1,蛇頭就會把 0 的位置填上,布局就變成:

# # # # # # #

# * * * * * #

# * * – + * #

# * * # * * #

# * * * * * #

# * * * * * #

# # # # # # #

此時,由於蛇的長度加1,蛇尾沒有動,而蛇頭被自己圍著,掛掉了。可是, 我們卻還有一個空白的格子#沒有填充。按照我們之前教給蛇的策略,

面對這種情況,蛇頭就只會一直追著蛇尾跑,每當它和食物有路徑時, 它讓虛擬的蛇跑一遍發現,得到的新布局是不安全的,所以不會去吃食物,

而是選擇繼續追著蛇尾跑。然後它就這樣一直跑,一直跑。死循環, 直到你按 ESC 鍵為止。

由於食物是隨機出現的,所以有可能出現上面這種無解的布局。當然了, 你也可以得到完滿的結局,貪吃蛇把整個矩形都填充滿。

上面的最後一個問題,暴力法是否能得到最優序列。從上面的分析看來, 可以得到,但不能保證一定得到。

最後,看看高瞻遠矚的蛇是怎麼跑的吧:

python有趣的編程代碼

class Point:

  row=0

  col=0

  def __init__(self, row, col):

    self.row=row

    self.col=col

  def copy(self):

    return Point(row=self.row, col=self.col)

#初始框架

import pygame

import random

#初始化

pygame.init()

W=800

H=600

ROW=30

COL=40

size=(W,H)

window=pygame.display.set_mode(size)

pygame.display.set_caption(‘貪吃蛇’)

bg_color=(255,255,255)

snake_color=(200,200,200)

head=Point(row=int(ROW/2), col=int(COL/2))

head_color=(0,128,128)

snakes=[

  Point(row=head.row, col=head.col+1),

  Point(row=head.row, col=head.col+2),

  Point(row=head.row, col=head.col+3)

]

#生成食物

def gen_food():

  while 1:

    pos=Point(row=random.randint(0,ROW-1), col=random.randint(0,COL-1))

    #

    is_coll=False

    #是否跟蛇碰上了

    if head.row==pos.row and head.col==pos.col:

      is_coll=True

    #蛇身子

    for snake in snakes:

      if snake.row==pos.row and snake.col==pos.col:

        is_coll=True

        break

    if not is_coll:

      break

  return pos

#定義坐標

food=gen_food()

food_color=(255,255,0)

direct=’left’       #left,right,up,down

#

def rect(point, color):

  cell_width=W/COL

  cell_height=H/ROW

  left=point.col*cell_width

  top=point.row*cell_height

  pygame.draw.rect(

    window, color,

    (left, top, cell_width, cell_height)

  )

  pass

#遊戲循環

quit=True

clock=pygame.time.Clock()

while quit:

  #處理事件

  for event in pygame.event.get():

    if event.type==pygame.QUIT:

      quit=False

    elif event.type==pygame.KEYDOWN:

      if event.key==273 or event.key==119:

        if direct==’left’ or direct==’right’:

          direct=’up’

      elif event.key==274 or event.key==115:

        if direct == ‘left’ or direct == ‘right’:

          direct=’down’

      elif event.key==276 or event.key==97:

        if direct == ‘up’ or direct == ‘down’:

          direct=’left’

      elif event.key==275 or event.key==100:

        if direct == ‘up’ or direct == ‘down’:

          direct=’right’

  #吃東西

  eat=(head.row==food.row and head.col==food.col)

  #重新產生食物

  if eat:

    food = gen_food()

  #處理身子

  #1.把原來的頭,插入到snakes的頭上

  snakes.insert(0, head.copy())

  #2.把snakes的最後一個刪掉

  if not eat:

    snakes.pop()

  #移動

  if direct==’left’:

    head.col-=1

  elif direct==’right’:

    head.col+=1

  elif direct==’up’:

    head.row-=1

  elif direct==’down’:

    head.row+=1

  #檢測

  dead=False

  #1.撞牆

  if head.col0 or head.row0 or head.col=COL or head.row=ROW:

    dead=True

  #2.撞自己

  for snake in snakes:

    if head.col==snake.col and head.row==snake.row:

      dead=True

      break

  if dead:

    print(‘死了’)

    quit=False

  #渲染——畫出來

  #背景

  pygame.draw.rect(window, bg_color, (0,0,W,H))

  #蛇頭

  for snake in snakes:

    rect(snake, snake_color)

  rect(head, head_color)

  rect(food, food_color)

  #

  pygame.display.flip()

  #設置幀頻(速度)

  clock.tick(8)

#收尾工作

這是一個簡易版貪吃蛇的代碼,雖然結構簡單,但是該有的功能都是完整的,可玩性也不錯

Python遊戲開發,Python實現貪吃蛇小遊戲與吃豆豆 附帶源碼

Python版本: 3.6.4

相關模塊:

pygame模塊;

以及一些Python自帶的模塊。

安裝Python並添加到環境變數,pip安裝需要的相關模塊即可。

貪吃蛇的 遊戲 規則應該不需要我多做介紹了吧T_T。寫個貪吃蛇 遊戲 其實還是很簡單的。首先,我們進行一下 遊戲 初始化:

然後定義一個貪吃蛇類:

其中head_coord用來記錄蛇頭所在位置,而tail_coords是一個二維數組,用來記錄所有蛇身的位置。一開始,貪吃蛇長為3,並且位置是隨機生成的。用戶通過 鍵來控制貪吃蛇的行動:

需要注意的是,貪吃蛇不能180 大拐彎,只能90 地拐彎。例如正在向左行動的貪吃蛇不能瞬間變成向右行動。具體而言,代碼實現如下:

然後,我們需要隨機生成一個食物,且需要保證該食物的位置不與貪吃蛇的位置相同:

在更新貪吃蛇的時候,如果它吃到了食物,則蛇身長加一,否則只是簡單的按照給定的方向行動而不改變蛇身長度:

同時,當貪吃蛇吃到食物時,需要重新生成一個新的食物:

最後,當貪吃蛇碰到牆壁或者蛇頭碰到蛇身時, 遊戲 結束:

並顯示一下 遊戲 結束界面:

玩家通過 鍵控制 遊戲 的主角吃豆人吃掉藏在迷宮內的所有豆子,並且不能被鬼魂抓到。

若能順利吃完迷宮內的所有豆子並且不被鬼魂抓到,則 遊戲 勝利,否則 遊戲 失敗。

逐步實現:

Step1:定義 遊戲 精靈類

首先,讓我們先來明確一下該 遊戲 需要哪些 遊戲 精靈類。

① 牆類

② 食物類(即豆豆)

③ 角色類

角色類包括吃豆人和鬼魂,鬼魂由電腦控制其運動軌跡,吃豆人由玩家控制其運動軌跡。

顯然,其均需具備更新角色位置和改變角色運動方向的能力,其源代碼如下:

Step2:設計 遊戲 地圖

利用Step1中定義的 遊戲 精靈類,我們就可以開始設計 遊戲 地圖了。由於時間有限,我只寫了一個關卡的 遊戲 地圖,有興趣的小夥伴可以在此基礎上進行擴展(在我的源代碼基礎上進行擴展是很方便滴~)。 遊戲 地圖的設計包括以下四方面內容:

① 創建牆

② 創建門(一開始關幽靈用的)

image.gif

③ 創建角色

④ 創建食物

因為食物不能和牆、門以及角色的位置重疊,所以為了方便設計 遊戲 地圖,要先創建完牆、門以及角色後再創建食物:

Step3:設計 遊戲 主循環

接下來開始設計 遊戲 主循環。首先是初始化:

然後定義主函數:

其中startLevelGame函數用於開始某一關 遊戲 ,其源代碼如下:

showText函數用於在 遊戲 結束或關卡切換時在 遊戲 界面中顯示提示性文字,其源代碼如下:

原創文章,作者:NYDXN,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/313765.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
NYDXN的頭像NYDXN
上一篇 2025-01-07 09:44
下一篇 2025-01-07 09:44

相關推薦

  • 如何查看Anaconda中Python路徑

    對Anaconda中Python路徑即conda環境的查看進行詳細的闡述。 一、使用命令行查看 1、在Windows系統中,可以使用命令提示符(cmd)或者Anaconda Pro…

    編程 2025-04-29
  • Python列表中負數的個數

    Python列表是一個有序的集合,可以存儲多個不同類型的元素。而負數是指小於0的整數。在Python列表中,我們想要找到負數的個數,可以通過以下幾個方面進行實現。 一、使用循環遍歷…

    編程 2025-04-29
  • Python中引入上一級目錄中函數

    Python中經常需要調用其他文件夾中的模塊或函數,其中一個常見的操作是引入上一級目錄中的函數。在此,我們將從多個角度詳細解釋如何在Python中引入上一級目錄的函數。 一、加入環…

    編程 2025-04-29
  • Python周杰倫代碼用法介紹

    本文將從多個方面對Python周杰倫代碼進行詳細的闡述。 一、代碼介紹 from urllib.request import urlopen from bs4 import Bea…

    編程 2025-04-29
  • Python計算陽曆日期對應周幾

    本文介紹如何通過Python計算任意陽曆日期對應周幾。 一、獲取日期 獲取日期可以通過Python內置的模塊datetime實現,示例代碼如下: from datetime imp…

    編程 2025-04-29
  • 蝴蝶優化演算法Python版

    蝴蝶優化演算法是一種基於仿生學的優化演算法,模仿自然界中的蝴蝶進行搜索。它可以應用於多個領域的優化問題,包括數學優化、工程問題、機器學習等。本文將從多個方面對蝴蝶優化演算法Python版…

    編程 2025-04-29
  • Python字典去重複工具

    使用Python語言編寫字典去重複工具,可幫助用戶快速去重複。 一、字典去重複工具的需求 在使用Python編寫程序時,我們經常需要處理數據文件,其中包含了大量的重複數據。為了方便…

    編程 2025-04-29
  • Python程序需要編譯才能執行

    Python 被廣泛應用於數據分析、人工智慧、科學計算等領域,它的靈活性和簡單易學的性質使得越來越多的人喜歡使用 Python 進行編程。然而,在 Python 中程序執行的方式不…

    編程 2025-04-29
  • python強行終止程序快捷鍵

    本文將從多個方面對python強行終止程序快捷鍵進行詳細闡述,並提供相應代碼示例。 一、Ctrl+C快捷鍵 Ctrl+C快捷鍵是在終端中經常用來強行終止運行的程序。當你在終端中運行…

    編程 2025-04-29
  • Python清華鏡像下載

    Python清華鏡像是一個高質量的Python開發資源鏡像站,提供了Python及其相關的開發工具、框架和文檔的下載服務。本文將從以下幾個方面對Python清華鏡像下載進行詳細的闡…

    編程 2025-04-29

發表回復

登錄後才能評論