怎樣從零開始用 Python 寫一個貪吃蛇?

PS: 感覺好像被當成伸手黨了 ,題主我一開始也是有個想法的,只是感覺運行效率太渣,來學習學習各位的方法。

還有現在忙著高考,也沒多少時間實踐這個貪吃蛇程序了。 但還是感謝各位提出的思路。

==--------以下為原問題--------==

首先說明「從零開始」不是指零基礎

首先說明「從零開始」不是指零基礎

首先說明「從零開始」不是指零基礎

是指從頭寫起。

1. 使用現有模塊的話有什麼模塊推薦?

2. 不使用現有模塊的話怎麼自己從底層開始寫?需要具備哪些知識?


大一,標準庫,沒有用到pygame。 代碼很醜,見諒。

# -*- coding:utf-8 -*-
# __author__ = "wj"
from Tkinter import *
import random
from time import *
import thread
import sys
sys.setrecursionlimit(sys.maxint)

def callback1(): # difficulty
global diff
diff = difficulty(0)

def callback11(): # difficulty
global diff
diff = difficulty(1)

def callback12(): # difficulty
global diff
diff = difficulty(2)

def callback2(): # start
start()

def callback3(): # exit
root.destroy()

def callback4(event): # up
m.append(0)

def callback5(event): # down
m.append(1)

def callback6(event): # left
m.append(2)

def callback7(event): # right
m.append(3)

def difficulty(x=2):
if x == 0:
return 0.5
if x == 1:
return 0.3
if x == 2:
return 0.1

def createfood():
x = random.randint(0, 39)
y = random.randint(0, 29)
return (x, y)

def pan(now):
for i in range(len(l)):
if lx[i] == now[0] * 20 and ly[i] == now[1] * 20:
return False

def food():
now = createfood()
while pan(now):
now = createfood()
r = f.create_rectangle(now[0] * 20, now[1] * 20, now[0] * 20 + 20, now[1] * 20 + 20, fill="red")
f.update()
z.append(r)
lxf.append(now[0] * 20)
lyf.append(now[1] * 20)

def gameover():
if lx[-1] &> 780 or lx[-1] &< 0 or ly[-1] &> 580 or ly[-1] &< 0: try: f.create_text(400, 250, text="Game Over", font=("Fixdsys", 40), fill="red", justify=CENTER) f.create_text(400, 330, text="Ur Score : " + str(len(l) - 3), font=("Fixdsys", 40), fill="blue", justify=CENTER) f.create_text(400, 400, text="please click exit", fill="black",font=("Fixdsys", 20)) except: print "Game Over" f.create_text(400,400,text="please click exit",fill="black",font=("Fixdsys", 20)) sleep(100) for i in range(len(l) - 1): if lx[i] == lx[-1] and ly[i] == ly[-1]: try: f.create_text(400, 250, text="Game Over", font=("Fixdsys", 40), fill="red", justify=CENTER) f.create_text(400, 330, text="Ur Score : " + str(len(l) - 3), font=("Fixdsys", 40), fill="blue",justify=CENTER) f.create_text(400, 400, text="please click exit", fill="black",font=("Fixdsys", 20)) except: print "Game Over" f.create_text(400, 400, text="please click exit", fill="black",font=("Fixdsys", 20)) sleep(100) #控制移動函數 def move(): if m[-1] == 0: up_move1() m.pop(0) elif m[-1] == 1: down_move1() m.pop(0) elif m[-1] == 2: left_move1() m.pop(0) elif m[-1] == 3: right_move1() m.pop(0) def crash(): for i in range(len(l) - 1): if lx[i] == lx[-1] and ly[i] == ly[-1]: return True #自動移動 def up_move(): if lx[-1] &< 0 or lx[-1]&>780 or ly[-1]&<0 or ly[-1]&>580:
pass
elif crash():
pass
else:
r = f.create_rectangle(lx[-1], ly[-1] - 20, lx[-1] + 20, ly[-1], fill="white")
l.append(r)
lx.append(lx[-1])
ly.append(ly[-1] - 20)
gameover()
if lx[-1] != lxf[-1] or ly[-1] != lyf[-1]: # 沒碰到
f.delete(l[0])
l.pop(0)
lx.pop(0)
ly.pop(0)
else: # 碰到了
f.delete(z[-1])
food()
f.update()
if len(m) != 0:
thread.start_new_thread(move, ())
sleep(diff)
move_straight()

#自動移動
def down_move():
if lx[-1] &< 0 or lx[-1]&>780 or ly[-1]&<0 or ly[-1]&>580:
pass
elif crash():
pass
else:
r = f.create_rectangle(lx[-1], ly[-1] + 20, lx[-1] + 20, ly[-1] + 40, fill="white")
f.update()
l.append(r)
lx.append(lx[-1])
ly.append(ly[-1] + 20)
gameover()
if lx[-1] != lxf[-1] or ly[-1] != lyf[-1]: # 沒碰到
f.delete(l[0])
l.pop(0)
lx.pop(0)
ly.pop(0)
else: # 碰到了
f.delete(z[-1])
food()
f.update()
if len(m) != 0:
thread.start_new_thread(move, ())
sleep(diff)
move_straight()

