ArrayList 选择坐标,如果客户端少于坐标,则为每个客户端提供一个坐标


    Coordinate[] coords = {
        new Coordinate(3093, 3630), new Coordinate(3095, 3632), new Coordinate(3098, 3633),
        new Coordinate(3101, 3633), new Coordinate(3104, 3631), new Coordinate(3106, 3629), 
        new Coordinate(3107, 3627), new Coordinate(3108, 3624), new Coordinate(3109, 3620),
        new Coordinate(3108, 3617), new Coordinate(3106, 3614), new Coordinate(3102, 3613),
        new Coordinate(3099, 3613), new Coordinate(3097, 3613), new Coordinate(3093, 3614),
        new Coordinate(3090, 3617), new Coordinate(3087, 3619)
    };

    int random = Misc.random(coords.length - 1);
    Coordinate coord = coords[random];
    boolean found = false;
    if (insidePlayers.size() < coords.length) {
        if (spawnPoints.contains(coord)) {
            found = false;
        }
        while (!found) {
            random = Misc.random(coords.length - 1);
            coord = coords[random];
            if (!spawnPoints.contains(coord)) {
                player.spawnPointX = coords[random].getX();
                player.spawnPointY = coords[random].getY();
                spawnPoints.add(coord);
                found = true;
                break;
            }
        }
    }
    else {
        player.spawnPointX = coords[random].getX();
        player.spawnPointX = coords[random].getY();
    }

基本上,我在这里要做的是,如果客户端多于可用坐标(点(,则为每个玩家提供自己的坐标(因此其他客户端不能具有相同的坐标(。

但不幸的是,它不起作用,有时客户端会得到相同的坐标。为什么会这样?我做错了什么?

坐标类:

public class Coordinate {
    private int x = 0;
    private int y = 0;
    public Coordinate(int x, int y) {
        this.x = x;
        this.y = y;
    }
    public int getX() {
        return x;
    }
    public int getY() {
        return y;
    }
}

数组列表:

public static ArrayList<Coordinate> spawnPoints = new ArrayList<Coordinate>();

那么那里有什么问题呢?

您需要覆盖坐标类中的equals()

@override
public void equals(Object o){
if(o==null)
 return false;
if(!(o instanceof Coordinate)){
  return false;
Coordinate newO = (Coordinate) o;
if(this.x == newO.x && this.y == newO.y)
  return true
return false;
}

这是因为 ArrayList#contains 使用 ArrayList#indexOf((,定义为:

public int indexOf(Object o) {
         if (o == null) {
             for (int i = 0; i < size; i++)
                 if (elementData[i]==null)
                     return i;
         } else {
             for (int i = 0; i < size; i++)
                 if (o.equals(elementData[i])) /// <--- Uses .equals()
                     return i;
         }
         return -1;
     }

注意:当你在它的时候,也覆盖hashCode((。在您的情况下,您并不真正需要它,但这是一个很好的做法,如果您使用基于哈希的数据结构,它将对您有所帮助。这将有所帮助。

所以本质上你有一组重生点,你想在这些点上生成玩家,但没有两个玩家可以拥有相同的重生点。一种更简单的方法是在将坐标提供给玩家后从列表中删除坐标。不确定您如何输入客户(玩家(,如果此解决方案没有帮助,请详细说明。

 Coordinate[] coords = {
    new Coordinate(3093, 3630), new Coordinate(3095, 3632), new Coordinate(3098, 3633),
    new Coordinate(3101, 3633), new Coordinate(3104, 3631), new Coordinate(3106, 3629), 
    new Coordinate(3107, 3627), new Coordinate(3108, 3624), new Coordinate(3109, 3620),
    new Coordinate(3108, 3617), new Coordinate(3106, 3614), new Coordinate(3102, 3613),
    new Coordinate(3099, 3613), new Coordinate(3097, 3613), new Coordinate(3093, 3614),
    new Coordinate(3090, 3617), new Coordinate(3087, 3619)
};
public static List<Coordinate> coordinates = new ArrayList<>(Arrays.asList(coords));
public static final Random rnd = new java.util.Random();
if(!coordinates.isEmpty())
    int randomIndex = rnd.nextInt(coordinates.size());
    Coord randomCoord = coordinates.get(randomIndex);
    player.spawnPointX = randomCoord.getX();
    player.spawnPointY = randomCoord.getY();
    coordinates.remove(randomIndex);
else
    System.out.println("No more coordinates left to assign to player");

我认为问题是两个因素的组合:1(您每次都在方法中分配一个新的coords数组;2(您的Coordinate类没有实现equals()hashCode()。这些导致问题的原因是,从Object继承的equals()hashCode()的默认实现基于对象标识,而不是值的相等性。结果是,如果在一次调用中,将值为 (例如( x=3093 和 y=3630 的Coordinate添加到 spawnPoints 中,则在下一次调用中,具有相同 x 和 y 值的新 Coordinate 对象将测试为不包含在 spawnPoints 中。

我认为这可以通过以下两种方式之一来解决:

  1. coords数组声明为static final字段,而不是每次都向方法分配一个新数组。那么对象标识就足以满足你的逻辑了。
  2. 实现Coordinate.equals(Object)Coordinate.hashCode(),以便具有相同xy字段值的Coordinate对象测试是否相等并具有相同的哈希代码。

即使第一种方法解决了问题,您也应该强烈考虑实现equalshashCode,尤其是在将Coordinate对象添加到其他集合时。

最新更新