这段时光个人几篇文章介绍了改路径教程的文章. 关联文章的地址
之前看了一副大涨势姿的贪吃蛇的图,甚为震精,可以再欣赏一下:
既然talk is cheap,show me the code ,我就按照http://hawstein.com/posts/snake-ai.html的教程写了一个,当然并没有能像上图那么人令涨势姿,但是让贪吃蛇主动跑很长时光还是做到了的
首先是照教程所说,网上下了一个可以根据方向键来控制贪吃蛇的一个码代版本,直接在下面行进造改,所以面下的码代有些地方可能有点无厘头=,=
第一步,当然是让贪吃蛇自己跑起来,这个很简单,但由于事先没仔细看教程,想想又要保存蛇和,什物之间的路径,就直接试了试dfs,码代很简单,码代很简单,但是会写码代的人就道知这不是最短路径啊!!!每次都要绕好长一圈才能到食品,这有什么意思?然后就思考了下bfs(),bfs()实确该应是最短路径了,但是用bfs怎么示表路径了,想了一会想到可以建个组数来示表点的父节点,于是bfs版本又写好了=,=能跑一段时光了,到后来才现发教程里就直接写着bfs路径的处理方法!!惋惜事先没看到,自己想一遍懂得也刻深点吧。。。。。。。
到前目的止,蛇能自己运行一段时光,但是万一蛇身的长度超越x轴或者y轴,蛇的智商就比拟捉急了,这时候由于找不到路径蛇就会直一停留在原地。
按照教程所说的,该应义定一个安全模式:在吃掉食品后,蛇头到蛇尾之间还有路径(就算蛇头到食品之间没有路径,舌头可以着跟蛇尾跑,跑动过程当中可能涌现到食品的路径)因为挪动过程当中蛇尾会直一释放出新的空间,所以每次找到到食品的路径后,该应派出一条虚拟蛇去吃食品,吃完后该应判断是否是安全,安全了派真蛇吃,不安全就着跟蛇尾跑(这里教程说跟蛇尾跑要用最长路径,本人比拟知无,用了dfs来替换),但其实在试验过程当中,种这思绪也会有bug(在现还没处理= =):就是虽然这一步你判断为安全,你朝食品进了一步,单手一步以后你现发安全了,只能着跟蛇尾跑,这样会涌现蛇直一在一个环循里跑的象现。。。。。。
实现了下面的思绪,面下是我自己的贪吃蛇的截图:
@代表蛇头,#代表蛇身,-代表蛇尾,+代表食品
talk is cheap,show me the code:
#!/usr/bin/python # -*- coding: utf8 -*- import curses, sys, random from time import sleep # init ------------------------------------------------------------------------- DIR_UP = 0 DIR_RIGHT = 1 DIR_DOWN = 2 DIR_LEFT = 3 directions = [[1,0],[-1,0],[0,1],[0,-1]] field = [] snake = [[10,5], [9,5], [8,5], [7,5]] dir = DIR_RIGHT; food = [] grow_snake = False is_game_over = False paths = [] # init curses library win = curses.initscr(); # enable arrow keys win.keypad(1) # do not wait for keypress win.nodelay(1) # hide cursor curses.curs_set(0) # read keys instantaneously curses.cbreak() # do not print stuff when key is presses curses.noecho() # get terminal size rows, cols = win.getmaxyx() rows -= 1 map = [] headX = 0 headY = 0 foodX = 0 foodY = 0 def initMap(snake1,targetX,targetY): global map,headX,headY,foodX,foodY map = [] for x in range(cols): line = [] for y in range(rows): line.append(False) map.append(line) for pos in snake1: x = pos[0] y = pos[1] map[x][y] = True map[targetX][targetY]=False headX = snake1[0][0] headY = snake1[0][1] foodX = targetX foodY = targetY def bfs(targetX,targetY,snake1,trueSnake): global map initMap(snake1,targetX,targetY) l = [] father = [0 for x in range(100000)] l.append([headX,headY]) father[0] = 0 index = 0 while len(l)>index: cur = l[index] curX = cur[0] curY = cur[1] if curX == foodX and curY == foodY: if trueSnake == True: endPoint = index temp = [] while endPoint != father[endPoint]: temp.insert(0,l[endPoint]) endPoint = father[endPoint] temp.insert(0,l[0]) return temp break else: return True for direction in directions: nextX = curX + direction[0] nextY = curY + direction[1] if nextX>=0 and nextX<cols and nextY >0 and nextY<rows and map[nextX][nextY]==False: l.append([nextX,nextY]) father[len(l)-1] = index map[nextX][nextY]=True index += 1 if trueSnake ==True: return [] else: return False def dfsTail(targetX,targetY): global map initMap(snake,targetX,targetY) map[targetX][targetY]=False l = [] l.append([headX,headY]) while len(l)>0: index = 0 cur = l[-1] curX = cur[0] curY = cur[1] if curX == foodX and curY == foodY: return l break for direction in directions: nextX = curX + direction[0] nextY = curY + direction[1] if nextX>=0 and nextX<cols and nextY >0 and nextY<rows and map[nextX][nextY]==False: l.append([nextX,nextY]) map[nextX][nextY]=True break else: index += 1 if index == 4: l.pop() return [] def createHead(head,direction): if direction == DIR_UP: head = [head[0], head[1]-1] elif direction == DIR_RIGHT: head = [head[0]+1, head[1]] elif direction == DIR_DOWN: head = [head[0], head[1]+1] elif direction == DIR_LEFT: head = [head[0]-1, head[1]] return head def createDirection(diffX,diffY): direction = 0 if diffX == 0 and diffY == -1: direction = 0 elif diffX == 0 and diffY == 1: direction = 2 elif diffX == 1 and diffY == 0: direction = 1 else: direction = 3 return direction def isSafe(paths): global map count = 0 fakeSnake = snake[:] for direction in paths: dir = direction head = fakeSnake[0] count += 1 # remove tail if count != len(paths): fakeSnake.pop() # calculate where head will be head = createHead(head,dir) fakeSnake.insert(0, head) snakeTail = fakeSnake[-1] initMap(fakeSnake,snakeTail[0],snakeTail[1]) return bfs(snakeTail[0],snakeTail[1],fakeSnake,False) def nextPaths(): global paths,snake path = bfs(food[0][0],food[0][1],snake,True) paths = [] for x in range(1,len(path)): diffX = path[x][0]-path[x-1][0] diffY = path[x][1]-path[x-1][1] direction = createDirection(diffX,diffY) paths.append(direction) if not isSafe(paths) or len(paths)==0: snakeTail = snake[-1] path = dfsTail(snakeTail[0],snakeTail[1]) paths = [] for x in range(1,len(path)): diffX = path[x][0]-path[x-1][0] diffY = path[x][1]-path[x-1][1] direction = createDirection(diffX,diffY) paths.append(direction) # redraw and refresh entire screen def redraw(): win.erase() drawCaption(" snake "+str(len(snake))+" ") drawFood() drawSnake() win.refresh() # draw top border with specified text def drawCaption(text): global cols win.addstr(0, 0, "." * cols) win.addstr(0, (cols - len(text)) / 2, text) # draw snake def drawSnake(): try: n = 0 for pos in snake: if n == 0: win.addstr(pos[1], pos[0], "@") elif n == len(snake)-1: win.addstr(pos[1], pos[0], "-") else: win.addstr(pos[1], pos[0], "#") n += 1 except: pass # draw all the food def drawFood(): try: for pos in food: win.addstr(pos[1], pos[0], "+") except: pass # check if snake has just eaten the food def isFoodCollision(): for pos in food: if pos == snake[0]: food.remove(pos) return True return False # check if snake has just commited suicide def isSuicide(): for i in xrange(0, len(snake)): if i > 0 and snake[i] == snake[0]: return True return False # end game gracefully def endGame(): curses.nocbreak(); win.keypad(0); curses.echo() curses.endwin() # move snake one step forward def moveSnake(): global snake global grow_snake global cols, rows # get head head = snake[0] # remove tail if (grow_snake == False): snake.pop() else: grow_snake = False # calculate where head will be head = createHead(head,dir) # insert new head snake.insert(0, head) # drop new food, but not on snake or on another food def dropFood(): x = random.randint(0, cols-1) y = random.randint(1, rows-1) for pos in food: if pos == [x,y]: dropFood() return for pos in snake: if pos == [x,y]: dropFood() return f = open('record.txt','w') f.write('food: '+str(x)+' '+str(y)+'\n') food.append([x,y]) # stop all the action and print the sad news def gameOver(): global is_game_over is_game_over = True drawCaption("game over") # start ------------------------------------------------------------------------- dropFood() redraw() while (True): if is_game_over == False: redraw() key = win.getch() nextPaths() dir = paths[0] if (isSuicide()): gameOver() if (isFoodCollision()): dropFood() grow_snake = True moveSnake() else: break endGame()
意注windows下要装安curse才能运行
文章结束给大家分享下程序员的一些笑话语录: IBM和波音777
波音777是有史以来第一架完全在电脑虚拟现实中设计制造的飞机,所用的设备完全由IBM公司所提供。试飞前,波音公司的总裁非常热情的邀请IBM的技术主管去参加试飞,可那位主管却说道:“啊,非常荣幸,可惜那天是我妻子的生日,So..”..
波音公司的总载一听就生气了:“胆小鬼,我还没告诉你试飞的日期呢!”