#自動移動
def left_move():
if lx[-1] &< 0 or lx[-1]&>780 or ly[-1]&<0 or ly[-1]&>580:
pass
elif crash():
pass
else:
r = f.create_rectangle(lx[-1] - 20, ly[-1], lx[-1], ly[-1] + 20, fill="white")
f.update()
l.append(r)
lx.append(lx[-1] - 20)
ly.append(ly[-1])
gameover()
if lx[-1] != lxf[-1] or ly[-1] != lyf[-1]: # 沒碰到
f.delete(l[0])
l.pop(0)
lx.pop(0)
ly.pop(0)
else: # 碰到了
f.delete(z[-1])
food()
f.update()
if len(m) != 0:
thread.start_new_thread(move, ())
sleep(diff)
move_straight()

#自動移動
def right_move():
if lx[-1] &< 0 or lx[-1]&>780 or ly[-1]&<0 or ly[-1]&>580:
pass
elif crash():
pass
else:
r = f.create_rectangle(lx[-1] + 20, ly[-1], lx[-1] + 40, ly[-1] + 20, fill="white")
l.append(r)
lx.append(lx[-1] + 20)
ly.append(ly[-1])
gameover()
if lx[-1] != lxf[-1] or ly[-1] != lyf[-1]: # 沒碰到
f.delete(l[0])
f.update()
l.pop(0)
lx.pop(0)
ly.pop(0)
else: # 碰到了
f.delete(z[-1])
food()
f.update()
if len(m) != 0:
thread.start_new_thread(move, ())
sleep(diff)
move_straight()

#自動移動
def move_straight(): # 坐標比較 然後調用四個方向移動的函數
if lx[-1] == lx[-2] and ly[-1] &> ly[-2]:
down_move()
if lx[-1] == lx[-2] and ly[-1] &< ly[-2]: up_move() if lx[-1] &> lx[-2] and ly[-1] == ly[-2]:
right_move()
if lx[-1] &< lx[-2] and ly[-1] == ly[-2]: left_move() #控制移動函數 def up_move1(): if lx[-1] &< 0 or lx[-1]&>780 or ly[-1]&<0 or ly[-1]&>580:
pass
elif crash():
pass
r = f.create_rectangle(lx[-1], ly[-1] - 20, lx[-1] + 20, ly[-1], fill="white")
l.append(r)
lx.append(lx[-1])
ly.append(ly[-1] - 20)
gameover()
if lx[-1] != lxf[-1] or ly[-1] != lyf[-1]: # 沒碰到
f.delete(l[0])
l.pop(0)
lx.pop(0)
ly.pop(0)
else: # 碰到了
f.delete(z[-1])
food()
f.update()

#控制移動函數
def down_move1():
if lx[-1] &< 0 or lx[-1]&>780 or ly[-1]&<0 or ly[-1]&>580:
pass
elif crash():
pass
else:
r = f.create_rectangle(lx[-1], ly[-1] + 20, lx[-1] + 20, ly[-1] + 40, fill="white")
f.update()
l.append(r)
lx.append(lx[-1])
ly.append(ly[-1] + 20)
gameover()
if lx[-1] != lxf[-1] or ly[-1] != lyf[-1]: # 沒碰到
f.delete(l[0])
l.pop(0)
lx.pop(0)
ly.pop(0)
else: # 碰到了
f.delete(z[-1])
food()
f.update()

#控制移動函數
def left_move1():
if lx[-1] &< 0 or lx[-1]&>780 or ly[-1]&<0 or ly[-1]&>580:
pass
elif crash():
pass
else:
r = f.create_rectangle(lx[-1] - 20, ly[-1], lx[-1], ly[-1] + 20, fill="white")
f.update()
l.append(r)
lx.append(lx[-1] - 20)
ly.append(ly[-1])
gameover()
if lx[-1] != lxf[-1] or ly[-1] != lyf[-1]: # 沒碰到
f.delete(l[0])
l.pop(0)
lx.pop(0)
ly.pop(0)
else: # 碰到了
f.delete(z[-1])
food()
f.update()

#控制移動函數
def right_move1():
if lx[-1] &< 0 or lx[-1]&>780 or ly[-1]&<0 or ly[-1]&>580:
pass
elif crash():
pass
else:
r = f.create_rectangle(lx[-1] + 20, ly[-1], lx[-1] + 20 + 20, ly[-1] + 20, fill="white")
l.append(r)
lx.append(lx[-1] + 20)
ly.append(ly[-1])
gameover()
if lx[-1] != lxf[-1] or ly[-1] != lyf[-1]: # 沒碰到
f.delete(l[0])
f.update()
l.pop(0)
lx.pop(0)
ly.pop(0)
else: # 碰到了
f.delete(z[-1])
food()
f.update()

def start():
global r1
global r2
l.append(r1)
l.append(r2)
lx.append(0)
lx.append(20)
ly.append(0)
ly.append(0)
food()
move_straight()

root = Tk()
root.title("snake")
root.geometry("800x600")
m = Menu(root)
root.config(menu=m)
m.add_command(label="Start", command=callback2)
difmenu = Menu(m)
m.add_cascade(label="Difficulty", menu=difmenu)
difmenu.add_command(label="Easy", command=callback1)
difmenu.add_separator()
difmenu.add_command(label="Normal", command=callback11)
difmenu.add_separator()
difmenu.add_command(label="Difficult", command=callback12)
paumenu = Menu(m)
m.add_cascade(label="Pause", menu=paumenu)
m.add_command(label="Exit", command=callback3)
f = Canvas(root, width=800, height=600, bg="white")
f.bind("&", callback4)
f.bind("&", callback5)
f.bind("&", callback6)
f.bind("&", callback7)
f.focus_set()
f.pack()

