我在网上查找了多个示例,但我似乎无法理解这里发生的情况。当程序打印出当前玩家和分数时,我不清楚它们存储在哪里。我是一名初学者,我被告知分析这段代码以帮助“更好地理解”我们当前的类项目。
import java.util.Arrays;
import java.util.Random;
import java.util.Scanner;
import java.util.stream.IntStream;
public interface PigDice {
public static void main(String... arguments) {
final int maxScore = 100;
final int playerCount = 2;
final String[] yesses = { "y", "Y", "" };
final Scanner scanner = new Scanner(System.in);
final Random random = new Random();
final int[] safeScore = new int[2];
final int[] score = new int[2];
IntStream.iterate(0, player -> (player + 1) % playerCount).map(player -> {
boolean isRolling = true;
while (isRolling) {
System.out.printf("Player %d: (%d, %d) Rolling? (y/n) ", player, safeScore[player], score[player]);
isRolling = safeScore[player] + score[player] < maxScore
&& Arrays.asList(yesses).contains(scanner.nextLine());
if (isRolling) {
final int rolled = random.nextInt(6) + 1;
System.out.printf("Rolled %d\n", rolled);
if (rolled == 1) {
System.out.printf("Bust! You lose %d but keep %d\n\n", score[player], safeScore[player]);
return -1;
} else {
score[player] += rolled;
}
} else {
safeScore[player] += score[player];
if (safeScore[player] >= maxScore) {
return player;
}
System.out.printf("Sticking with %d\n\n", safeScore[player]);
}
}
score[player] = 0;
return -1;
}).filter(player -> player > -1).findFirst().ifPresent(
player -> System.out.printf("\n\nPlayer %d wins with a score of %d", player, safeScore[player]));
}
}
最佳答案
为了理解这段代码的作用,我首先应用几个关键的重构:
将
main()
的所有局部变量提升为PigDice
类的静态变量。将传递给
map()
的大型多行 lambda 提取到PigDice
类的静态方法中。调用此方法turn()
:static int turn(int player) { ... }
流管道现在看起来像这样:
IntStream.iterate(0, player -> (player + 1) % playerCount)
.map(PigDice::turn)
.filter(player -> player > -1)
.findFirst()
.ifPresent(
player ->
System.out.printf("\n\nPlayer %d wins with a score of %d",
player, safeScore[player]));
IntStream.iterate()
方法生成一个 int
值流,从提供的初始值开始,在本例中初始值为零。后续值由 lambda 表达式计算。在此,该表达式加一并用 playerCount
计算余数,在本例中为 2。结果是值 0, 1, 0, 1, 0, 1, ... 的流,表示轮到的玩家编号。
map()
阶段将每个值传递给 turn()
方法,该方法执行所有游戏逻辑。但如果你简化这个逻辑,基本上,如果没有获胜者,它会返回 -1;如果该玩家获胜,它会返回其输入参数(当前玩家编号)。如果玩家 0 获胜,则结果为流 -1, -1, -1, -1, ... 0(如果玩家 1 获胜,则最后一个值为 1)。
来自 map()
的结果流只是故事的一部分。实际的游戏逻辑通过对游戏状态的副作用进行操作,这些状态保存在捕获的变量scanner
、random
、score<中
和 safeScore
。
filter()
阶段仅传递大于 -1 的值,因此它会在游戏进行时丢弃所有前导 -1 值,仅在玩家获胜后才生成值.
findFirst()
阶段获取第一个元素,然后终止流。这就是游戏最终终止的原因。
现在,findFirst()
返回一个 OptionalInt
,其中包含获胜玩家的号码。一般来说,它可能是空的,但在这种情况下,它永远不会是空的,因为 iterate() 会产生无限流。由于它永远不会为空,因此 ifPresent()
内部的 lambda 表达式始终会被执行,并传递获胜玩家的号码;这会打印出最终的游戏结果。
这基本上就是它的工作原理。
请注意,正如我和其他人在评论中指出的那样,这里存在一些不好的代码味道和反模式,以及一些错误。我强烈建议不要使用此作为良好的 lambda 和流编码实践的示例。
关于java - 有人可以向我简要解释一下 IntStream 发生了什么吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35051248/