在二维数组Java中绘制数字菱形

时间:2018-09-27 01:47:44

标签: java arrays

我一直在解决一些编码问题,以使自己为参加编码面试做好准备,并且发现了一个似乎令人费解的问题。我花了一些时间解决了这个问题。但是,代码看起来是硬编码的,没有样式。因此,我想知道我是否可以获得有关代码样式的反馈,或者是否有解决此问题的更好的主意。

问题基本上是要求您在2d阵列中绘制带有图案的数字菱形。 它给出了“ x”的坐标和x的范围。从x开始,数字一一展开,直至达到范围。因此,有4种不同的输入,即N(数组的大小),X,Y(“ x”的坐标为(行,列)的坐标)和R(范围)。

如果给定它们的大小为8,则坐标(4,5)的范围为3,结果将是这样,

0 0 0 0 3 0 0 0
0 0 0 3 2 3 0 0
0 0 3 2 1 2 3 0
0 3 2 1 x 1 2 3
0 0 3 2 1 2 3 0
0 0 0 3 2 3 0 0
0 0 0 0 3 0 0 0
0 0 0 0 0 0 0 0

下面是我所拥有的,

    int n = sc.nextInt();
    char[][] arr = new char[n][n];
    int r = sc.nextInt() - 1;
    int c = sc.nextInt() - 1;
    int range = sc.nextInt();

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            arr[i][j] = '0';
        }
    }

    arr[r][c] = 'x';


    int num = 1;
    for (int i = 0; i < range; i++) {
        //Cross
        if (c-num > -1) {
            arr[r][c - num] = (char) (num + '0');
        }
        if (c+num < n) {
            arr[r][c + num] = (char) (num + '0');
        }
        if (r-num > -1) {
            arr[r - num][c] = (char) (num + '0');
        }
        if (r+num < n) {
            arr[r + num][c] = (char) (num + '0');
        }
        //Diagonal
        if (i > 0) {
            int sum = num - 1, delta = 1;

            while (sum != 0) {
                if (r-sum > -1 && c+delta < n) {
                    arr[r - sum][c + delta] = (char) (num + '0');
                }
                sum--;
                delta++;
            }
            sum = num - 1; delta = 1;
            while (sum != 0) {
                if (r+sum < n && c-delta > -1) {
                    arr[r + sum][c - delta] = (char) (num + '0');
                }
                sum--;
                delta++;
            }
            sum = num - 1; delta = 1;
            while (sum != 0) {
                if (r-sum > -1 && c-delta > -1) {
                    arr[r - sum][c - delta] = (char) (num + '0');
                }
                sum--;
                delta++;
            }
            sum = num - 1; delta = 1;
            while (sum != 0) {
                if (r+sum < n && c+delta > -1) {
                    arr[r + sum][c + delta] = (char) (num + '0');
                }
                sum--;
                delta++;
            }
        }
        num++;
    }

除了使用四个不同的while循环外,我没有其他方法可以处理对角线数字。我将不胜感激。预先感谢!

3 个答案:

答案 0 :(得分:1)

您只需在数组上循环一次,然后根据当前位置(i, j)与固定坐标(x, j)的相对距离来设置值。

您的代码可能如下所示:

import java.util.Arrays;

public class Test {
    public static void main(String[] args) {
        // variables
        int n = 8;
        int x = 4 - 1; // coordinates are one-based
        int y = 5 - 1; // coordinates are one-based
        int r = 3;
        char[][] array = new char[n][n];

        // logic
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                int dist = Math.abs(x - i) + Math.abs(y - j); // calculate distance

                if(dist == 0) {         // at x,y
                    array[i][j] = 'x';
                } else if (dist <= r) { // distance to x,y is within range
                    array[i][j] = (char) (dist + '0');
                } else {                // distance to x,y is outside of range
                    array[i][j] = '0';
                }
            }
        }

        // dump output
        System.out.println(Arrays.deepToString(array)
                           .replace("], ", "]\n")
                           .replace("[", "")
                           .replace("]", "")
                           .replace(", ", " "));
    }
}

