如何用Python写一个贪吃蛇AI

http://www.hawstein.com/posts/snake-ai.html


import curses,time,copy
from random import randint

border_size = (22,22)

class Snake(object):
	global ms
	global border_size
	def __init__(self,arg):
		if arg==None:
			self.border = [[0 for i in range(border_size[0])] for j in range(border_size[1])]
		else:
			self.border = copy.deepcopy(arg)
		border_width = border_size[0]
		border_height = border_size[1]
		self.is_add_score = 1
		self.body = []
		self.x = randint(0,border_height-1)
		self.y = randint(0,border_width-1)
		self.body.append([self.x,self.y])
		self.border[self.x][self.y] = 3
	def map_border(self,input_num):
		if input_num == 0:
			return "  "
		elif input_num == 1:
			return "o "
		elif input_num == 2:
			return "@ "
		else:
			return "H "

	def show_border(self):
		for i in range(border_size[1]):
			#once I face a question is over the range of the region it can display
			#it make me puzzle and waste a lot of time
			ms.addstr(i+1,1,"".join(map(self.map_border,self.border[i])))
		ms.refresh()


	def rand_egg(self):
		global score
		if self.is_add_score == 1:
			score += 1
		self.egg_x = randint(0,border_size[1]-1)
		self.egg_y = randint(0,border_size[0]-1)
		while self.border[self.egg_x][self.egg_y] != 0:
			self.egg_x = randint(0,border_size[1]-1)
			self.egg_y = randint(0,border_size[0]-1)
		self.border[self.egg_x][self.egg_y] = 2

	def move(self,direction,s=1):
		for i in range(1):
			self.move_o(direction)

	def move_o(self,direction):
		def next_step(x,y,x_i,y_i):
			return [(x+x_i+border_size[1])%border_size[1],(y+y_i+border_size[0])%border_size[0]]
		def go_to_next(x,y,x_i,y_i):
			tmp_next = next_step(x,y,x_i,y_i)
			if self.border[tmp_next[0]][tmp_next[1]] == 0:
				tmp_pop = self.body.pop(len(self.body)-1)
				self.border[tmp_pop[0]][tmp_pop[1]] = 0
				if len(self.body) == 0:
					self.body = [tmp_next,]
				else:
					self.border[self.body[0][0]][self.body[0][1]] = 1
					self.body.insert(0,tmp_next)
				self.border[self.body[0][0]][self.body[0][1]] = 3
			else:
				self.border[self.body[0][0]][self.body[0][1]] = 1
				self.body.insert(0,tmp_next)
				self.border[self.body[0][0]][self.body[0][1]] = 3
				self.rand_egg()
		def can_go(x,y,x_i,y_i):
			if self.border[(x+x_i+border_size[1])%border_size[1]][(y+y_i+border_size[0])%border_size[0]]==0 or self.border[(x+x_i+border_size[1])%border_size[1]][(y+y_i+border_size[0])%border_size[0]]==2:
				ms.addstr(2,border_size[0]*2 + 2,"             ")
				ms.addstr(2,border_size[0]*2 + 2,"avialable")
				return True
			else:	
				ms.addstr(2,border_size[0]*2 + 2,"             ")
				ms.addstr(2,border_size[0]*2 + 2,"unavialable")
				return False
		if direction == 1:
			if can_go(self.body[0][0],self.body[0][1],-1,0):
				go_to_next(self.body[0][0],self.body[0][1],-1,0)
		elif direction == 2:
			if can_go(self.body[0][0],self.body[0][1],1,0):
				go_to_next(self.body[0][0],self.body[0][1],1,0)
		elif direction == 3:
			if can_go(self.body[0][0],self.body[0][1],0,1):
				go_to_next(self.body[0][0],self.body[0][1],0,1)
		elif direction == 4:
			if can_go(self.body[0][0],self.body[0][1],0,-1):
				go_to_next(self.body[0][0],self.body[0][1],0,-1)
	def get_direction(self):
		ch_input = ms.getch()
		if ch_input == 65:
			self.move(1)
			return "up"
		elif ch_input == 66:
			self.move(2)
			return "down"
		elif ch_input == 67:
			self.move(3)
			return "right"
		elif ch_input == 68:
			self.move(4)
			return "left"
		else:	
			self.move(5)
			return "     "

	def get_closest_way(self,des_x,des_y):	
		return self.get_way_BFS(des_x,des_y,1)

	def get_farest_way(self,des_x,des_y):	
		return self.get_way_BFS(des_x,des_y,0)

	def get_way_BFS(self,des_x,des_y,arg):	
		direction = [[-1,0],[1,0],[0,1],[0,-1]]
		visited = []
		BFS_list = []
		x,y = self.body[0]
		BFS_list.append([[x,y],-1,-1])
		visit_tmp = []

		while len(BFS_list)>0:
			tmp = BFS_list.pop(0)
			visited.append(tmp)
			visit_tmp.append(tmp[0])
			for index,item in enumerate(direction):
				next_x = (tmp[0][0]+item[0]+border_size[1])%border_size[1]
				next_y = (tmp[0][1]+item[1]+border_size[0])%border_size[0]
				#sta = border[next_x][next_y]
				data = [[next_x,next_y],index+1,len(visited)-1]
				if arg == 1:
					if next_x == des_x and next_y == des_y:	
						path = str(index + 1)
						if len(visited) == 1:
							return index + 1,path
						back_tmp = visited[-1]
						while self.body[0] != back_tmp[0]:
							back_tmp_t = back_tmp
							path += str(back_tmp[1])
							back_tmp = visited[back_tmp[2]]
						return back_tmp_t[1],path[::-1]
					else:
						if self.border[next_x][next_y]==0:
							if [next_x,next_y] not in visit_tmp:
								BFS_list.append(data)
								visit_tmp.append(data[0])
				else:
					if self.border[next_x][next_y]==0:
							if [next_x,next_y] not in visit_tmp:
								BFS_list.append(data)
								visit_tmp.append(data[0])
		if arg == 1:
			return None,None
		else:
			tmp = visited.pop(-1)
			while not (tmp[0][0] == des_x and tmp[0][1] == des_y) and len(visited)>0:
				tmp = visited.pop(-1)
			if len(visited) == 0:
				return None,None
			path = ""
			while not(body[0][0] == tmp[0][0] and body[0][1] == tmp[0][1]):
				tmp_backup = tmp
				path += str(tmp[1])
				tmp = visited[tmp[2]]
			return tmp_backup[1],path[::-1]
	
		
	def automaticly_move(self):
		des,path = self.get_closest_way(self.egg_x,self.egg_y)
		if des == None:
			des = randint(1,4)
			path = des
		self.move(des)
		return des,path

