java - 2D字符格式数组

标签 java arrays multidimensional-array graph formatting

因此,我正在编写一个程序,其中我必须从包含坐标点的文件中读取内容,然后显示绘图。例如,我将其作为第一行2010。我的程序应该做的是使用2D字符数组来绘制图形。点将使用“ X”。

这就是我计算斜率和回归线公式的方式。

enter image description here

  float xMean = xSum / count;
  float yMean = ySum / count;
  float n = count;
  float slope = (xySum - n* xMean * yMean) / (xSqSum - n * xMean * xMean);


如果没有“ X”字符,然后有“ *”字符,我将使用以下方法来打印“-”字符。

for (int i = 0; i < graph.length; i++) {
      int yPred = Math.round(yMean + slope * (i - xMean)); // calculate regression value
        graph[21-1-yPred][i + 1] = graph[21-1-yPred][i + 1 ] == 'X' ? '*' : '-';
    }


我想要的正确输出

Scatterplot using 2D array of characters

但是我得到这个输出:

enter image description here

我要实现的目标是,我的程序将打印“-”作为回归线段,而将“ *”显示为线段和点位于同一位置


  但是,与正确的输出相比,我的程序中的破折号更少。另外,星号不在应有的中间。


这是我正在使用的文本文件。我可以使用我的程序来完成验证。 ** x坐标在[0,40]范围内,y坐标在[1,20]范围内。**
enter image description here

最佳答案

好吧,让我们解决这个问题!首先,在花了15分钟左右的时间在屏幕截图文本文件中添加行之后,这是我绘制的图像(当然是原始图像):

orig img with line markup

现在,您提到要绘制的行或“ X”条目。这也是一个文本文件,您正在从文件中读取它,所以这就是所说的文件(在本示例中,我们将其称为“ coords.txt”)。

20 10


enter image description here

以20和10为读取的坐标,基于我制作的线叠置图像,我认为(20 10)将与x轴= 21,y轴= 10相关(偏离1可能是通过一个错误进行简单索引编制-阅读更多here我基本上只是将图视为图)。

这是从文件中读取该点/数据并准备将其绘制的一种方法:
从文件中读取20 10

Scanner s = new Scanner(new File("coords.txt"));
int x = 0;
int y = 0;
if (s.hasNext())
    x = s.nextInt();
if (s.hasNext())
    y = s.nextInt();
s.close();


该代码很容易,因为它使Scanner对象可以读取文件的内容。然后,声明一个xy整数以便存储我们的坐标值。注意:s.hasNext()通常是有价值的逻辑,可在尝试读取文本文件之前先检查以确保文本文件中有要读取的内容-您也可以改编s.hasNextInt()以便仅向前查找整数令牌。从文件读取。

但是,我注意到您的结果图中有几个X标记。回到图像上,我画出了一个直观的视图,您可能会在未提及的显式“ coords.txt”文件中看到该坐标,假设在此示例中,您将拥有一个包含以下几行的文件:

20 10
0 1
40 20
13 17
10 20


现在这些数字基于我画过线的原始图像,但是我考虑了“一一对应”错误,这就是为什么它们不直接与该图像上的坐标相关联的原因,因为为了校正“一一对应”一个错误。

现在有了几个坐标,如何以更有效的方式读取该输入?这是解决问题的一种方法:

import java.io.File;
import java.io.IOException;
import java.util.Scanner;

public class App {
    public static final int SIZE = 100;
    public static void main(String[] args) throws IOException {
        Scanner s = new Scanner(new File("C:\\Users\\Nick\\Desktop\\coords.txt"));
        int x = 0;
        int y = 0;
        int[] xCoords = new int[SIZE];
        int[] yCoords = new int[SIZE];
        int index = 0;
        while (s.hasNextLine()) {
            if (s.hasNextInt()) {
                x = s.nextInt();
            } else {
                System.out.println("had a next line, but no integers to read");
                break;
            }
            if (s.hasNextInt()) {
                y = s.nextInt();
            } else {
                System.out.println("had a next line, but no integers to read");
                break;
            }
            xCoords[index] = x;
            yCoords[index] = y;
            index++;
        }
        s.close();
    }
}


