我有下面的for循环,它应该生成两个随机整数并调用grid.place(x,y)。如果grid.place(x,y)返回false,我想知道如何生成不同的对。如果提供的x和y以前没有提供,place方法将返回true。谢谢。
for (int i = 0; i < 10; i++) {
mx = randomGenerator.nextInt(10);
my = randomGenerator.nextInt(10);
grid.place(mx,my);
}发布于 2017-05-31 18:25:11
这是do-while循环的最佳情况:
for (int i = 0; i < 10; i++) {
do{
mx = randomGenerator.nextInt(10);
my = randomGenerator.nextInt(10);
}while(!grid.place(mx,my));
}另一个解决方案是使用Collections.shuffle()方法。就像这样:
List<Integer> xPos = IntStream.rangeClosed(0,10).boxed().collect(Collectors.toList());
List<Integer> yPos = IntStream.rangeClosed(0,10).boxed().collect(Collectors.toList());
Collections.shuffle(xPos);
Collections.shuffle(yPos);
for(int i=0;i<10;i++)
grid.place(xPos.get(i), yPos.get(i));这将为您提供所有的和弦,并且不会比do-while循环更复杂地重复。
发布于 2017-05-31 18:24:21
为了避免重复,您可以使用一个列表,例如:
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
list.add(i);//fill your list
}
Random randomGenerator = new Random();
int mx = randomGenerator.nextInt(10);//generate the first value
int x = mx;//to not lost this value we store it in another variable
list.remove(mx);//remove the first value from your list, to avoid duplicate
int my = randomGenerator.nextInt(9);//generate the second value
int y = my;
grid.place(x, y);//now, you are sure that you have two different values 发布于 2017-05-31 18:49:38
下面是一种更像OO的方法:
最有可能的是,“网格”不是无限的。这意味着您可以创建网格中所有可能位置的列表:
class Position{
private final int x;
private final int y;
public Position(int x, int y){
this.x=x;
this.y=y;
}
public getX(){return x;}
public getY(){return y;}
}
List<Position> availablePositions = new ArrayList<>();
for(int i =0; i<MAX_X;i++)
for(int j =0; j<MAX_Y;j++)
availablePositions.add(new Position(i,j));然后您可以从该列表中检索一个随机索引:
for (int i =0;i<10;i++){
Position randomPosition =
availablePositions.remove(
new Random().nextInt(availablePositions.size()));
grid.place(
randomPosition.getX(),
randomPosition.getY());
}这样,您将永远不会得到一个重复,但所采取的立场是失去程序当前的执行。
或者,您只需对列表进行洗牌,并获取前10个元素:
Collections.shuffle(availablePositions);
for (int i =0;i<10;i++)
grid.place(
availablePositions.get(i).getX(),
availablePositions.get(i).getY());这也确保了循环中不同的位置,但您可以将列表中的所有位置保留在列表中供以后使用.
这个解决方案最大的问题是它有确定的时间,而代价是O(MAX_X * MAX_Y)内存。其他解决方案有O(1)时间(对于i的小值),虽然不是确定性的,还有O(1)内存。-戈博纳多
在现代计算机上,内存不是限制资源(甚至在手机上也不是.)。在用Java进行编程时,除非您已经证明存在问题,否则不应该优化内存和/或性能。如果您真的有内存问题,那么Java很可能是任务的错误工具。
但是:
当我们在解决方案中接受更多的OO时,我们将不需要单独的
Position对象占用内存。我们可以让Cell具有我们可以更改的状态,而不是网格中不可变的String对象。将自定义类作为网格中的元素使用,除了启用这种选择机制之外,还有更多的优点,因此我们应该看看它。
Cell.java
class Cell{
private String content = " "; // empty
public void placeHere(String newContent){
content = newContent;
}
}Grid.java
// ... Cell[][] gameField = new Cell[MAX\_X][MAX\_Y]; for(int i =0; i 然后,我们可以在一个单独的列表中收集现有的单元格:
List allCells =新的ArrayList<>();for(Cell[]行: gameField) allCells.addAll(Arrays.asList(行));
并选择随机单元来更改状态:
Collections.shuffle(allCells);
for(int i =0; i<10; i++)
allCells.get(i).placeHere("*");实际上,我们甚至不需要知道变化的细胞坐标。这就是OOP的意义所在:用代码中尽可能少的技术知识来解决任务。
等等,还有更多:
如何使用纯String数组重置游戏?对,迭代整个数组。但我得到的最佳性能优化提示是:
做某事最快的方法就是不去做。
那么,我们如何避免对完整数组的迭代呢?
使用我的方法,我们可以在一个单独的列表中收集修改后的单元格:
List<Cell> modifiedCells = new ArrList<>();
Collections.shuffle(allCells);
for(int i =0; i<10; i++){
Cell currentCell = allCells.get(i);
currentCell.placeHere("*");
modifiedCells.add(currentCell);
}然后,您必须重置该额外列表中的10单元对象,而不是数组中的MAX_X*MAX_Y字符串。
https://stackoverflow.com/questions/44292048
复制相似问题