㈠ 沒分了…python貪吃蛇問題
這不是好的提問習慣。你應該指出哪些語句你不懂,然後有針對地提出問題。問之前至少你自己要努力過吧?
㈡ 怎樣從零開始用 Python 寫一個貪吃蛇
新建一個文本文檔,復制粘貼下面的代碼進去,保存,關閉,更改擴展名為html,用瀏覽器打開。這就是一個只用了一行代碼的貪吃蛇程序。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<canvas id="canvas" width="400" height="400"></canvas>
</head>
<body>
<script>
window.onkeydown=((ctx,snake,food,direction,move,draw)=>((loop,newFood,timer)=>Array.from({length:400}).forEach((_e,i)=>draw(ctx,i,"black"))||(timer=setInterval(()=>loop(newFood)||clearInterval(timer)||console.log(timer)||alert('Game Over'),200))&&(e=>direction=snake[1]-snake[0]==(move=[-1,-20,1,20][(e||event).keyCode-37]||direction)?direction:move))((newFood)=>snake.unshift(move=snake[0]+direction)&&snake.indexOf(move,1)>0||move<0||move>399||direction==1&&move%20==0||direction==-1&&move%20==19?false:(draw(ctx,move,"green")||move==food?newFood()&draw(ctx,food,"red"):draw(ctx,snake.pop(),"Black"))!==[],()=>Array.from({length:8000}).some(e=>snake.indexOf(food=~~(Math.random()*400))===-1)))(document.getElementById('canvas').getContext('2d'),[42,41],43,1,null,(ctx,node,color)=>(ctx.fillStyle=color)&ctx.fillRect(node%20*20+1,~~(node/20)*20+1,18,18));
</script>
</body>
</html>
㈢ 如何用Python寫一個貪吃蛇
以前在遠標寫過:from Tkinter import *
import tkMessageBox,sys
from random import randint
class Grid(object):
def __init__(self,master=None,window_width=800,window_height=600,grid_width=50,offset=10):
self.height = window_height
self.width = window_width
self.grid_width = grid_width
self.offset = offset
self.grid_x = self.width/self.grid_width
self.grid_y = self.height/self.grid_width
self.bg = "#EBEBEB"
self.canvas = Canvas(master, width=self.width+2*self.offset, height=self.height+2*self.offset, bg=self.bg)
self.canvas.pack()
self.grid_list()
def draw(self, pos, color,):
x = pos[0]*self.grid_width + self.offset
y = pos[1]*self.grid_width + self.offset
self.canvas.create_rectangle(x, y, x+self.grid_width, y+self.grid_width,fill=color,outline=self.bg)
def grid_list(self):
grid_list = []
for y in range(0,self.grid_y):
for x in range(0,self.grid_x):
grid_list.append((x,y))
self.grid_list = grid_list
class Food(object):
def __init__(self, Grid):
self.grid = Grid
self.color = "#23D978"
self.set_pos()
def set_pos(self):
x = randint(0,self.grid.grid_x - 1)
y = randint(0,self.grid.grid_y - 1)
self.pos = (x, y)
def display(self):
self.grid.draw(self.pos,self.color)
class Snake(object):
def __init__(self, Grid):
self.grid = Grid
self.body = [(10,6),(10,7),(10,8)]
self.direction = "Up"
self.status = ['run','stop']
self.speed = 300
self.color = "#5FA8D9"
self.food = Food(self.grid)
self.display_food()
self.gameover = False
self.score = 0
def available_grid(self):
return [i for i in self.grid.grid_list if i not in self.body[2:]]
def change_direction(self, direction):
self.direction = direction
def display(self):
for (x,y) in self.body:
self.grid.draw((x,y),self.color)
def display_food(self):
while(self.food.pos in self.body):
self.food.set_pos()
self.food.display()
def move(self):
head = self.body[0]
if self.direction == 'Up':
new = (head[0], head[1]-1)
elif self.direction == 'Down':
new = (head[0], head[1]+1)
elif self.direction == 'Left':
new = (head[0]-1,head[1])
else:
new = (head[0]+1,head[1])
if not self.food.pos == head:
pop = self.body.pop()
self.grid.draw(pop,self.grid.bg)
else:
self.display_food()
self.score += 1
self.body.insert(0,new)
if not new in self.available_grid():
self.status.reverse()
self.gameover = True
else:
self.grid.draw(new,color=self.color)
class SnakeGame(Frame):
def __init__(self,master=None, *args, **kwargs):
Frame.__init__(self, master)
self.master = master
self.grid = Grid(master=master,*args, **kwargs)
self.snake = Snake(self.grid)
self.bind_all("", self.key_release)
self.snake.display()
def run(self):
if not self.snake.status[0] == 'stop':
self.snake.move()
if self.snake.gameover == True:
message = tkMessageBox.showinfo("Game Over", "your score: %d" % self.snake.score)
if message == 'ok':
sys.exit()
self.after(self.snake.speed,self.run)
def key_release(self, event):
key = event.keysym
key_dict = {"Up":"Down","Down":"Up","Left":"Right","Right":"Left"}
if key_dict.has_key(key) and not key == key_dict[self.snake.direction]:
self.snake.change_direction(key)
self.snake.move()
elif key == 'p':
self.snake.status.reverse()
if __name__ == '__main__':
root = Tk()
snakegame = SnakeGame(root)
snakegame.run()
snakegame.mainloop()
㈣ 如何用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怎樣做貪吃蛇
ffffdfdfd
㈥ python貪吃蛇代碼中蛇的坐標是如何存儲的
牆有坐標撒,以左下角為坐標原點,蛇每走一步加入判斷:蛇方向是上,判斷蛇頭的位置是否與右上角的縱坐標相等,相等就是撞牆;其他方向類似。
蛇的身體是一個(x,y)的一系列坐標鏈表,每走一步除了判斷牆體,再判斷蛇頭的坐標-反向坐標,與坐標集合的第二個節點相比,是否相等,相等就是反向操作;再判斷蛇頭坐標+正向坐標,與每個節點是否相等,相等就是撞到自己。
㈦ 如何用Python寫一個貪吃蛇AI-CSDN論壇
但如果僅僅是貪吃蛇游戲,那麼它就沒有什麼讓人漲姿勢的地方了。 問題的關鍵在於,圖片中的貪吃蛇真的很貪吃XD,它把矩形中出現的食物吃了個遍, 然後華麗麗地把整個矩形填滿,真心是看得賞心悅目。作為一個CSer,
㈧ 100行Python代碼,輕松完成貪吃蛇小游戲
你是想讓我們向你提問題?你這個放錯地方了,應該發布到自己的博客或論壇上面才對