该代码假定了几件事,包括:


我们认为我们不会读取超过100个坐标进行绘图。 (如果您确实知道此数字,只需将SIZE值编辑为预定值。如果您不知道该值,则在Java列表中查找growing/expanding an arrayjava.util.Listtutorial接口)。
xCoordsyCoords整数数组是匹配/镜像的,它们均应在给定的索引处填充,以表示可绘制的坐标(X标记现场)。
与上一点类似,在while循环中,每行被认为包含两个类似于坐标的整数值以进行读取。
每个循环后,整数index值都会增加,以帮助准备下一个要读取的点,并且还让我们知道在while循环时,已读取了多少点。


运行上面的代码以读取'coords.txt'文件,并在while循环之后但System.out.println()之前添加一些简单的s.close();有助于显示读入的内容。
这是输入阅读的第二版,以及显示发生了什么的输出:

import java.io.File;
import java.io.IOException;
import java.util.Scanner;

public class App {
    public static final int SIZE = 100;
    public static void main(String[] args) throws IOException {
        Scanner s = new Scanner(new File("C:\\Users\\Nick\\Desktop\\coords.txt"));
        int x = 0;
        int y = 0;
        int[] xCoords = new int[SIZE];
        int[] yCoords = new int[SIZE];
        int index = 0;
        while (s.hasNextLine()) {
            if (s.hasNextInt()) {
                x = s.nextInt();
            } else {
                System.out.println("had a next line, but no integers to read");
                break;
            }
            if (s.hasNextInt()) {
                y = s.nextInt();
            } else {
                System.out.println("had a next line, but no integers to read");
                break;
            }
            xCoords[index] = x;
            yCoords[index] = y;
            index++;
        }
        System.out.println("Output from what was read in from file:");
        for (int i = 0; i < index; ++i) {
            System.out.print(xCoords[i] + ", ");
            System.out.println(yCoords[i]);
        }
        s.close();
    }
}


并分别输出:

had a next line, but no integers to read
Output from what was read in from file:
20, 10
0, 1
40, 20
13, 17
10, 20


前两行只是可以删除的注释。很高兴看到我们可以有效地读取数据!

进入问题的主要内容,即完整输出。为了输出示例图像,我们需要有效地打印出二维的字符数组(至少这是我将在此处解释的想法)。

我们知道(基于观察线标记图),为了完整的副本输出,我们需要具有21 x 42的尺寸。这是因为轴标记本身。因此,让我们从声明一个2D数组开始:

char[][] graph = new char[21][42];


那很棒!我们有一个看不见的图!让我们取出那些简陋的空字符,并在其中放置一些旧的空格!毕竟,这是将所有内容都打印出来的根本原因,您不能期望char'\0'值与' '相同。

for (int i = 0; i < graph.length; ++i)
    for (int j = 0; j < graph[0].length; ++j)
        graph[i][j] = ' ';


现在,我们开始用裸轴对其进行标记。首先是y轴:

for (int i = 0; i < graph.length; ++i) {
    graph[i][0] = '/';
}
graph[20][0] = '+';


注意:我们可以用+符号作弊,因为它在最后。 for循环可以使用和if语句,并用+标记最后一个索引,但也请尝试使其更加直观。

然后,对于x轴:

for (int i = 1; i < graph[0].length; ++i) {
    graph[20][i] = '-';
}


因为我们知道末尾在哪里,所以我们仅使用硬编码值20并遍历索引以输入x轴符号/ char -

让我们用下面的代码看一下这个新创建的图:

for (int i = 0; i < graph.length; ++i) {
    for (int j = 0; j < graph[0].length; ++j) {
        System.out.print(graph[i][j]);
    }
    System.out.println();
}


哪个应该产生以下输出:

/                                         
/                                         
/                                         
/                                         
/                                         
/                                         
/                                         
/                                         
/                                         
/                                         
/                                         
/                                         
/                                         
/                                         
/                                         
/                                         
/                                         
/                                         
/                                         
/                                         
+-----------------------------------------