def map_dire(dire):
	if dire == 1:
		return "up"
	elif dire == 2:
		return "down"
	elif dire == 3:
		return "right"
	elif dire == 4:
		return "left"
	else:
		return "None"

def go_and_predict(snake):
	s_tmp = copy.deepcopy(snake)
	#s_tmp_tmp = copy.deepcopy(snake)
	s_tmp.is_add_score = 0
	egg_x = s_tmp.egg_x
	egg_y = s_tmp.egg_y
	s_tmp_des,s_tmp_path = s_tmp.get_closest_way(egg_x,egg_y)
	s_tmp_des_orig = s_tmp_des
	s_tmp_path_orig = s_tmp_path
	if s_tmp_des != None:
		while not(egg_x == s_tmp.body[0][0] and egg_y == s_tmp.body[0][1]):
			s_tmp.move(s_tmp_des)
			s_tmp_des,s_tmp_path = s_tmp.get_closest_way(egg_x,egg_y)
		s_tmp_des,s_tmp_path = s_tmp.get_closest_way(s_tmp.body[-1][0],s_tmp.body[-1][1])
		if s_tmp_des != None:
			return s_tmp_des_orig,s_tmp_path_orig
		else:
			s_tmp_des,s_tmp_path = snake.get_farest_way(snake.body[-1][0],snake.body[-1][1])
			if s_tmp_des != None:
				return s_tmp_des,s_tmp_path
			else:
				s = randint(1,4)
				tmp_x = randint(1,4)
				return 5,str(s)+str(tmp_x)
	else:
		s_tmp_des,s_tmp_path = s_tmp.get_farest_way(s_tmp.body[-1][0],s_tmp.body[-1][1])
		if s_tmp_des != None:
			return s_tmp_des,s_tmp_path
		else:
			s = randint(1,4)
			tmp_x = randint(1,4)
			return 5,str(s)+str(tmp_x)

try:
	score = -1
	ms = curses.initscr()
	ms.border(0)
	s = Snake(None)
	s.rand_egg()
	s.show_border()
	ms.getch()
	step = 1
	direction = [[-1,0],[1,0],[0,1],[0,-1]]
	while True:
		#tmp_i = randint(1,4)
		#direc = s.get_direction()
		#ms.addstr(1,border_size[0]*2 + 2,direc)
		ms.addstr(3,border_size[0]*2 + 2,"step:"+str(step))
		#dire,path = s.automaticly_move()
		dire,path = go_and_predict(s)
		if dire == 5:
			dire = int(path[1])
			t = int(path[0])
			path = dire
			for i in range(t):
				s.move(dire)
		else:
			s.move(dire)
		ms.addstr(1,border_size[0]*2 + 2,"          ")
		ms.addstr(1,border_size[0]*2 + 2,"dir:"+map_dire(dire))
		ms.addstr(4,border_size[0]*2 + 2,"                                ")
		ms.addstr(4,border_size[0]*2 + 2,"path:"+str(path))
		ms.addstr(5,border_size[0]*2 + 2,"             ")
		if dire == None:
			next = None
			next_x = None
			next_y = None
			next_value = None
		else:		
			next = direction[dire-1]
			next_x = next[0]
			next_y = next[1]
			next_value = s.border[(s.body[0][0]+next[0]+border_size[1])%border_size[1]][(s.body[0][1]+next[1]+border_size[0])%border_size[0]]
		ms.addstr(5,border_size[0]*2 + 2,"next value:"+str(next_value))
		ms.addstr(6,border_size[0]*2 + 2,"     	  ")
		ms.addstr(6,border_size[0]*2 + 2,"dir:"+str(next_x)+"  "+str(next_y))
		ms.addstr(7,border_size[0]*2 + 2,"                      ")
		ms.addstr(7,border_size[0]*2 + 2,"Head:"+str(s.body[0][0])+" "+str(s.body[0][1]))
		ms.addstr(8,border_size[0]*2 + 2,"                      ")
		ms.addstr(8,border_size[0]*2 + 2,"Tail:"+str(s.body[-1][0])+" "+str(s.body[-1][1]))
		ms.addstr(9,border_size[0]*2 + 2,"               ")
		ms.addstr(9,border_size[0]*2 + 2,"score:"+str(score))
		s.show_border()
		time.sleep(0.02)
		step += 1
finally:
	curses.endwin()


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值