一个 Boolean 的有趣的扩展

我定义了一个叫做 isEnabled 的变量:

 var isEnabled: Boolean = ... 

后面要用它的时候通常来说我会直接写出这个变量名,然后想到还得写个 if ... else,就像这样:

 if(isEnabled) ... else ... 

当然 IntelliJ 也为我们提供了后缀表达式快速输入 if 语句:

0?wx_fmt=gif

当我想要做一个判断的时候,我首先想到的是这个变量 isEnabled,于是通常我会很快的把它给打出来,接着我想着如果它为 true,那么如何如何,这时候还需要把光标移到最开始,写下 if,尽管我们刚说 IntelliJ 提供了后缀表达式来简化这个输入过程,但还是不能改变这个反人类的输入本质啊。

我想要的就是一个数据处理流,每一次函数调用都是一次数据的变换,if 的出现破坏了流的结构。

相比之下我更喜欢下面的写法:

 isEnabled.yes { 
    ... 
 }.otherwise { 
    ... 
 } 

如果你还是看不出来 if 到底有什么“罪过”,那我们再来看一个场景:

 args 
     .map(String::toInt) 
     .filter{    it % 2 == 0        } 
     .count().equals(5) 
 ... 

例子是我瞎写的,不用在意它的含义。假设我们通过一系列的函数调用得到了一个 Boolean 值,并且需要根据它的值来做出一些操作,那么我们是不是应该在外面套一层 if else 语句呢?

 if(args 
    .map(String::toInt) 
    .filter{    it % 2 == 0     } 
    .count() == 5 
 ){ 
     println("输入参数中偶数的个数为5") 
 } else { 
     println("输入参数中偶数的个人不为5") 
 } 

而我们通过扩展完全可以实现下面的写法:

 args 
     .map(String::toInt) 
     .filter{    it % 2 == 0        } 
     .count().equals(5) 
     .yes { 
         println("输入参数中偶数的个数为5") 
     }.otherwise { 
         println("输入参数中偶数的个人不为5") 
     } 

如果分支语句中还有返回值,我们也可以接着向下执行(当然,对于有返回值的分支语句,我们要求分支完备,也就是必须有 otherwise 调用):

 args.map(String::toInt).filter{ 
         it % 2 == 0 
     }.count().equals(5).yes { 
         "666" 
     }.otherwise { 
         "23333" 
     }.let(::println) 

另外,我们可以稍稍做下修改,让语法变得更简单(并且不易懂= =?):

 isEnabled { 
     "666" 
 } otherwise { 
     "2333" 
 } 

不过这样写有个弊端,就是在前面的 Boolean 值是个表达式的时候,需要加括号, otherwise 调用之后如果还有后续操作,那么也会产生歧义。当然这一步其实不是很必须了,做到前面的步骤已经足够。

下面我们来看下扩展的源码:

 sealed class BooleanExt<out T> constructor(val boolean: Boolean) 
   
 object Otherwise : BooleanExt<Nothing>(true) 
 class WithData<out T>(val data: T): BooleanExt<T>(false) 
   
 inline fun <T> Boolean.yes(block: () -> T): BooleanExt<T> = when { 
     this -> { 
         WithData(block()) 
     } 
     else -> Otherwise 
 } 
   
 inline fun <T> Boolean.no(block: () -> T) = when { 
     this -> Otherwise 
     else -> { 
         WithData(block()) 
     } 
 } 
   
 inline infix fun <T> BooleanExt<T>.otherwise(block: () -> T): T { 
     return when (this) { 
         is Otherwise -> block() 
         is WithData<T> -> this.data 
         else ->{ 
             throw IllegalAccessException() 
         } 
     } 
 } 
   
 inline operator fun <T> Boolean.invoke(block: () -> T) = yes(block) 

如果你有兴趣加入我们,请直接关注公众号 Kotlin ,或者加 QQ 群:162452394 (必须正确回答加群暗号哈,防止特务混入)联系我们。

0?wx_fmt=jpeg


好的,我会尽力回答你的问题。 骑士巡游游戏是一个经典的回溯算法问题,其中骑士需要从一个给定的起始位置出发,沿着棋盘上的八个方向移动,每个位置只能走一次,最终到达终点位置。在这个过程中,我们需要找到一条能够经过棋盘上所有位置的路径。 下面是实现骑士巡游游戏的Java代码: ```java public class KnightTour { private static final int BOARD_SIZE = 8; private static int[][] board; private static final int[] xMoves = {2, 1, -1, -2, -2, -1, 1, 2}; private static final int[] yMoves = {1, 2, 2, 1, -1, -2, -2, -1}; public static void main(String[] args) { board = new int[BOARD_SIZE][BOARD_SIZE]; solveKnightTour(0, 0, 1); } private static void solveKnightTour(int row, int col, int move) { board[row][col] = move; if (move == BOARD_SIZE * BOARD_SIZE) { printBoard(); } else { for (int i = 0; i < xMoves.length; i++) { int nextRow = row + xMoves[i]; int nextCol = col + yMoves[i]; if (isValidMove(nextRow, nextCol)) { solveKnightTour(nextRow, nextCol, move + 1); } } } board[row][col] = 0; } private static boolean isValidMove(int row, int col) { if (row < 0 || row >= BOARD_SIZE || col < 0 || col >= BOARD_SIZE) { return false; } return board[row][col] == 0; } private static void printBoard() { for (int i = 0; i < BOARD_SIZE; i++) { for (int j = 0; j < BOARD_SIZE; j++) { System.out.print(board[i][j] + " "); } System.out.println(); } System.out.println(); } } ``` 在这个代码中,我们创建了一个8x8的棋盘,并初始化了一个二维数组来表示每个位置的状态(0表示未访问,1-64表示访问的顺序)。我们还定义了两个数组来表示骑士可以走的8个方向。 我们使用递归的方式来查找一条能够经过棋盘上所有位置的路径。在每个位置,我们尝试向8个方向移动,并检查下一个位置是否合法(未访问过且在棋盘范围内)。如果找到了一条完整的路径,我们就打印出解决方案。 最后,我们需要在main方法中调用solveKnightTour方法来开始查找解决方案。 这是一个基本的骑士巡游游戏的实现,你可以根据你的需要对其进行修改和扩展,来创建更加复杂和有趣的游戏。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值