收藏 分销(赏)

利用Python如何制作贪吃蛇及AI版贪吃蛇详解.pdf

上传人:鱼** 文档编号:851929 上传时间:2024-03-29 格式:PDF 页数:8 大小:359.16KB
下载 相关 举报
利用Python如何制作贪吃蛇及AI版贪吃蛇详解.pdf_第1页
第1页 / 共8页
利用Python如何制作贪吃蛇及AI版贪吃蛇详解.pdf_第2页
第2页 / 共8页
点击查看更多>>
资源描述
利 PythonPython如何制作贪吃蛇及 AIAI版贪吃蛇详解python制作普通贪吃蛇哈喽,家不知道是上午好还是中午好还是下午好还是晚上好!贪吃蛇,应该是90后时候的记忆(连我这个00后也不例外),今天,我们就python这款编程语来实现贪吃蛇系统:所有都可以需导模块:randompygamepygame.localssys下载以上模块指令:random和sys是Python带的,我们只需要下载pygame即可下载pygame:在开始菜单输“cmd”回车打开,输指令:pip install pygame苹果电脑需要改成:pip3 install pygame下载好后,打开python的shell界,输import pygame,回车,如果没报错,及代表安装完成。接下来什么都不说,直接奉上代码(恕我没写注释):import randomimport pygameimport sysfrom pygame.locals import*Snakespeed=17Window_Width=800Window_Height=500Cell_Size=20#Width and height of the cells#Ensuring that the cells fit perfectly in the window.eg if cell size was#10 and window width or windowheight were 15 only 1.5 cells would#fit.assert Window_Width%Cell_Size=0,Window width must be a multiple of cell size.#Ensuring that only whole integer number of cells fit perfectly in the window.assert Window_Height%Cell_Size=0,Window height must be a multiple of cell size.Cell_W=int(Window_Width/Cell_Size)#Cell WidthCell_H=int(Window_Height/Cell_Size)#Cellc HeightWhite=(255,255,255)Black=(0,0,0)Red=(255,0,0)#Defining element colors for the program.Green=(0,255,0)DARKGreen=(0,155,0)DARKGRAY=(40,40,40)YELLOW=(255,255,0)Red_DARK=(150,0,0)BLUE=(0,0,255)BLUE_DARK=(0,0,150)BGCOLOR=Black#Background colorUP=upDOWN=down#Defining keyboard keys.LEFT=leftRIGHT=rightHEAD=0#Syntactic sugar:index of the snakes headdef main():global SnakespeedCLOCK,DISPLAYSURF,BASICFONT pygame.init()SnakespeedCLOCK=pygame.time.Clock()DISPLAYSURF=pygame.display.set_mode(Window_Width,Window_Height)BASICFONT=pygame.font.Font(freesansbold.ttf,18)pygame.display.set_caption(Snake)showStartScreen()while True:runGame()showGameOverScreen()def runGame():#Set a random start point.startx=random.randint(5,Cell_W-6)starty=random.randint(5,Cell_H-6)wormCoords=x:startx,y:starty,x:startx-1,y:starty,x:startx-2,y:starty direction=RIGHT#Start the apple in a random place.apple=getRandomLocation()while True:#main game loop for event in pygame.event.get():#event handling loop if event.type=QUIT:terminate()elif event.type=KEYDOWN:if(event.key=K_LEFT)and direction!=RIGHT:direction=LEFT elif(event.key=K_RIGHT)and direction!=LEFT:direction=RIGHT elif(event.key=K_UP)and direction!=DOWN:direction=UP elif(event.key=K_DOWN)and direction!=UP:direction=DOWN elif event.key=K_ESCAPE:terminate()#check if the Snake has hit itself or the edge if wormCoordsHEADx=-1 or wormCoordsHEADx=Cell_W or wormCoordsHEADy=-1 or wormCoordsHEADy=Cell_H:return#game over for wormBody in wormCoords1:if wormBodyx=wormCoordsHEADx and wormBodyy=wormCoordsHEADy:return#game over#check if Snake has eaten an apply if wormCoordsHEADx=applex and wormCoordsHEADy=appley:#dont remove worms tail segment apple=getRandomLocation()#set a new apple somewhere else:del wormCoords-1#remove worms tail segment#move the worm by adding a segment in the direction it is moving if direction=UP:newHead=x:wormCoordsHEADx,y:wormCoordsHEADy-1 elif direction=DOWN:newHead=x:wormCoordsHEADx,y:wormCoordsHEADy+1 elif direction=LEFT:newHead=x:wormCoordsHEAD x-1,y:wormCoordsHEADy elif direction=RIGHT:newHead=x:wormCoordsHEAD x+1,y:wormCoordsHEADy wormCoords.insert(0,newHead)DISPLAYSURF.fill(BGCOLOR)drawGrid()drawWorm(wormCoords)drawApple(apple)drawScore(len(wormCoords)-3)pygame.display.update()SnakespeedCLOCK.tick(Snakespeed)def drawPressKeyMsg():pressKeySurf=BASICFONT.render(Press a key to play.,True,White)pressKeyRect=pressKeySurf.get_rect()pressKeyRect.topleft=(Window_Width-200,Window_Height-30)DISPLAYSURF.blit(pressKeySurf,pressKeyRect)def checkForKeyPress():if len(pygame.event.get(QUIT)0:terminate()keyUpEvents=pygame.event.get(KEYUP)if len(keyUpEvents)=0:return None if keyUpEvents0.key=K_ESCAPE:terminate()return keyUpEvents0.keydef showStartScreen():titleFont=pygame.font.Font(freesansbold.ttf,100)titleSurf1=titleFont.render(Snake!,True,White,DARKGreen)degrees1=0 degrees2=0 while True:DISPLAYSURF.fill(BGCOLOR)rotatedSurf1=pygame.transform.rotate(titleSurf1,degrees1)rotatedRect1=rotatedSurf1.get_rect()rotatedRect1.center=(Window_Width/2,Window_Height/2)DISPLAYSURF.blit(rotatedSurf1,rotatedRect1)drawPressKeyMsg()if checkForKeyPress():pygame.event.get()#clear event queue return pygame.display.update()SnakespeedCLOCK.tick(Snakespeed)degrees1+=3#rotate by 3 degrees each frame degrees2+=7#rotate by 7 degrees each framedef terminate():pygame.quit()sys.exit()def getRandomLocation():return x:random.randint(0,Cell_W-1),y:random.randint(0,Cell_H-1)def showGameOverScreen():gameOverFont=pygame.font.Font(freesansbold.ttf,100)gameSurf=gameOverFont.render(Game,True,White)overSurf=gameOverFont.render(Over,True,White)gameRect=gameSurf.get_rect()overRect=overSurf.get_rect()gameRect.midtop=(Window_Width/2,10)overRect.midtop=(Window_Width/2,gameRect.height+10+25)DISPLAYSURF.blit(gameSurf,gameRect)DISPLAYSURF.blit(overSurf,overRect)drawPressKeyMsg()pygame.display.update()pygame.time.wait(500)checkForKeyPress()#clear out any key presses in the event queue while True:if checkForKeyPress():pygame.event.get()#clear event queue returndef drawScore(score):scoreSurf=BASICFONT.render(Score:%s%(score),True,White)scoreRect=scoreSurf.get_rect()scoreRect.topleft=(Window_Width-120,10)DISPLAYSURF.blit(scoreSurf,scoreRect)def drawWorm(wormCoords):for coord in wormCoords:x=coordx*Cell_Size y=coordy*Cell_Size wormSegmentRect=pygame.Rect(x,y,Cell_Size,Cell_Size)pygame.draw.rect(DISPLAYSURF,DARKGreen,wormSegmentRect)wormInnerSegmentRect=pygame.Rect(x+4,y+4,Cell_Size-8,Cell_Size-8)pygame.draw.rect(DISPLAYSURF,Green,wormInnerSegmentRect)def drawApple(coord):x=coordx*Cell_Size y=coordy*Cell_Size appleRect=pygame.Rect(x,y,Cell_Size,Cell_Size)pygame.draw.rect(DISPLAYSURF,Red,appleRect)def drawGrid():for x in range(0,Window_Width,Cell_Size):#draw vertical lines pygame.draw.line(DISPLAYSURF,DARKGRAY,(x,0),(x,Window_Height)for y in range(0,Window_Height,Cell_Size):#draw horizontal lines pygame.draw.line(DISPLAYSURF,DARKGRAY,(0,y),(Window_Width,y)if _name_=_main_:try:main()except SystemExit:pass以上是贪吃蛇的全部代码,接下来,我们来制作AI版贪吃蛇。python制作AI版贪吃蛇AI版贪吃蛇,即让系统玩贪吃蛇,句话:玩。下开始:系统:什么都可以需导的模块:pygamesystimerandom如果你已经下载好了pygame,即可直接开始。还是什么都不说,直接奉上代码(这次有注释)#coding:utf-8import pygame,sys,time,randomfrom pygame.locals import*#定义颜变量redColour=pygame.Color(255,0,0)blackColour=pygame.Color(0,0,0)whiteColour=pygame.Color(255,255,255)greenColour=pygame.Color(0,255,0)headColour=pygame.Color(0,119,255)#注意:在下所有的除法中,为了防pygame输出偏差,必须取除数(/)不是单纯除法(/)#蛇运动的场地长宽,因为第0,HEIGHT,第0列,WIDTH列为围墙,所以实际是13*13HEIGHT=15WIDTH=15FIELD_SIZE=HEIGHT*WIDTH#蛇头位于snake数组的第个元素HEAD=0#数字代表不同的对象,由于运动时矩阵上每个格会处理成到达物的路径长度,#因此这三个变量间需要有够的间隔(HEIGHT*WIDTH)来互相区分#写般是坐标,写代表常量FOOD=0UNDEFINED=(HEIGHT+1)*(WIDTH+1)SNAKE=2*UNDEFINED#由于snake是维数组,所以对应元素直接加上以下值就表向四个向移动LEFT=-1RIGHT=1UP=-WIDTH#维数组,所以需要整个宽度都加上才能表上下移动DOWN=WIDTH#错误码ERR=-2333#维数组来表维的东西#board表蛇运动的矩形场地#初始化蛇头在(1,1)的地#初始蛇长度为1board=0*FIELD_SIZE#0,0,0,snake=0*(FIELD_SIZE+1)snakeHEAD=1*WIDTH+1snake_size=1#与上变量对应的临时变量,蛇试探性地移动时使tmpboard=0*FIELD_SIZEtmpsnake=0*(FIELD_SIZE+1)tmpsnakeHEAD=1*WIDTH+1tmpsnake_size=1#food:物位置初始在(4,7)#best_move:运动向food=4*WIDTH+7best_move=ERR#运动向数组,游戏分数(蛇长)mov=LEFT,RIGHT,UP,DOWNscore=1#检查个cell有没有被蛇覆盖,没有覆盖则为free,返回truedef is_cell_free(idx,psize,psnake):return not(idx in psnake:psize)#检查某个位置idx是否可向move向运动def is_move_possible(idx,move):flag=False if move=LEFT:#因为实际范围是13*13,1,13*1,13,所以idx为1时不能往左跑,此时取余为1所以1 flag=True if idx%WIDTH 1 else False elif move=RIGHT:#这的WIDTH-2跟上是样的道理 flag=True if idx%WIDTH (2*WIDTH-1)else False elif move=DOWN:flag=True if idx (FIELD_SIZE-2*WIDTH)else False return flag#重置board#board_BFS后,UNDEFINED值都变为了到达物的路径长度#如需要还原,则要重置它def board_reset(psnake,psize,pboard):for i in range(FIELD_SIZE):if i=food:pboardi=FOOD elif is_cell_free(i,psize,psnake):#该位置为空 pboardi=UNDEFINED else:#该位置为蛇 pboardi=SNAKE#度优先搜索遍历整个board,#计算出board中每个SNAKE元素到达物的路径长度def board_BFS(pfood,psnake,pboard):queue=queue.append(pfood)inqueue=0*FIELD_SIZE found=False#while循环结束后,除了蛇的体,#其它每个格中的数字为从它到物的曼哈顿间距 while len(queue)!=0:idx=queue.pop(0)#初始时idx是物的坐标 if inqueueidx=1:continue inqueueidx=1 for i in range(4):#左右上下 if is_move_possible(idx,movi):if idx+movi=psnakeHEAD:found=True if pboardidx+movi pboardidx+1:#于的时候不管,不然会覆盖已有的路径数据 pboardidx+movi=pboardidx+1 if inqueueidx+movi=0:queue.append(idx+movi)return found#从蛇头开始,根据board中元素值,#从蛇头周围4个领域点中选择最短路径def choose_shortest_safe_move(psnake,pboard):best_move=ERR min=SNAKE for i in range(4):if is_move_possible(psnakeHEAD,movi)and pboardpsnakeHEAD+movimin:#这判断最和下的函数判断最,都是先赋值,再循环互相较 min=pboardpsnakeHEAD+movi best_move=movi return best_move#从蛇头开始,根据board中元素值,#从蛇头周围4个领域点中选择最远路径def choose_longest_safe_move(psnake,pboard):best_move=ERR max=-1 for i in range(4):if is_move_possible(psnakeHEAD,movi)and pboardpsnakeHEAD+movimax:max=pboardpsnakeHEAD+movi best_move=movi return best_move#检查是否可以追着蛇尾运动,即蛇头和蛇尾间是有路径的#为的是避免蛇头陷死路#虚拟操作,在tmpboard,tmpsnake中进def is_tail_inside():global tmpboard,tmpsnake,food,tmpsnake_size tmpboardtmpsnaketmpsnake_size-1=0#虚拟地将蛇尾变为物(因为是虚拟的,所以在tmpsnake,tmpboard中进)tmpboardfood=SNAKE#放置物的地,看成蛇 result=board_BFS(tmpsnaketmpsnake_size-1,tmpsnake,tmpboard)#求得每个位置到蛇尾的路径长度 for i in range(4):#如果蛇头和蛇尾紧挨着,则返回False。即不能follow_tail,追着蛇尾运动了 if is_move_possible(tmpsnakeHEAD,movi)and tmpsnakeHEAD+movi=tmpsnaketmpsnake_size-1 and tmpsnake_size3:result=False return result#让蛇头朝着蛇尾运步#不管蛇阻挡,朝蛇尾向运def follow_tail():global tmpboard,tmpsnake,food,tmpsnake_size tmpsnake_size=snake_size tmpsnake=snake:board_reset(tmpsnake,tmpsnake_size,tmpboard)#重置虚拟board tmpboardtmpsnaketmpsnake_size-1=FOOD#让蛇尾成为物 tmpboardfood=SNAKE#让物的地变成蛇 board_BFS(tmpsnaketmpsnake_size-1,tmpsnake,tmpboard)#求得各个位置到达蛇尾的路径长度 tmpboardtmpsnaketmpsnake_size-1=SNAKE#还原蛇尾 return choose_longest_safe_move(tmpsnake,tmpboard)#返回运向(让蛇头运动1步)#在各种案都不时,随便找个可的向来(1步),def any_possible_move():global food,snake,snake_size,board best_move=ERR board_reset(snake,snake_size,board)board_BFS(food,snake,board)min=SNAKE for i in range(4):if is_move_possible(snakeHEAD,movi)and boardsnakeHEAD+movimin:min=boardsnakeHEAD+movi best_move=movi return best_move#转换数组函数def shift_array(arr,size):for i in range(size,0,-1):arri=arri-1def new_food():#随机函数成新的物 global food,snake_size cell_free=False while not cell_free:w=random.randint(1,WIDTH-2)h=random.randint(1,HEIGHT-2)food=WIDTH*h+w cell_free=is_cell_free(food,snake_size,snake)pygame.draw.rect(playSurface,redColour,Rect(18*(food/WIDTH),18*(food%WIDTH),18,18)#真正的蛇在这个函数中,朝pbest_move1步def make_move(pbest_move):global snake,board,snake_size,score shift_array(snake,snake_size)snakeHEAD+=pbest_move p=snakeHEAD for body in snake:#画蛇,体,头,尾 pygame.draw.rect(playSurface,whiteColour,Rect(18*(body/WIDTH),18*(body%WIDTH),18,18)pygame.draw.rect(playSurface,greenColour,Rect(18*(snakesnake_size-1/WIDTH),18*(snakesnake_size-1%WIDTH),18,18)pygame.draw.rect(playSurface,headColour,Rect(18*(p/WIDTH),18*(p%WIDTH),18,18)#下是把初始情况会出现的第个块bug填掉 pygame.draw.rect(playSurface,(255,255,0),Rect(0,0,18,18)#刷新pygame显层 pygame.display.flip()#如果新加的蛇头就是物的位置#蛇长加1,产新的物,重置board(因为原来那些路径长度已经不上了)if snakeHEAD=food:boardsnakeHEAD=SNAKE#新的蛇头 snake_size+=1 score+=1 if snake_size FIELD_SIZE:new_food()else:#如果新加的蛇头不是物的位置 boardsnakeHEAD=SNAKE#新的蛇头 boardsnakesnake_size=UNDEFINED#蛇尾变为UNDEFINED,pygame.draw.rect(playSurface,blackColour,Rect(18*(snakesnake_size/WIDTH),18*(snakesnake_size%WIDTH),18,18)#刷新pygame显层 pygame.display.flip()#虚拟地运次,然后在调处检查这次运可否可#可才真实运。#虚拟运吃到物后,得到虚拟下蛇在board的位置def virtual_shortest_move():global snake,board,snake_size,tmpsnake,tmpboard,tmpsnake_size,food tmpsnake_size=snake_size tmpsnake=snake:#如果直接tmpsnake=snake,则两者指向同处内存 tmpboard=board:#board中已经是各位置到达物的路径长度了,不再计算 board_reset(tmpsnake,tmpsnake_size,tmpboard)food_eated=False while not food_eated:board_BFS(food,tmpsnake,tmpboard)move=choose_shortest_safe_move(tmpsnake,tmpboard)shift_array(tmpsnake,tmpsnake_size)tmpsnakeHEAD+=move#在蛇头前加个新的位置#如果新加的蛇头的位置正好是物的位置#则长度加1,重置board,物那个位置变为蛇的部分(SNAKE)if tmpsnakeHEAD=food:tmpsnake_size+=1 board_reset(tmpsnake,tmpsnake_size,tmpboard)#虚拟运后,蛇在board的位置 tmpboardfood=SNAKE food_eated=True else:#如果蛇头不是物的位置,则新加的位置为蛇头,最后个变为空格 tmpboardtmpsnakeHEAD=SNAKE tmpboardtmpsnaketmpsnake_size=UNDEFINED#如果蛇与物间有路径,则调本函数def find_safe_way():global snake,board safe_move=ERR#虚拟地运次,因为已经确保蛇与物间有路径,所以执有效#运后得到虚拟下蛇在board中的位置,即tmpboard virtual_shortest_move()#该函数唯调处 if is_tail_inside():#如果虚拟运后,蛇头蛇尾间有通路,则选最短路运(1步)return choose_shortest_safe_move(snake,board)safe_move=follow_tail()#否则虚拟地follow_tail 1步,如果可以做到,返回true return safe_move#初始化pygamepygame.init()#定义个变量来控制游戏速度fpsClock=pygame.time.Clock()#创建pygame显层playSurface=pygame.display.set_mode(270,270)pygame.display.set_caption(贪吃蛇)#绘制pygame显层playSurface.fill(blackColour)#初始化物pygame.draw.rect(playSurface,redColour,Rect(18*(food/WIDTH),18*(food%WIDTH),18,18)while True:for event in pygame.event.get():#循环监听键盘和退出事件 if event.type=QUIT:#如果点了关闭 print(score)#游戏结束后打印分数 pygame.quit()sys.exit()elif event.type=KEYDOWN:#如果esc键被按下 if event.key=K_ESCAPE:print(score)#游戏结束后打印分数 pygame.quit()sys.exit()#刷新pygame显层 pygame.display.flip()#画围墙,255,255,0是黄,边框是36是因为,pygame矩形是以边为初始,向四周填充边框 pygame.draw.rect(playSurface,(255,255,0),Rect(0,0,270,270),36)#重置距离 board_reset(snake,snake_size,board)#如果蛇可以吃到物,board_BFS返回true#并且board中除了蛇(=SNAKE),其它的元素值表从该点运动到物的最短路径长 if board_BFS(food,snake,board):best_move=find_safe_way()#find_safe_way的唯调处 else:best_move=follow_tail()if best_move=ERR:best_move=any_possible_move()#上次思考,只得出个向,运步 if best_move!=ERR:make_move(best_move)else:print(score)#游戏结束后打印分数 break#控制游戏速度 fpsClock.tick(20)#20看上去速度正好ok,这就是今天的全部内容866!到此这篇关于利Python如何制作贪吃蛇及AI版贪吃蛇的章就介绍到这了,更多相关Python制作贪吃蛇及AI版贪吃蛇内容请搜索以前的章或继续浏览下的相关章希望家以后多多持!
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传
相似文档                                   自信AI助手自信AI助手

当前位置:首页 > 通信科技 > 其他

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2025 宁波自信网络信息技术有限公司  版权所有

客服电话:4009-655-100  投诉/维权电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服