#這裡需要一張底色不為白色、gif格式的圖片,可以自行調整(我劃的線是白色)
#pic = PhotoImage(file="C:UserswjDesktop\snake.gif")
#f.create_image(400, 300, image=pic)

for i in range(20 - 1, 600 - 1, 20):
f.create_line(0, i, 800, i, smooth=0, fill="white")

for i in range(20 - 1, 800 - 1, 20):
f.create_line(i, 0, i, 600, smooth=0, fill="white")

l = []
lx = []
ly = []
lxf = []
lyf = []
z = []
m = []
r1 = f.create_rectangle(0, 0, 20, 20, fill="white")
r2 = f.create_rectangle(20, 0, 40, 20, fill="white")
diff = difficulty()
root.mainloop()


pygame

100來行就可以了

源碼:

codetimer/Snake


一、前言

看了提問者在另一個回答的評論

真的覺得提問者應該試試pygame。「工欲善其事,必先利其器。」個人認為,python與其他編程語言相比,亮點在於它有豐富的第三方庫。比如用python做爬蟲,原生庫urllib2和第三方庫requests相比,哪個效率更高?

二、推薦

pygame顧名思義,python和game相結合,專註於2D遊戲開發。pygame很容易入門。網上有一些不錯的教程,在此推薦我的入門教程:-Daydayblog-第1頁(貌似博客不見了?——2016.10.15)

博客提供了16個章節:

  • pygame遊戲編程(1)--pygame簡介及安裝

  • pygame遊戲編程(2)--第一個pygame程序

  • pygame遊戲編程(3)--文本列印及字體

  • pygame遊戲編程(4)--像素、顏色和圖像

  • pygame遊戲編程(5)--surface對象

  • pygame遊戲編程(6)--窗口顯示

  • pygame遊戲編程(7)--繪製幾何圖像

  • pygame遊戲編程(8)--event事件

  • pygame遊戲編程(9)--動畫之直線運動

  • pygame遊戲編程(10)--動畫之向量

  • pygame遊戲編程(11)--人機交互

  • pygame遊戲編程(12)--人工智慧

  • pygame遊戲編程(13)--聲音

  • pygame遊戲編程(14)--音樂播放器

  • pygame遊戲編程(15)--貪吃蛇遊戲

三、貪吃蛇

沒錯,博客作者提供了如何使用pygame開發貪吃蛇的教程,詳見pygame遊戲編程(16)--貪吃蛇遊戲-pygame教程-Daydayblog,作者程序運行界面如下:

貪吃蛇主要包括以下幾個方面:

  • 物體表示:蛇和蘋果如何存儲和顯示、蛇如何移動和吃蘋果變長;

  • 字體顯示:提示玩家該如何操作,顯示玩家的分數;

  • 人機交互:使用鍵盤的方向鍵來控制蛇的移動;

  • 矩形繪圖:繪製各種基本的圖形來組成圖像。

使用pygame開發貪吃蛇,您只需要先學會:

  • pygame簡介及安裝
  • surface對象
  • 窗口顯示
  • 繪製幾何圖形
  • event事件
  • 人機交互

四、成果

pygame開發2D遊戲簡直不能太簡單,我粗略看了教程之後,就自主完成兩個遊戲開發:

1、貪吃蛇

附上本人貪吃蛇遊戲代碼(很多細節沒處理好,勿噴。)

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys,pygame,random
from pygame.locals import *

windowWidth=600
windowHeight=600
cellSize=20
head = 0

def main():
#初始化
pygame.init()
global screen
screen=pygame.display.set_mode((windowWidth,windowHeight))
pygame.display.set_caption("Greedy Snake")
gameStart()
FPS=pygame.time.Clock()
startX=cellSize*random.randint(8,windowWidth/cellSize-8)
startY=cellSize*random.randint(8,windowHeight/cellSize-8)

snake=[{"x": startX , "y": startY},
{"x": startX - 1 * cellSize, "y": startY},
{"x": startX - 2 * cellSize, "y": startY},
{"x": startX - 3 * cellSize, "y": startY}]
appleX = cellSize * random.randint(0, windowWidth / cellSize)
appleY = cellSize * random.randint(0, windowHeight / cellSize)

while True:
FPS.tick(15)
for event in pygame.event.get():
if event.type==QUIT:
pygame.quit()
sys.exit()
if event.type==KEYDOWN:
turn(snake,event)
move(snake)
if snake[head]["x"]==appleX and snake[head]["y"]==appleY:
appleX = cellSize * random.randint(0, windowWidth / cellSize)
appleY = cellSize * random.randint(0, windowHeight / cellSize)
eat(snake)

if snake[head]["x"]&<0 or snake[head]["x"]&>windowWidth or snake[head]["y"]&<0 or snake[head]["y"]&>windowHeight:
gameOver(snake)
for body in snake[1:]:
if body==snake[head]:
gameOver(snake)

