Java写一条吃全屏幕的贪吃蛇(A*自动寻路算法和一些简单的策略) 三

本文介绍了使用Java编写贪吃蛇游戏时,如何运用A*自动寻路算法确保蛇能始终找到安全路径。在蛇身体增长过程中,为避免堵住自己的退路,会在每一步前预判下一步的安全性。文章提供了完整的代码示例,包括Food、Snake和Play三个类,其中包含了多种实现思路和调试信息。
摘要由CSDN通过智能技术生成

这几天在琢磨反射和动态代理,难度有点高,这博客拖了好久才来完成它。虽然在学校学习了Java和一些其他语言,但是高级特性接触得都不多,主要还是面向过程编程,看了这么多书,慢慢的体悟了面向对象的好处,内心十分触动。以后写代码尽量做到功能单一,便于拓展,便于维护,面向对象。

    贪吃蛇吃满屏幕的要点在于,要有一条安全的路径,不管发生什么情况,只要安全路径存在,贪食蛇就能坚持走下去,所以第一步我们要找一条一直存在的安全路径:我们很容易想到贪吃蛇是可以绕圈圈的,蛇头跟着蛇尾走,就一直绕圈,不会撞墙或者撞自己的身体,所以只要蛇头和蛇尾吧之间存在一条路径,那不管发生了什么情况蛇都可以调整自己的状态。

    小蛇什么时候要走安全路径?一般来说当小蛇自动吃食物的时候,根据我们的算法,它会找到最短的路径去吃食物,然而因为蛇身体是不断增长的,有一些时候他的身体会把食物三面围起来,这时候再走最短路径去吃食物,很显然,蛇身体就会堵住所有的退路,然后就无路可走,我们应该避免这种情况,所以我们应该在蛇走的每一步之前预判断一下,他的下一步安全吗?

完整代码如下,还有一些坑,都是当初设计代码的时候留下的,但是基本功能实现了,给读者做参考,注释比较多,所以不再解释了。


一共有三个类

Food类内容如下:

import java.util.Random;

public class Food {
	private int x;
	private int y;
	private int length ;
	private int width ;
	private int pace;
	
	public Food(int length, int width,int pace) {
		super();
		random = new Random();
		this.length = length;
		this.width = width;
		this.pace = pace;
		
	}
	private Random random;
	
	public int getX() {
		return x;
	}
	
	public int getY() {
		return y;
	}
	
	public void setX(int x) {
		this.x = x;
	}

	public void setY(int y) {
		this.y = y;
	}

	public void setY() {
		this.y = random.nextInt(width/pace)*pace;
	}
	public void setX() {
		this.x = random.nextInt( length/pace)*pace;
	}
	/*public void setY(int sss) {
		this.y = yyy[sss-1];
	}
	public void setX(int sss) {
		this.x = xxx[sss-1];
	}*/
	
}

Snake类内容如下:


import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.Set;

class Road {
	private int x;
	private int y;
	private Road father;

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + x;
		result = prime * result + y;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Road other = (Road) obj;
		if (x != other.x)
			return false;
		if (y != other.y)
			return false;
		return true;
	}

	public int getX() {
		return x;
	}
	

	public void setX(int x) {
		this.x = x;
	}

	public int getY() {
		return y;
	}

	public void setY(int y) {
		this.y = y;
	}

	public void setFather(Road father) {
		this.father = father;
	}

	public Road() {
		super();
		// TODO Auto-generated constructor stub
	}

	public Road(int x, int y, Road father) {
		super();
		this.x = x;
		this.y = y;
		this.father = father;
	}

	public Road getFather() {
		return father;
	}
}

public class Snake {
	private int x;
	private int y;
	private int length;
	private int pace;
	private int nextx;
	private int nexty;
	private int tailx;
	private int taily;
	//Distance from the target
	private int dFromT;
	private int len;
	private int width;
	private String direction;
	private ArrayList<Node> snake = new ArrayList<Node>();

	
	public int getDFromT() {
		return dFromT;
	}