将产生以下输出:

0 0 0 0 3 0 0 0
0 0 0 3 2 3 0 0
0 0 3 2 1 2 3 0
0 3 2 1 x 1 2 3
0 0 3 2 1 2 3 0
0 0 0 3 2 3 0 0
0 0 0 0 3 0 0 0
0 0 0 0 0 0 0 0

如果您想更加简洁,可以用三元运算符替换分支的if… else if… else语句:

array[i][j] = dist == 0 ? 'x' : dist <= r ? (char) (dist + '0') : '0';

答案 1 :(得分:0)

您可以尝试使用Floodfill,尽管根据您的级别可能会有点远。

https://en.wikipedia.org/wiki/Flood_fill

编辑:Robby Cornelissen的代码比我的代码看起来更干净,更简单,因此您应该检查一下他的代码。但是,以后充水是一个非常重要的概念,因此不妨检查一下。

这篇文章很长,但是文章中的GIF是最重要的部分。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class test {

    public static void main(String[] args) throws IOException {
        //Get inputs (I used BufferedReader, Scanner works fine as well)
        //My inputs are formatted as 'N X Y R' (ex. '8 4 5 3')
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine(), " ");
        int N = Integer.parseInt(st.nextToken());
        int R = Integer.parseInt(st.nextToken()) - 1;
        int C = Integer.parseInt(st.nextToken()) - 1;
        int range = Integer.parseInt(st.nextToken());
        char[][] arr = new char[N][N];

        //Make everything in array '0'
        for (int i = 0; i < N; i++) {
            Arrays.fill(arr[i], '0');
        }

        //Floodfill using BFS
        //FYI: this BFS is iterative, not recursive
        Queue<int[]> q = new LinkedList<>();
        q.add(new int[]{0, R, C});
        while (!q.isEmpty()) {
            int[] current = q.remove();
            if (arr[current[1]][current[2]] == '0' && current[0] <= range) {
                arr[current[1]][current[2]] = (current[0]+"").charAt(0);
                if(current[1]+1 < N) q.add(new int[]{current[0]+1, current[1]+1, current[2]});
                if(current[1]-1>= 0) q.add(new int[]{current[0]+1, current[1]-1, current[2]});
                if(current[2]+1 < N) q.add(new int[]{current[0]+1, current[1], current[2]+1});
                if(current[2]-1>= 0) q.add(new int[]{current[0]+1, current[1], current[2]-1});
            }
        }
        arr[R][C] = 'x';

        //Print out the final grid
        for (int i = 0; i < N; i++) {
            for (int j = 0; j< N; j++) {
                System.out.print(arr[i][j] + " ");
            }
            System.out.println();
        }
    }
}

答案 2 :(得分:0)

这是一个相当紧凑的方法。在每次迭代i中,我们用i+1菱形环(以i+1为中心,用值(row, col)填充单个字符宽的i。为避免填充钻石内部,我们检查到(row, col)的曼哈顿距离等于i-这仅适用于钻石边界上的单元格。

static char[][] buildDiamond(int n, int row, int col, int range)
{
  char[][] arr = new char[n][n];
  for(char[] a : arr) Arrays.fill(a, '0');
  arr[row][col] = 'x';

  for(int i=1; i<=range; i++)
    for(int j=0; j<=i; j++)
      for(int k=0; k<=i; k++)
        if(Math.abs(k-j) + Math.abs(k+j-i) == i)
          arr[row+k-j][col+k+j-i] += i;

  return arr;
}

测试:

public static void main(String[] args)
{
  for(char[] a : buildDiamond(7, 3, 3, 3)) 
    System.out.println(new String(a).replaceAll(".", "$0 "));
}

输出:

0 0 0 3 0 0 0 
0 0 3 2 3 0 0 
0 3 2 1 2 3 0 
3 2 1 x 1 2 3 
0 3 2 1 2 3 0 
0 0 3 2 3 0 0 
0 0 0 3 0 0 0