用C语言用数组绘制轨迹图



第一次发问题,希望能有个好口碑!标题很好地描述了我的任务的性质:

在用户输入弹丸的初始速度和发射角度后,我的程序必须生成点并绘制弹丸的轨迹图。为此,我必须使用两个2D数组-一个用于生成的点,另一个作为画布(基本上是一个40x80的空数组,充满空格)。

我得到了我必须使用的函数的原型,所以这里是我想出的相关代码(它相当长,但只是为了完整起见)。实际问题可以在第三和第四个函数中找到):

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "Assignment6B.h"
int Sx = 0;
int Sy = 0;
void calcTraj(double initSpeed, double launchAngle, double trajData[][2]) {
    do {
        double Ux = initSpeed*cos(launchAngle*3.14/180.0);
        double Uy = initSpeed*sin(launchAngle*3.14/180.0);
        Sy = (Sx/Ux)*(Uy - ((9.81*Sx)/(2*Ux)));
        if (Sy >= ZERO) {
            trajData[Sx][0] = Sx;
            trajData[Sx][1] = Sy;
        }
        Sx++;
    } while (Sy >= ZERO);
}
int Row, Column;
void clearDisplayData(char displayData[HEIGHT][WIDTH]) {
    for (Row = 0; Row < HEIGHT; Row++) {
        for (Column = 0; Column < WIDTH; Column++) {
            displayData[Row][Column] = ' ';
        }
    }
}
void updateDisplayData(char displayData[HEIGHT][WIDTH], double trajData[][2]) {

这是我被困住的部分,相当无可救药的无能为力。

我理解这个函数背后的想法:它接收"空画布"数组以及包含数据的数组(图中的点)。所以,现在需要做的是,displayData中所有与trajData[Sx][Sy]坐标相对应的元素,都需要替换为X。例如,假设trajData中的[1][4]有一个元素,那么displayData[1][4] = X

我只是不知道如何编码。如果有人能提供样品,那就太好了!

}
void printData(char displayData[HEIGHT][WIDTH]) {
    puts("");
    for (Column = 0; Column < WIDTH + 2; Column++) {
        printf("_");
    }
    puts("");
    for (Row = 0; Row < HEIGHT; Row++) {
        printf("|");
        for (Column = 0; Column < WIDTH; Column++) {
            printf("%c", displayData[Row][Column]);
        }
        printf("|");
        puts("");
    }
    for (Column = 0; Column < WIDTH + 2; Column++) {
        printf("_");
    }

这个函数也不完全正确。我必须绘制一个图表,这意味着[0,0]点必须在左下角。但是数组的元素[0][0]在左上角。

我认为行显示的顺序应该与for -循环相反,例如for (Row = HEIGHT; Row > 0; Row--) -对吗?请告知…}

如果任何人发现任何其他问题或有任何建议,请分享!

Ashton,如果我没弄错的话,你所遇到的概念上的困难似乎只是部分与C有关(语法方面)。另一部分是简单地理解您被要求对这两个单独的数组做什么。我要试着驱散雾,希望不会让情况变得更糟。这基本上是一个数据伸缩问题。

两个数组trajDatadisplayData只是相同数据的两种不同表示。trajData保留完整的值,displayData将简单地保留相同的值,以适应[HEIGHT][WIDTH]

您的trajData保存从任何给定时间点的运动学方程返回的值。您的displayData只是一个数组,如果您要将trajData的内容打印到某些[HEIGHT][WIDTH]显示器,则该数组将保存打印到屏幕上的内容。这是你工作的地方。

为了将trajData拟合到displayData[HEIGHT][WIDTH]约束中,需要计算两个比例因子。第一个将缩放HEIGHTMAX - HEIGHTMIN之间的差异,以便所有 y值数据点适合HEIGHT。您的第二个比例因子将确保您的所有时间值(您计算点的迭代次数,例如while (Sy >= ZERO);)将适合WIDTH。(这也意味着您需要返回(或更新指针)trajData中的点数。

由于您目前使用的是type void,请将返回类型更改为有用的东西,例如unsigned intsize_t或简单地int(即使没有负时间)并返回点数)。始终选择您的返回类型,以便它返回一些有价值的信息给您。void返回值(不要与void *混淆)只应该在没有返回值的情况下使用,比如只有print数据或free内存等的函数。

知道点的数量和'Y'值的范围,你可以计算因子来缩放你的trajData值。这些比例因子将限制你用来填充displayData的值,这样它就完全合适了,这样你就不会犯写超出数组末尾的错误。

displayData数组的目标(在清除之后)只是打开保存trajData值的单元格,这些单元格缩放以适合[HEIGHT][WIDTH]。要使用这个刻度,您需要知道SxSy的范围,因此您可以添加一些变量,例如:

int Sx = 0;
int Sy = 0;
int y_min = INT_MAX;
int y_max = INT_MIN;
然后你需要在calcTraj中选择Sy的最大/最小值,类似于:
int calcTraj(double initSpeed, double launchAngle, double trajData[][2]) {
    ... 
    if (Sy >= ZERO) {
        if (Sy > y_max) y_max = Sy;
        if (Sy < y_min) y_min = Sy;
        ...
    } while (Sy >= ZERO);
    return Sx;
}
要计算比例因子,您将执行类似的操作:
int scale_x = WIDTH/Sx;
int scale_y = HEIGHT/(y_max - y_min);