screen.fill((0, 150, 0))
drawgrid()
drawSnake(snake)
pygame.draw.rect(screen, (255, 0, 0), (appleX, appleY, cellSize, cellSize))

pygame.display.update()

#繪製網格
def drawgrid():
for i in xrange(cellSize,windowWidth,cellSize):
pygame.draw.line(screen,(0,255,0),(i,0),(i,windowHeight),1)
for j in xrange(cellSize,windowHeight,cellSize):
pygame.draw.line(screen,(0,255,0),(0,j),(windowWidth,j),1)

#繪製蛇
def drawSnake(snake):
for cood in snake:
pygame.draw.rect(screen,(150,150,0),(cood["x"],cood["y"],cellSize,cellSize))
pygame.draw.rect(screen, (250, 250, 0), (snake[head]["x"], snake[head]["y"], cellSize, cellSize))

def turn(snake,event):
# 上下轉向
if snake[head]["y"] == snake[1]["y"]:
if event.key == K_UP:
del snake[-1]
newHead = {"x": snake[head]["x"], "y": snake[head]["y"] - cellSize}
snake.insert(0, newHead)

elif event.key == K_DOWN:
del snake[-1]
newHead = {"x": snake[head]["x"], "y": snake[head]["y"] + cellSize}
snake.insert(0, newHead)

# 左右轉向
if snake[head]["x"] == snake[1]["x"]:
if event.key == K_LEFT:
del snake[-1]
newHead = {"x": snake[head]["x"] - cellSize, "y": snake[head]["y"]}
snake.insert(0, newHead)

if event.key == K_RIGHT:
del snake[-1]
newHead = {"x": snake[head]["x"] + cellSize, "y": snake[head]["y"]}
snake.insert(0, newHead)

def move(snake):
# 向左運動
if snake[head]["x"] &< snake[1]["x"]: del snake[-1] newHead = {"x": snake[head]["x"] - cellSize, "y": snake[head]["y"]} snake.insert(0, newHead) # 向右運動 elif snake[head]["x"] &> snake[1]["x"]:
del snake[-1]
newHead = {"x": snake[head]["x"] + cellSize, "y": snake[head]["y"]}
snake.insert(0, newHead)
# 向上運動
elif snake[head]["y"] &< snake[1]["y"]: del snake[-1] newHead = {"x": snake[head]["x"], "y": snake[head]["y"] - cellSize} snake.insert(0, newHead) # 向下運動 elif snake[head]["y"] &> snake[1]["y"]:
del snake[-1]
newHead = {"x": snake[head]["x"], "y": snake[head]["y"] + cellSize}
snake.insert(0, newHead)

def eat(snake):
# 向左運動
if snake[head]["x"] &< snake[1]["x"]: newHead = {"x": snake[head]["x"] - cellSize, "y": snake[head]["y"]} snake.insert(0, newHead) # 向右運動 elif snake[head]["x"] &> snake[1]["x"]:
newHead = {"x": snake[head]["x"] + cellSize, "y": snake[head]["y"]}
snake.insert(0, newHead)
# 向上運動
elif snake[head]["y"] &< snake[1]["y"]: newHead = {"x": snake[head]["x"], "y": snake[head]["y"] - cellSize} snake.insert(0, newHead) # 向下運動 elif snake[head]["y"] &> snake[1]["y"]:
newHead = {"x": snake[head]["x"], "y": snake[head]["y"] + cellSize}
snake.insert(0, newHead)

def gameStart():
screen.fill((0, 150, 0))
drawgrid()
fontObj1 = pygame.font.Font("freesansbold.ttf", 60)
textSurfaceObj1 = fontObj1.render("Greedy Snake", True, (255,255,255))
textRectObj1 = textSurfaceObj1.get_rect()
textRectObj1.center = (windowWidth/2, windowHeight/3)
screen.blit(textSurfaceObj1,textRectObj1)

fontObj2 =pygame.font.Font("freesansbold.ttf", 30)
textSurfaceObj2 = fontObj2.render("Devloper: JIE ", True,(0, 0, 0))
textRectObj2 = textSurfaceObj2.get_rect()
textRectObj2.center = (windowWidth/2, windowHeight*2/3)
screen.blit(textSurfaceObj2,textRectObj2)

pygame.display.update()
flag=True
while(flag):
for event in pygame.event.get():
if event.type==QUIT:
pygame.quit()
sys.exit()
if event.type==KEYDOWN:
if event.key==K_SPACE:
flag=False

def gameOver(snake):
screen.fill((0, 150, 0))
drawgrid()
fontObj = pygame.font.Font("freesansbold.ttf", 60)
textSurfaceObj1 = fontObj.render("Game over!", True, (255,0,0))
textRectObj1 = textSurfaceObj1.get_rect()
textRectObj1.center = (windowWidth/3, windowHeight/3)
screen.blit(textSurfaceObj1,textRectObj1)

textSurfaceObj2 = fontObj.render("Score: %s" % (len(snake)-4), True, (255, 0, 0))
textRectObj2 = textSurfaceObj2.get_rect()
textRectObj2.center = (windowWidth*2/3, windowHeight*2/3)
screen.blit(textSurfaceObj2,textRectObj2)

pygame.display.update()
while(True):
for event in pygame.event.get():
if event.type==QUIT:
pygame.quit()
sys.exit()

if __name__ == "__main__":
main()

