我在线查看了多个示例,但我似乎无法理解这里发生的事情。当程序打印出当前玩家和分数时,对我来说这些存储的位置并不明显。我是一个初学者,我被告知要分析这段代码以帮助更好地理解"我们目前的课程项目。
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]));
}
}
答案 0 :(得分:4)
要理解这段代码的作用,我首先应用几个关键的重构:
将所有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
和{{1}中维护}。
safeScore
阶段仅传递大于-1的值,因此在游戏进行过程中会丢弃所有前导-1值的值,只有在玩家获胜后才会产生值。
filter()
阶段获取第一个元素,然后终止流。这就是游戏最终终止的原因。
现在,findFirst()
返回findFirst()
,其中包含获胜玩家的号码。通常它可能是空的,但在这种情况下它永远不会为空,因为OptionalInt
产生无限流。因为它永远不会为空,所以iterate()
内的lambda表达式总是被执行并传递给获胜玩家的号码;这打印出最终的游戏结果。
这基本上就是这样的。
请注意,正如我和其他人在评论中指出的那样,这里有几个不良的代码气味和反模式,加上一些错误。我强烈建议不使用它作为良好的lambda和流编码实践的一个例子。