对于填充displayData,您只需打开具有您想要显示轨迹路径的任何字符的单元格,例如'X''#''*'。像下面这样的东西应该很接近,但是注意,因为您使用的是整数除法,您可能必须调整HEIGHT小于(y_max - y_min)时使用的缩放公式,或者更改为不同的中间数据类型,如floatdouble,以准确地缩放值。

同样,如果SxWIDTH大得多,你可能会为每个'X'写几个'Y'值,这样轨迹的斜率就会变得垂直——就像笔直射击子弹的情节一样。(如果你只能给出一个值,你可以取平均值)。下面的代码应该可以工作:

/* set each relative cell to 'X' */
for (i = 0; i < Sx; i++) {
    displayData[scale_x * trajData[i][0]][scale_y * trajData[i][1]] = 'X';
}

注意:这些只是关于这个问题的想法,我还没有编码一个完整的例子来测试。所以如果你遇到问题,告诉我。

终于!我已经完成了我的程序,它运行得很好。

完整的代码如下。我添加它只是为了让可能有同样问题的人可以看到所需的结果。

但是,请注意,这个程序不是为了准确性而构建的,而是为了测试C初学者的技能,知识和能力…

头文件:

#ifndef ASSIGNMENT6B_H_
#define ASSIGNMENT6B_H_
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// Constants (of array to serve an "canvas" for graph and calculations)
#define WIDTH   80
#define HEIGHT  40
#define g       9.81
#define ZERO    0.0
// Function Prototypes
void calcTraj(double initSpeed, double launchAngle, double trajData[WIDTH][2]);
void clearDisplayData(char displayData[HEIGHT][WIDTH]);
void updateDisplayData(char displayData[HEIGHT][WIDTH], double trajData[WIDTH][2]);
void printData(char displayData[HEIGHT][WIDTH]);
#endif /* ASSIGNMENT6B_H_ */

功能:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "Assignment6B.h"
void calcTraj(double initSpeed, double launchAngle, double trajData[WIDTH][2]) {
    int Sx = 0;
    int Sy = 0;
    //assign all values in array to 0
    int i, j;
    for (i = 0; i < WIDTH; i++) {
        for (j = 0; j < 2; j++) {
            trajData[i][j] = 0;
        }
    }
    double Ux = initSpeed*cos(launchAngle*M_PI/180.0);      //Horizontal component of velocity
    double Uy = initSpeed*sin(launchAngle*M_PI/180.0);      //Vertical component of velocity
    do {
        Sy = (Sx/Ux)*(Uy - ((g*Sx)/(2*Ux)));                //Calculates y-value of position for every x used
        if (Sy >= ZERO) {
            //Stores data in a table form
            trajData[Sx][0] = Sx;
            trajData[Sx][1] = Sy;
        }
        Sx++;
    } while (Sy >= 0 && Sx <= 80 && Sx >= 0);               //Executed only for as long as projectile is air-borne
}                                                           //and within graphing range
//Assigns spaces to all elements of the "canvas",
//i.e. creates an empty array with the desired dimensions
void clearDisplayData(char displayData[HEIGHT][WIDTH]) {
    int Row, Column;
    for (Row = 0; Row < HEIGHT; Row++) {
        for (Column = 0; Column < WIDTH; Column++) {
            displayData[Row][Column] = ' ';
        }
    }
}
//Merges the two arrays,
//i.e. adds all data (coordinates) for trajData to displayData to create the graph
void updateDisplayData(char displayData[HEIGHT][WIDTH], double trajData[WIDTH][2]) {
    int i;
    for (i = 0; i < WIDTH; i++) {
        if (HEIGHT - (int)floor(trajData[i][1]) >= 0) {
            displayData[HEIGHT - (int)floor(trajData[i][1])][(int)floor(trajData[i][0])] = '*';
        }
    }
}
//Prints graph and border
void printData(char displayData[HEIGHT][WIDTH]) {
    int Row, Column;
    puts("");
    for (Column = 0; Column < WIDTH + 2; Column++) {
        printf("_");
    }
    puts("");
    for (Row = 0; Row < HEIGHT; Row++) {
        printf("|");
        for (Column = 0; Column < WIDTH; Column++) {
            printf("%c", displayData[Row][Column]);
        }
        printf("|");
        puts("");
    }
    for (Column = 0; Column < WIDTH + 2; Column++) {
        printf("_");
    }
}
主:

#include "Assignment6B.h"
double initSpeed, launchAngle;
char displayData[HEIGHT][WIDTH];
double trajData[WIDTH][2];
int a;
int main() {
    do {
        //Clear display (on Windows)
        system("cls");
        setbuf(stdout, 0);
        clearDisplayData(displayData);
        printData(displayData);
        //Values to be entered by user and used in functions
        printf("nnEnter the Initial Speed of the particle: ");
        scanf("%lf", &initSpeed);
        printf("nEnter the Launch Angle of the particle: ");
        scanf("%lf", &launchAngle);
        calcTraj(initSpeed, launchAngle, trajData);
        updateDisplayData(displayData, trajData);
        printData(displayData);
        //Allows user to repeat or exit
        printf("nnType a '0' to exit; any other number to continue: ");
        scanf("%d", &a);
    } while (a != 0);
    return 0;
}

就是这样!请随意评论,评分,投票或其他任何方式-谢谢你,Stack Overflow的人!

最新更新