2、打飛機

附上本人打飛機遊戲代碼(很多細節沒處理好,勿噴。)

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys,pygame,random
from pygame.locals import *

windowWidth=420
windowHeight=600
cellSize=20

shots=[]#飛行的子彈
enemys=[]#飛行的敵機

def main():
#初始化
global shoted
shoted= 0
global enemyed
enemyed = 0
pygame.init()
pygame.key.set_repeat(10) #重複響應一個按鍵
global screen,guard
screen=pygame.display.set_mode((windowWidth,windowHeight))
pygame.display.set_caption("aircraft")
gamestart()
FPS=pygame.time.Clock()
guard=[{"x":windowWidth/2-cellSize/2,"y":windowHeight-cellSize},#中0
{"x":windowWidth/2-cellSize/2,"y":windowHeight-2*cellSize},#上1
{"x": windowWidth / 2-cellSize*3/2, "y": windowHeight - cellSize},#左2
{"x": windowWidth / 2+cellSize/2, "y": windowHeight - cellSize}]#右3

while True:
screen.fill((0, 0, 0))
FPS.tick(5)
gamemedium()
for event in pygame.event.get():
if event.type==QUIT:
pygame.quit()
sys.exit()
if event.type==KEYDOWN:
#飛機左移
if event.key==K_LEFT and guard[2]["x"]&>-1:
for body in guard:
body["x"]-=cellSize
#飛機右移
if event.key == K_RIGHT and guard[3]["x"] &< windowWidth: for body in guard: body["x"] += cellSize #發射子彈 if event.key==K_UP: shoted+=1 shot={"x":guard[1]["x"],"y":guard[1]["y"]} shots.insert(0,shot) #子彈飛行 if shots != [] : for s in shots: s["y"]-=2*cellSize flag=True while(flag and shots!=[]): flag=False if shots[-1]["y"]&<0: del shots[-1] flag=True #產生敵機 if random.randint(0,1)==0: newenemy={"x":cellSize*random.randint(0,windowWidth/cellSize-1),"y":0} enemys.insert(0,newenemy) if enemys!=[]: for enemy in enemys: enemy["y"] += 0.5*cellSize #敵機飛行速度 drawenemys() delshots=[] delenemys=[] for i in xrange(len(shots)): for j in xrange(len(enemys)): if len(shots) != [] and len(enemys) != []: if shots[i]["x"]==enemys[j]["x"] and shots[i]["y"]&windowHeight-cellSize:
gameover()

drawshots()
#drawgrid()
drawguard()
pygame.display.update()

#繪製網格
def drawgrid():
for i in xrange(cellSize,windowWidth,cellSize):
pygame.draw.line(screen,(255,255,255),(i,0),(i,windowHeight),1)
for j in xrange(cellSize,windowHeight,cellSize):
pygame.draw.line(screen,(255,255,255),(0,j),(windowWidth,j),1)

#繪製自己的戰機
def drawguard():
for body in guard:
pygame.draw.rect(screen, (255, 255, 255), (body["x"], body["y"], cellSize, cellSize))

#繪製子彈
def drawshots():
for s in shots:
pygame.draw.rect(screen, (255, 255, 255), (s["x"]+cellSize/3, s["y"]+cellSize/4, cellSize / 3, cellSize/2))

#繪製敵機
def drawenemys():
for e in enemys:
pygame.draw.rect(screen, (255, 255, 255), (e["x"], e["y"], cellSize, cellSize/2))
pygame.draw.rect(screen, (255, 255, 255), (e["x"]+cellSize/4, e["y"]+cellSize/2, cellSize/2, cellSize / 2))

#遊戲開始界面
def gamestart():
#drawgrid()
fontObj1 = pygame.font.Font("freesansbold.ttf", 60)
textSurfaceObj1 = fontObj1.render("Aircraft", True, (255,255,255))
textRectObj1 = textSurfaceObj1.get_rect()
textRectObj1.center = (windowWidth/2, windowHeight/3)
screen.blit(textSurfaceObj1,textRectObj1)

fontObj2 =pygame.font.Font("freesansbold.ttf", 30)
textSurfaceObj2 = fontObj2.render("Developer : JIE", True,(255, 255, 255))
textRectObj2 = textSurfaceObj2.get_rect()
textRectObj2.center = (windowWidth/2, windowHeight*2/3)
screen.blit(textSurfaceObj2,textRectObj2)

pygame.display.update()
flag=True
while(flag):
for event in pygame.event.get():
if event.type==QUIT:
pygame.quit()
sys.exit()
if event.type==KEYDOWN:
if event.key==K_SPACE:
flag=False

#遊戲顯示界面
def gamemedium():
fontObj1 = pygame.font.Font("freesansbold.ttf", 20)
textSurfaceObj1 = fontObj1.render("enemy: %d"%enemyed , True, (255, 255, 0))
textRectObj1 = textSurfaceObj1.get_rect()
textRectObj1.center = (windowWidth-3*cellSize, 2*cellSize)
screen.blit(textSurfaceObj1, textRectObj1)

fontObj2 = pygame.font.Font("freesansbold.ttf", 20)
textSurfaceObj2 = fontObj2.render("shot: %d" % shoted, True, (255, 255, 0))
textRectObj2 = textSurfaceObj2.get_rect()
textRectObj2.center = (2*cellSize, 2*cellSize)
screen.blit(textSurfaceObj2, textRectObj2)