现在,根据您与早期代码中的坐标一起使用的方式,绘制现场X标记。

这可以通过循环镜像整数数组(xCoordsyCoords)并使用这些坐标绘制到2D char[][] graph上来完成。

for (int i = 0; i < index; ++i) {
    graph[21 - 1 - yCoords[i]][xCoords[i] + 1] = 'X';
}


在此处分解信息(上方),[21 - 1 - yCoords[i]]用于通过使用向后描绘的图形顶部值的偏移量将y坐标转换为2D数组中表示的相应点(因此,使用21开始顶部)和另一个由于轴本身而减去一个偏移量(例如分别为'/'和'-'和'+'字符)。对于xCoords,轴本身的偏移量将使用一个简单的加号。

这是输出:

/          X                             X
/                                         
/                                         
/             X                           
/                                         
/                                         
/                                         
/                                         
/                                         
/                                         
/                    X                    
/                                         
/                                         
/                                         
/                                         
/                                         
/                                         
/                                         
/                                         
/X                                        
+-----------------------------------------


看起来很像是这些输出应该是的那些图片的早期阶段!

总而言之,这就是我最终的代码:

import java.io.File;
import java.io.IOException;
import java.util.Scanner;

public class App {
    public static final int SIZE = 100;
    public static void main(String[] args) throws IOException {
        Scanner s = new Scanner(new File("C:\\Users\\Nick\\Desktop\\coords.txt"));
        int x = 0;
        int y = 0;
        int[] xCoords = new int[SIZE];
        int[] yCoords = new int[SIZE];
        int index = 0;
        while (s.hasNextLine()) {
            if (s.hasNextInt()) {
                x = s.nextInt();
            } else {
                System.out.println("had a next line, but no integers to read");
                break;
            }
            if (s.hasNextInt()) {
                y = s.nextInt();
            } else {
                System.out.println("had a next line, but no integers to read");
                break;
            }
            xCoords[index] = x;
            yCoords[index] = y;
            index++;
        }
        System.out.println("Output from what was read in from file:");
        for (int i = 0; i < index; ++i) {
            System.out.print(xCoords[i] + ", ");
            System.out.println(yCoords[i]);
        }
        s.close();
        char[][] graph = new char[21][42];
        for (int i = 0; i < graph.length; ++i)
            for (int j = 0; j < graph[0].length; ++j)
                graph[i][j] = ' ';
        for (int i = 0; i < graph.length; ++i)
            graph[i][0] = '/';
        graph[20][0] = '+';
        for (int i = 1; i < graph[0].length; ++i)
            graph[20][i] = '-';
        for (int i = 0; i < index; ++i)
            graph[21 - 1 - yCoords[i]][xCoords[i] + 1] = 'X';
        for (int i = 0; i < graph.length; ++i) {
            for (int j = 0; j < graph[0].length; ++j)
                System.out.print(graph[i][j]);
            System.out.println();
        }
    }
}


如果您想提供更多细节,例如多个“-”代表回归,“ *”代表点,我鼓励使用此信息来学习并适应于阅读那些坐标以获得该附加信息并将其应用于本示例。但是,没有提供任何信息,因此,我不会冒险使用所谓的文本文件和协调的主题,而是将其编辑为问题,或者自己尝试尝试并学习一些东西。 :)干杯

关于java - 2D字符格式数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40348878/

相关文章:

带静态变量和不带静态变量的 Java 同步

arrays - 将数组中的N个元素从后向前移动

c++ - 如何将多维数组传递给C++中的头文件

java - JFileChooser 使用扩展名保存

java - 对于大值,Math.pow 和 Math.sqrt 的工作方式不同吗?

java - 为什么静态 block 中不允许静态字段声明?

arrays - swift 语法 : index of array element accessed in setter?

java - Java中的字符串数组排序

c - 在 C 中将 .csv 解析为 3d 数组

python - 将列表作为 N 维 numpy 数组的切片传递