java - 如何降低圈复杂度?
问题描述
感谢您阅读我的问题。我目前正在 Coursera 上上 Java 课程,并被要求为这项作业编写一个关于扫雷的程序。我的代码创建了正确的结果,但我的成绩被大大扣分了,因为根据自动评分器的说法,我的代码“过于复杂,圈复杂度为 60”。我知道有太多的条件和循环,但我很难让它变得更简单。
这是我的代码。它需要 3 个整数命令行参数 m、n 和 k 来创建一个 m×n 网格,其中 k 个地雷位于随机位置。我使用“5”来标记地雷而不是“ ”,因为瓷砖中可以获得的最高数字是 4(因为瓷砖有 4 个面)。如果两个地雷并排放置,则可能会在其标记“5”中添加额外的值。因此,当我将所有值 >= 5打印出来时,我将它们变为“”。每个值由两个空格分隔。
public class Minesweeper {
public static void main(String[] args) {
int m = Integer.parseInt(args[0]);
int n = Integer.parseInt(args[1]);
int k = Integer.parseInt(args[2]);
int[][] mine = new int[m][n];
//put the mines
for(int z = 0; z < k; z++) {
int randomX = (int) (Math.random() * m);
int randomY = (int) (Math.random() * n);
mine[randomX][randomY] = 5;
}
for(int y = 0; y < n; y++) {
for(int x = 0; x < m; x++) {
//first row of the grid
if(y == 0) {
//upper left corner
if(x == 0) {
if(mine[x + 1][y] >= 5) {
mine[x][y] += 1;
}
if(mine[x][y + 1] >= 5) {
mine[x][y] += 1;
}
}
//upper right corner
else if(x == m - 1) {
if(mine[x - 1][y] >= 5) {
mine[x][y] += 1;
}
if(mine[x][y + 1] >= 5) {
mine[x][y] += 1;
}
}
//mid of first row
else {
if(mine[x - 1][y] >= 5) {
mine[x][y] += 1;
}
if(mine[x + 1][y] >= 5) {
mine[x][y] += 1;
}
if(mine[x][y + 1] >= 5) {
mine[x][y] += 1;
}
}
}
//mid rows
else if(y > 0 && y < n - 1) {
//left side
if(x == 0) {
if(mine[x][y - 1] >= 5) {
mine[x][y] += 1;
}
if(mine[x][y + 1] >= 5) {
mine[x][y] += 1;
}
if(mine[x + 1][y] >= 5) {
mine[x][y] += 1;
}
}
//right side
else if(x == m - 1) {
if(mine[x][y - 1] >= 5) {
mine[x][y] += 1;
}
if(mine[x][y + 1] >= 5) {
mine[x][y] += 1;
}
if(mine[x - 1][y] >= 5) {
mine[x][y] += 1;
}
}
//mid
else {
if(mine[x][y - 1] >= 5) {
mine[x][y] += 1;
}
if(mine[x][y + 1] >= 5) {
mine[x][y] += 1;
}
if(mine[x - 1][y] >= 5) {
mine[x][y] += 1;
}
if(mine[x + 1][y] >= 5) {
mine[x][y] += 1;
}
}
}
//bottom row
else if(y == n - 1) {
//bottom left corner
if(x == 0) {
if(mine[x + 1][y] >= 5) {
mine[x][y] += 1;
}
if(mine[x][y - 1] >= 5) {
mine[x][y] += 1;
}
}
//bottom right corner
else if(x == m - 1) {
if(mine[x - 1][y] >= 5) {
mine[x][y] += 1;
}
if(mine[x][y - 1] >= 5) {
mine[x][y] += 1;
}
}
//middle of the bottom row
else {
if(mine[x + 1][y] >= 5) {
mine[x][y] += 1;
}
if(mine[x - 1][y] >= 5) {
mine[x][y] += 1;
}
if(mine[x][y - 1] >= 5) {
mine[x][y] += 1;
}
}
}
}
}
//print out the grid
for(int y = 0; y < n; y++) {
for(int x = 0; x < m; x++) {
//println at the right edge of the grid
if(x == m - 1) {
if(mine[x][y] >= 5) {
System.out.println("*");
}
else {
System.out.println(mine[x][y]);
}
}
//other tiles, no need to switch lines
else {
if(mine[x][y] >= 5) {
System.out.print("* ");
}
else {
System.out.print(mine[x][y] + " ");
}
}
}
}
}
}
感谢您抽出宝贵时间,非常感谢您提出任何建议。
解决方案
如果您在循环中进行左/右/上/下测试以节省大量代码行,则可以降低复杂性:
for (int tryX = -1; tryX <= 1; tryX++) {
for (int tryY = -1; tryY <= 1; tryY++) {
if(mine[x + tryX][y + tryY] >= 5) {
mine[x][y] += 1;
}
}
}
由于这需要很多代码行,因此会降低复杂性。您应该使用 IDE 将代码提取到方法中(有关 IntelliJ,请参见此处)。好的提取点是循环。
我看到两个很好的提取点:
- initArrayWithRandomMines()
- 计算NeighborMines()
推荐阅读
- flutter - 在flutter webview应用程序中删除网站浮动操作按钮
- python - 合并来自 Github Repository Link 的所有 csv 文件并使其成为一个 csv 文件
- nginx - 为什么代理传递不适用于 set $variable?
- ssl - azure windows server 2016 上的启动脚本
- android - 什么是 sdk_version:“module_current”与 sdk_version:“system_current”?
- java - Java 扫描器如何正确读取字符串
- android - 从图像选择器打开相机时,应用程序“失去与设备的连接”会颤抖。
- javascript - 如何获取地图中的每个元素并更改其 CSS?
- python - 为什么维特比算法(POS标注)总是预测一个标签?
- material-ui - 如何在无服务器堆栈中使用模块别名?