#遊戲結束界面
def gameover():
#drawgrid()
fontObj1 = pygame.font.Font("freesansbold.ttf", 50)
textSurfaceObj1 = fontObj1.render("Game over!", True, (255, 0, 0))
textRectObj1 = textSurfaceObj1.get_rect()
textRectObj1.center = (windowWidth / 2, windowHeight*3 / 8)
screen.blit(textSurfaceObj1, textRectObj1)

fontObj2 = pygame.font.Font("freesansbold.ttf", 30)
textSurfaceObj2 = fontObj2.render("shot: %d"%shoted, True, (255, 255, 255))
textRectObj2 = textSurfaceObj2.get_rect()
textRectObj2.center = (windowWidth / 2, windowHeight * 8 / 16)
screen.blit(textSurfaceObj2, textRectObj2)

fontObj3 = pygame.font.Font("freesansbold.ttf", 30)
textSurfaceObj3 = fontObj3.render("enemy: %d" % enemyed, True, (255, 255, 255))
textRectObj3 = textSurfaceObj3.get_rect()
textRectObj3.center = (windowWidth / 2, windowHeight * 9 / 16)
screen.blit(textSurfaceObj3, textRectObj3)

pygame.display.update()
flag = True
while (flag):
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_SPACE:
flag = False

if __name__ == "__main__":
main()


新建一個文本文檔,複製粘貼下面的代碼進去,保存,關閉,更改擴展名為html,用瀏覽器打開。這就是一個只用了一行代碼的貪吃蛇程序。

&
&
&
&
&Title&
&&
&

&
&
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==1move%20==0||direction==-1move%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));
&

&

&


歪個樓,放一下CovScript編寫的貪吃蛇。CovScript和Python差不多,但格式相對自由些。Github源碼地址

共183行,用到了Darwin圖形庫擴展

import darwin
const var head_pix=darwin.pixel("#",darwin.white,darwin.black)
const var body_pix=darwin.pixel("+",darwin.white,darwin.black)
const var food_pix=darwin.pixel("@",darwin.white,darwin.black)
var snake_body={}
var snake_head={0,0}
var food={0,0}
var heading=2
const var init_long=5
var god_mode=false
var cross_wall=false
const var hard=2
var score=0
darwin.load()
var pic=darwin.get_drawable()

function die()
var str0="You die!Your score is "+score+"."
var str1="Press any key to continue..."
loop
if(darwin.is_kb_hit())
darwin.get_kb_hit()
break
end
pic.clear()
pic.fill(darwin.pixel(" ",darwin.white,darwin.red))
pic.draw_string(0.5*(pic.get_width()-str0.size()),0.5*pic.get_height(),str0,darwin.pixel(" ",darwin.white,darwin.red))
pic.draw_string(0.5*(pic.get_width()-str1.size()),pic.get_height()-1,str1,darwin.pixel(" ",darwin.white,darwin.red))
darwin.update_drawable()
end
end

function gen_food()
var is_fit=true
while(is_fit)
food[0]=runtime.randint(0,pic.get_width()-1)
food[1]=runtime.randint(0,pic.get_height()-1)
is_fit=false
for it iterate snake_body
if(it[0]==food[0]it[1]==food[1])
is_fit=true
end
end
end
end

function start()
snake_head={init_long,to_integer(0.5*pic.get_height())}
for i=0 to init_long-2
snake_body.push_back({snake_head[0]-i,snake_head[1]})
end
gen_food()
var frame=0
var pause=false
loop
if(darwin.is_kb_hit())
switch darwin.get_kb_hit()
case "p"
pic.save_to_file("./screen_shot.cdpf")
end
case "w"
if(!pause(god_mode||heading!=4))
heading=3
end
end
case "s"
if(!pause(god_mode||heading!=3))
heading=4
end
end
case "a"
if(!pause(god_mode||heading!=2))
heading=1
end
end
case "d"
if(!pause(god_mode||heading!=1))
heading=2
end
end
case " "
if(pause)
pause=false
else
pause=true
end
end
end
end
if(!pauseframe==hard)
switch heading
case 1
--snake_head[0]
end
case 2
++snake_head[0]
end
case 3
--snake_head[1]
end
case 4
++snake_head[1]
end
end
if(cross_wall)
if(snake_head[0]&<0) snake_head[0]=snake_head[0]+pic.get_width() end if(snake_head[0]&>pic.get_width()-1)
snake_head[0]=snake_head[0]-pic.get_width()
end
if(snake_head[1]&<0) snake_head[1]=snake_head[1]+pic.get_height() end if(snake_head[1]&>pic.get_height()-1)
snake_head[1]=snake_head[1]-pic.get_height()
end
else
if(snake_head[0]&<0||snake_head[0]&>pic.get_width()-1||snake_head[1]&<0||snake_head[1]&>pic.get_height()-1)
die()
return 0
end
end
if(!god_mode)
for it iterate snake_body
if(it[0]==snake_head[0]it[1]==snake_head[1])
die()
return 0
end
end
end
snake_body.push_front(snake_head)
if(snake_head[0]==food[0]snake_head[1]==food[1])
gen_food()
score=score+to_integer(10*(1.0/hard))
else
snake_body.pop_back()
end
frame=0
end
pic.clear()
pic.draw_string(0,0,"Score:"+to_string(score),darwin.pixel(" ",darwin.black,darwin.white))
if(cross_wall)
pic.draw_string(0,1,"Cross Wall",darwin.pixel(" ",darwin.white,darwin.blue))
end
if(god_mode)
pic.draw_string(0,2,"God Mode",darwin.pixel(" ",darwin.white,darwin.red))
end
if(pause)
pic.draw_string(0,3,"Pause",darwin.pixel(" ",darwin.white,darwin.yellow))
end
for it iterate snake_body
pic.draw_pixel(it[0],it[1],body_pix)
end
pic.draw_pixel(snake_head[0],snake_head[1],head_pix)
pic.draw_pixel(food[0],food[1],food_pix)
darwin.update_drawable()
if(!pause)
++frame
end
end
end

