一 相關知識
1 randrange()函數
- 功能:randrange() 方法返回指定遞增基數集合中的一個隨機數,基數默認值為1。
- 語法:random.randrange ([start,] stop [,step])
- 注意:randrange()是不能直接訪問的,需要導入 random 模塊,然后通過 random 靜態對象調用該方法。
- 方法一:import random
- 方法二:from random import randrange
- 注意:randrange()是不能直接訪問的,需要導入 random 模塊,然后通過 random 靜態對象調用該方法。
- 參數:
- start -- 指定范圍內的開始值,包含在范圍內。
- stop -- 指定范圍內的結束值,不包含在范圍內。
- step -- 指定遞增基數。
- 返回值:從給定的范圍返回隨機項。
2 turtle.tracer()函數
- 功能:啟用/禁用海龜動畫並設置刷新圖形的延遲時間。——可看作是為了加快/減慢作圖的,你可以在里面添加參數
- 語法:turtle.tracer(n=None,delay=None)
- 如果指定 n 值,則只有每第 n 次屏幕刷新會實際執行。(可被用來加速復雜圖形的繪制。) 如果調用時不帶參數,則返回當前保存的 n 值。第二個參數設置延遲值
- n -- 非負整型數;delay -- 非負整型數
- turtle.tracer(False)或者duturtle.tracer(0):圖形將一次性畫好
- turtle.tracer(1):圖形按照正常速度進行,可有可無
- turtle.tracer(4):在循環中,圖形將一次畫出4次循環的圖
3 turtle.update():執行一次 TurtleScreen 刷新。在禁用追蹤時使用。
4 turtle.clear():從中刪除所有海龜的全部繪圖。將已清空的 TurtleScreen 重置為初始狀態: 白色背景,無背景片,無事件綁定並啟用追蹤。
5 turtle.ontimer(fun,t):安裝一個計時器,在tms后調用fun函數
二 分析過程https://www.jb51.net/article/153788.htm
貪吃蛇的身體是由list構成的,list中每一個元組代表貪吃蛇在棋盤上的坐標,我們只需在這些位置畫上圖案,就能制作出一條圓滾滾的貪吃蛇來。但是如果想讓貪吃蛇活蹦亂跳,我們就要寫一個move函數。
1貪吃蛇怎么移動
如果貪吃蛇沒吃到食物,那么我們就刪除list中最后一個坐標,再在蛇頭部分插入新的位置。如何確定新的位置呢,我們就要設定貪吃蛇移動的方向(x,y),將原蛇頭位置的坐標在移動方向上進行加減操作。這樣貪吃蛇就實現了向前移動的目標。如果貪吃蛇恰好吃到了食物,唯一的不同就是不需要刪除貪吃蛇尾部的元素。其中需要注意的是,貪吃蛇不能朝着當前移動方向的反方向移動。體現在代碼中,就是當前方向與改變方向的乘積不能為負值。
2 如何知道貪吃蛇吃到了食物呢
如果貪吃蛇蛇頭的坐標與食物的坐標重合的話,貪吃蛇就吃到了食物。如果貪吃蛇吃到了食物,就在棋盤上隨機更新食物。如果隨機生成的食物的坐標,恰好與貪吃蛇的位置重合的話,就繼續隨機產生坐標,直到確保與貪吃蛇的坐標不同的時候。
3 如何知道游戲失敗了呢
如果貪吃蛇蛇頭的坐標與邊框的坐標重合的話,蛇卒。如果貪吃蛇各個部分的坐標有重合的話,就說明貪吃蛇咬到了自己,游戲結束。
三 代碼
代碼功能都是齊全的,然后按鍵控制onkey函數中的參數是'Right',我一直以為是通過輸入這個字符串控制貪吃蛇移動的,結果它的意思是按鍵盤上的向上的方向鍵,並不是輸入字符串,所以我一直沒辦法通過鍵盤控制貪吃蛇的移動方向,導致我還以為是代碼有問題。。。。
然后跟原來的代碼相比,我加了一部分改變食物位置的changeFood函數,原理跟改變貪吃蛇移動方向的changeSnake函數一致。
該貪吃蛇程序是利用turtle庫完成的,網上很多貪吃蛇代碼都是利用pygame庫實現的,那些資料里面可能游戲開始結束設置的比較全面一點,但是用turtle庫感覺簡單了好多有木有!!!
1 """Snake,classic arcade game 2 Exercise 3 1. How do you make the snake faster or slower? 通過改變ontimer(move,500)語句中的第二個參數 4 2. How can you make the snake go around the edges?可將初始坐標定為(180,0)、(-180,0)、(0,180)、(0,-180)、(180,180)、(-180,180)、(180,-180)、(-180,-180) 5 3 How would you move the food? 通過onkey函數調用changeFood函數改變食物坐標 6 4. Change the snake to respond to arrow keys. 已經實現了吧,Right、Left、Up、Down分別對應向右、向左、向上、向下箭頭 7 """ 8 9 from turtle import * # 導入turtle庫,此種方式導入可直接使用庫內函數,不使用trutle.做前導 10 from random import randrange # 從random庫中導入randrange()函數,使food隨機出現 11 from freegames import square,vector # 從freegames庫中導入square和vector,用square正方形表示food、snake,用vector這個二維向量表示snake 12 13 food = vector(0,0) # 初始化food變量,用來表示第一個食物在坐標為(0,0)處 14 snake = [vector(180,0)] # 初始化snake,而且snake是列表,其元素是向量 15 aim = vector(0,-10) # 用來控制貪吃蛇的移動方向和距離 16 aim2 = vector(10,10) # 用來控制食物移動的方向和距離 17 18 19 def changeSnake(x,y): # 改變貪吃蛇移動方向部分,通過onkey函數和lambda表達式調用changeSnake函數,獲得下一個移動坐標(x,y) 20 "Change snake direction." 21 aim.x = x # 將x的值賦給aim.x改變貪吃蛇目標的橫坐標 22 aim.y = y # 將y的值賦給aim.x改變貪吃蛇目標的縱坐標 23 24 def changeFood(x,y): # 改變食物移動方向部分,通過onkey函數和lambda表達式調用changeFood函數,獲得下一個移動坐標(x/2,y/2) 25 "Change food direction." 26 aim2.x = x/2 # 將x/2的值賦給aim2.x改變食物目標的橫坐標 27 aim2.y = y/2 # 將y/2的值賦給aim2.y改變食物目標的縱坐標 28 29 def inside(head): # 判斷貪吃蛇有沒有碰到畫布邊界部分,限制貪吃蛇的移動范圍 30 "Return True if head inside the boundaries." 31 return -200 < head.x < 190 and -200 < head.y < 190 32 33 def move(): 34 "Move snake forward one segment." 35 # 更改食物和貪吃蛇蛇頭坐標 36 head = snake[-1].copy() # 表示復制snake列表的最后一個元素,這里用列表的最后一個元素表示蛇頭 37 head.move(aim) # 每調用一次move函數,貪吃蛇就移動到(head.x+aim.x,head.y+aim.y)的位置 38 food.move(aim2) # 每調用一次move函數,食物就移動到(food.x+aim2.x,food.y+aim2.y)的位置 39 40 #判斷游戲是否結束 41 if not inside(head) or head in snake: # 判斷是否結束游戲部分:head碰到牆壁|頭碰到身體 42 square(head.x,head.y,9,'red') # 將貪吃蛇蛇頭的正方形改成紅色,表示游戲結束 43 update() # 執行一次屏幕刷新 44 return # 用來終止程序的運行,其后語句不會再執行 45 46 # 更新貪吃蛇的身體 47 snake.append(head) # 蛇頭坐標已經更改,將新的蛇頭目標添加到snake列表中 48 49 if head == food: # snake吃到food,下一個food會隨機出現在畫布的另一個地方 50 print('Snake',len(snake)) # 打印貪吃蛇的長度 51 food.x = randrange(-15,15) * 10 # 隨機產生食物橫坐標 52 food.y = randrange(-15,15) * 10 # 隨機產生食物縱坐標 53 else: # snake沒有吃到food 54 snake.pop(0) # snake沒有吃到食物,所以將snake列表最后一個元素刪除,保持貪吃蛇長度不變,這里用列表的第一個元素表示蛇尾 55 56 # 清空畫布,重新畫好食物和貪吃蛇的位置,利用ontimer函數調用move函數,控制貪吃蛇進行下一次移動 57 clear() # 相當於刷新操作,將所有的繪圖全部刪了 58 59 for body in snake: # 重新畫出貪吃蛇的身體部分 60 square(body.x,body.y,9,'black') # 黑色方塊表示貪吃蛇的身體 61 square(food.x,food.y,9,'green') # 畫出食物,綠色方塊表示食物 62 update() # 執行一次屏幕刷新 63 ontimer(move,500) # 經過500ms后繼續調用move函數 64 65 setup(420,420,370,0) # 初始畫布尺寸 66 hideturtle() # 隱藏鼠標 67 tracer(False) # 保證畫圖操作(食物和貪吃蛇身體)一次性完成 68 move() 69 listen() # 監聽,屏幕聚焦 70 # 綁定鍵盤方向,改變貪吃蛇的移動方向 71 onkey(lambda:changeSnake(10,0),'Right') # 右轉,Right是鍵盤方向鍵的右鍵,不是輸入單詞Right 72 onkey(lambda:changeSnake(-10,0),'Left') # 左轉 73 onkey(lambda:changeSnake(0,10),'Up') # 向上走 74 onkey(lambda:changeSnake(0,-10),'Down') # 向下走 75 # 綁定鍵盤方向,改變食物的移動方向 76 onkey(lambda:changeFood(10,0),'D') # 右轉,在鍵盤上輸入大寫字母'D' 77 onkey(lambda:changeFood(-10,0),'A') # 左轉 78 onkey(lambda:changeFood(0,10),'W') # 向上走 79 onkey(lambda:changeFood(0,-10),'S') # 向下走 80 81 done()