	public void setDFromT(int distance) {
		this.dFromT = distance;
	}

	{
		dFromT = 0;
		nextx = -1;
		nexty = -1;

	}

	public int getTailx() {
		return tailx;
	}

	public void setTailx(int tailx) {
		this.tailx = tailx;
	}

	public int getTaily() {
		return taily;
	}

	public void setTaily(int taily) {
		this.taily = taily;
	}

	public int getNextx() {
		return nextx;
	}

	public void setNextx(int nextx) {
		this.nextx = nextx;
	}

	public int getNexty() {
		return nexty;
	}

	public void setNexty(int nexty) {
		this.nexty = nexty;
	}

	public int getPace() {
		return pace;
	}

	public void setPace(int pace) {
		this.pace = pace;
	}

	public int getLength() {
		return length;
	}

	private class Node {
		private int x;
		private int y;

		public Node(int x, int y) {
			super();
			length++;
			this.x = x;
			this.y = y;
		}

		public int getX() {
			return x;
		}

		public void setX(int x) {
			this.x = x;
		}

		public int getY() {
			return y;
		}

		public void setY(int y) {
			this.y = y;
		}

	}

	public boolean eat(Food fd) {
		if (fd.getX() == this.x && fd.getY() == this.y) {
			System.out.println("吃东西啦!好开心~");
			snake.add(new Node(tailx, taily));
			return true;
		}
		return false;
	}

	public int show(int i, int j) {
		int num = 0;
		for (Node node : snake) {
			if (node.getX() == i && node.getY() == j) {
				// System.out.println("冲突检测");
				return num;
			}
			num++;
		}
		return -1;
	}
	public boolean run(Food fd){
		if(fd.getX()>this.x){
			this.nextx+=this.pace;
			this.nexty = this.y;
		}else if(fd.getX()<this.x){
			this.nextx-=this.pace;
			this.nexty = this.y;
		}else if(fd.getY()>this.y){
			this.nextx = this.x;
			this.nexty+=this.pace;
		}else if(fd.getY()<this.y){
			this.nextx = this.x;
			this.nexty-=this.pace;
		}else{
			return false;
		}
		return true;
	}
	
	public boolean hangOut(int ax,int ay) {
		System.out.println("进入闲逛模式,参数是需要远离的点,如果没有办法选择安全路径就会切换到不安全的随机模式");
		
		int[][] map;
		map = new int[this.len][this.width];
		int aimx = ax;
		int aimy = ay;
		//标记食物不可以吃,吃食物必须在外面
		for (Node node : snake) {
			if (node.getX() >= 0 && node.getY() >= 0) {
				map[node.getX()][node.getY()] = 1;
			}
		}

		int findx = this.x;
		int findy = this.y;
		boolean reflag = false;
		int biggerManha = 0;
		int ManhattanDistance = 0;
		int defaultx = -1;
		int defaulty = -1;
		int space = -1;
		int willGo = findx + this.pace;
		int biggerStep = -1;
		if (willGo < len && map[willGo][findy] != 1) {

			// 如果这一步在棋盘范围内,而且不会撞上蛇身
			// 计算它和食物的哈曼吨距离
			ManhattanDistance = Math.abs(aimx - (willGo)) + Math.abs(aimy - findy);
			System.out.println("右移 最大距离:" + biggerManha + " 本次距离:" + ManhattanDistance);

			// 如果longdistance记录的哈曼吨距离小于这个点的
			if (biggerManha <= ManhattanDistance || defaultx == -1) {
				// 记录下这个点的曼哈顿距离还有坐标,这一点就是远离食物的点,我们还要检测它是不是能找到尾巴

				if (findShortestRoad(willGo, findy, tailx, taily)) {
					if (biggerStep < this.dFromT) {
						biggerStep = this.dFromT;

						biggerManha = ManhattanDistance;
						if (dFromT > space) {
							defaultx = willGo;
							defaulty = findy;
							this.nextx = willGo;
							this.nexty 
  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值