for i=1 to system.args.size()-1
switch system.args.at(i)
case "--god-mode"
god_mode=true
end
case "--cross-wall"
cross_wall=true
end
default
throw runtime.exception("Unknown arguments")
end
end
end
darwin.ui.message_box("Greedy Snake","Press any key to start","OK")
darwin.fit_drawable()
loop
snake_body.clear()
heading=2
start()
end


這兩天寫了一個貪吃蛇 用的是 pygame

純原創 暑假自學了python 有些演算法可能有不太合適的地方 大神請無視

放在了Github上

qizhenkang/Snaker_AI

如有不懂需要解釋的地方可在評論區回復~


pygame的貪吃蛇,一次投遞多個食物,默認畫布帶下15*15,一次投遞20個食物,食物之間、食物與蛇之間不會重疊。當方塊總數 - 蛇身長度 - 食物個數 &< 20時,判斷玩家勝利。有生之年終於可以看到貪吃蛇的結局了!

稍作修改也可以成為命令行版本的貪吃蛇

# -*- coding: utf-8 -*-
"""
Created on Tue May 16 07:24:28 2017

@author: zbg
"""
import pygame
from pygame.locals import *

from random import randint, choice, shuffle

class Map(dict):
def __init__(self, w, h):
dict.__init__(self)
self.w = w
self.h = h
self.clear()

def __str__(self):
s = ""
for j in range(self.h):
for i in range(self.w):
s += self[(i, j)]
s += "
"
return s

def clear(self):
for i in range(self.w):
for j in range(self.h):
self[(i, j)] ="."

class Food(object):
def __init__(self, world, n = 1):
self.n = n #一次產生n個食物
self.m = world.m
self.world = world
self.w = self.m.w
self.h = self.m.h
self.locations = {}#用字典是為了吃食物時方便刪除

def generate(self):#由外部world調用,維持n個食物
space = []#除開蛇以外的地方的坐標
for i in range(self.w):
for j in range(self.h):
if (i, j) not in self.world.snake.body:
space.append((i, j))
shuffle(space)
while len(self.locations) &< self.n: self.locations[space[-1]] = 1 #後面的值1並沒有意義。 del space[-1] def draw(self): for l in self.locations: self.m[l] = "o" class Snake(object): """ 蛇做一些簡單的移動、計算和繪製 改變移動方向交給外部的World來處理 """ def __init__(self, world): self.world = world self.m = world.m self.h = self.m.h self.w = self.m.w self.direction = "left" # self.state = "alive" # "alive" or "dead" cw, ch = self.w / 2, self.h / 2 self.body = [(cw, ch), (cw + 1, ch), (cw + 2, ch)] def draw(self): for b in self.body: self.m[b] = "x" def newhead(self): headw, headh = self.body[0] newheadw, newheadh = headw, headh if self.direction == "left": newheadw = headw - 1 elif self.direction == "right": newheadw = headw + 1 elif self.direction == "up": newheadh = headh - 1 elif self.direction == "down": newheadh = headh + 1 return newheadw, newheadh def move(self): x, y = self.newhead() if len(self.body) + self.world.food.n + 20 &> self.w * self.h:
print "fine, you win!!"
elif x == -1 or y == -1 or x == self.w or y == self.h:
print "error, dead"
elif (x, y) in self.body:
print "error, dead"
elif (x, y) in self.world.food.locations:
self.body = [self.newhead()] + self.body[:]
del world.food.locations[(x, y)]
else:
self.body = [self.newhead()] + self.body[0: -1]

def changedirection(self, direction):
self.direction = direction

class World(object):
def __init__(self, w, h):
self.m = Map(w, h)
self.snake = Snake(self)
self.food = Food(self, 20)
self.w, self.h = w, h

def run(self):
self.food.generate()
self.m.clear()
self.snake.move()
self.food.draw()
self.snake.draw()

def show(screen, m):
for i in range(m.w):
for j in range(m.h):
if m[(i, j)] == "x":
r = pygame.Rect(i * unit, j * unit, unit, unit)
pygame.draw.rect(screen,(136,0,21),r,0)
elif m[(i, j)] == "o":
r = pygame.Rect(i * unit, j * unit, unit, unit)
pygame.draw.rect(screen,(0,174,21),r,0)

h = 15
w = 15
unit = 30
SCREEN_SIZE = (w * unit, h * unit)
DIRECTION = {pygame.K_UP: "up", pygame.K_DOWN: "down", pygame.K_LEFT: "left", pygame.K_RIGHT:"right"}
world = World(15,15)
clock = pygame.time.Clock()

pygame.init()
screen = pygame.display.set_mode(SCREEN_SIZE, 0, 32)

while True:
for event in pygame.event.get():
if event.type == QUIT:
exit(0)
if event.type == pygame.KEYDOWN:
if event.key in DIRECTION:
direction = DIRECTION[event.key]
if direction in ["up", "down"] and world.snake.direction in ["up", "down"]:
pass
elif direction in ["left", "right"] and world.snake.direction in ["left", "right"]:
pass
else:
world.snake.changedirection(direction)

screen.fill((255,255,255))
world.run()
show(screen, world.m)
pygame.display.update()
print world.m
clock.tick(3)


大概看了下,如果不調用包吧。你至少知道怎麼搞gui。python主要的Gui是pyqt,tkinter,GKT,wxpython。 第一、第五個重點參考吧。你同時再知道一個隨機數的生成方式。

至於調用包寫的話,推薦pygame,random夠了。一百行左右的代碼量吧。


貪吃蛇只需要有如下基本的 IO 功能就可以寫了:

  1. 在指定坐標寫/畫一個塊
  2. 不阻塞不回顯地讀鍵盤

Console 下面能寫,GUI 也可以。甚至 Console 需要的功能還少些。

所以最簡單就是用標準庫 curses 寫個 Console 的貪吃蛇。curses 入門可以看官方的 How to:

Curses Programming with Python

如果用 Windows,可能需要下載安裝非官方的 curses 包:

http://www.lfd.uci.edu/~gohlke/pythonlibs/#curses

而如果用 GUI,效果會好些,概念也要多些。我想 pygame 是很應景的東西,用起來比較方便,網站上有教程。

注意 IO 是操作系統提供的功能,由庫包裝一下系統功能來提供上面兩個 IO 操作就已經算是從零開始了。如果你覺得用 curses 還不夠「從零開始」,那麼你就得針對不同操作系統來寫了。例如對於 Windows,就是調用諸如 SetConsoleCursorPosition、WriteConsole 等 API 完成基本的輸出,調用 SetConsoleMode、ReadConsole 之類函數處理輸入。用 C 寫貪吃蛇倒常有人這麼干,Python 沒見過這樣的。


用print寫的貪吃蛇,pygame只用監視鍵盤,其他都是標準庫

import pygame
from time import time
from random import choice
from collections import deque

def getdrt():
pygame.event.pump()
keys = pygame.key.get_pressed()
if keys[pygame.K_UP] and olddrt[1] != 1:
return (0,-1)
elif keys[pygame.K_DOWN] and olddrt[1] != -1:
return (0,1)
elif keys[pygame.K_LEFT] and olddrt[0] != 1:
return (-1,0)
elif keys[pygame.K_RIGHT] and olddrt[0] != -1:
return (1,0)
else:
return drt

def show():
global score
show_out = ""
for row in layout:
for i in row:
show_out += shape[i]
show_out += "
"
show_out += " Score: " + str(score)
print("
"*50) #more beautiful
print(show_out)

def move(drt):
global snake_x,snake_y
snake_x += drt[0]
snake_y += drt[1]
thing = layout[snake_y][snake_x]
layout[snake_y][snake_x] = 2
snake.append((snake_x,snake_y))
if thing == 0:
go()
elif thing == 1 or thing == 2:
die(thing)
elif thing == 3:
eat()

def die(thing):
if thing == 1:
print("You moved into the wall!")
elif thing == 2:
print("You ate yourself!")
quit()

def eat():
global score,move_speed,food
score += 1
move_speed *= 0.94
i = j = 0 #food
while layout[j][i]:
i = choice(range(1,width-1))
j = choice(range(1,height-1))
layout[j][i] = 3 #food

def go():
i = snake.popleft()
layout[i[1]][i[0]] = 0

#settings and initializations
width = 18
height = 20
shape = [" "," X "," * "," $ "] #0=nothing 1=wall 2=snake 3=food
layout = [[0 for i in range(width)] for i in range(height)] #wall
for i in [0,width-1]:
for j in range(0,height):
layout[j][i] = 1
for i in [0,height-1]:
for j in range(0,width):
layout[i][j] = 1
snake_x = snake_y = 10
olddrt = drt = (1,0) #initial moving direction
snake = deque([(snake_x,snake_y)])
layout[snake_y][snake_x] = 2 #snake
layout[choice(range(1,height-1))][choice(range(1,width-1))] = 3 #food
move_speed = 0.7 #snake moves * time per second
score = 0

pygame.init()
loop = True
move_time = show_time = time()
while loop:
drt = getdrt()
if time() - move_time &> move_speed:
move(drt)
show()
olddrt = drt
move_time = time()


天辣嚕 。我要好好學習一下python 了

感覺很不錯啊。


不懂python,水一下,做遊戲界面為什麼用python


推薦閱讀:

python3.5 pip安裝庫,無法找到vcvarsall.bat錯誤?裝VS、改源碼無效
用python寫程序時,怎麼知道我想實現的功能有沒有現成的函數?
python爬蟲如何深入學習?

TAG:Python | 編程 | Python框架 | Python庫 | Python開發 |