簡體   English   中英

使用C ++繪制線條而沒有圖形

[英]Draw Line using c++ without graphics

我希望編寫不使用圖形庫就使用c ++ lang繪制線的程序,我嘗試了很多,但沒有達到我想要的線方程為:

y=mx+b

我要畫這條線(例如)

y=3x+2

這是我的代碼

#include <iostream>
#include <math.h>

using namespace std;

int pth (int x)  {
    return 2*x-3;
}

int main()  {
    int i,j,y;
    for (int x=-10;x <= 10;x++)  {
        for ( i=-10;i <= x;i++)  {
            if (i==x) {
                y=pth(x);
                cout<<"x=";
                cout<<x;
                cout<<"y=";
                cout<<y;

                for(j=-10;j<=y;j++) {
                    if(j==y)
                        cout << "*";
                    else
                        cout << " ";
                }
            }
        }
        cout << "\n";
    }
    cin.get();
    return 0;
 }

輸出是這樣的

x=0y=3   *
 x=1y=5     *
  x=2y=7       *
   x=3y=9         *
    x=4y=11           *
     x=5y=13             *
      x=6y=15               *
       x=7y=17                 *
        x=8y=19                   *
         x=9y=21                     *
          x=10y=23                       *

但是對於給定的方程(y = 2x-3),結果必須是

                                      *
                                  *
                              *
                           *
                        *
                    *
                 *

代碼是我認為正確的,但是問題是如何確定線條的方向,以便正確繪制

因為我喜歡挑戰,所以我做了一個很小的Canvas類,其用法如下:

int main() {
    using Canvas = BasicCanvas<160, 80>;
    Canvas canvas;
    canvas.origin = {canvas.cols()/3, canvas.rows()/3};

    canvas.axes();

    canvas.plot([](double x) { return  x; });
    canvas.plot([](double  ) { return -8; });
    canvas.plot([](double x) { return 3*log(x); });
    canvas.plot([](double x) { return 4*sin(x/2); });
    canvas.plot([](double x) { return 24*cos(x/12); });

    std::cout << canvas;
}

哪些印刷品 在此處輸入圖片說明

或注釋掉原點分配: 在此處輸入圖片說明

履行

實現基本上遍歷x軸上的位置,並根據該點函數的角度(一階導數)繪制近似的線條圖字符:

template <size_t Columns = 100, size_t Rows = 50>
struct BasicCanvas {
    using Line   = std::array<char, Columns>;
    using Screen = std::array<Line, Rows>;
    struct Coord { size_t x, y; };

    static constexpr size_t rows() { return Rows; }
    static constexpr size_t cols() { return Columns; }

    Screen screen;
    Coord origin;

    BasicCanvas(Coord origin = {Columns/2, Rows/2}) : origin(origin) {
        Line empty;
        std::fill(empty.begin(), empty.end(), '.');
        std::fill(screen.begin(), screen.end(), empty);
    }

    friend std::ostream& operator<<(std::ostream& os, BasicCanvas const& c) {
        for (auto& line : c.screen) {
            os.write(line.data(), line.size()) << "\n";
        }
        return os;
    }

    Line&       operator[](size_t y)          { return screen.at(screen.size()-(y+1)); }
    Line const& operator[](size_t y) const    { return screen.at(screen.size()-(y+1)); }
    char&       operator[](Coord coord)       { return operator[](coord.y).at(coord.x); }
    char const& operator[](Coord coord) const { return operator[](coord.y).at(coord.x); }

    void axes() {
        for (auto& line : screen)
            line.at(origin.x) = '|';

        auto& y_axis = operator[](origin.y);

        for (auto& cell : y_axis)
            cell = '-';

        y_axis.at(origin.x) = '+';
    }

    template <typename F>
    void plot(F f, double scaleX = 1.0, double scaleY = 1.0) {
        for (size_t x_tick = 0; x_tick < Columns; ++x_tick) {
            auto x = (x_tick * scaleX) - origin.x;
            auto y = f(x);
            auto y_ = derivative(f, x, scaleX/2);

            size_t y_tick = (y / scaleY) + origin.y;
            if (y_tick < Rows)
                operator[]({x_tick, y_tick}) = glyph(y_);
        }
    }

  private:
    template <typename F>
    auto derivative(F const& f, double x, double dx = 0.01) {
        return (f(x+dx)-f(x-dx))/(2*dx);
    }

    char glyph(double tangent) {
        auto angle = atan(tangent);

        while (angle < 0) 
            angle += 2*M_PI;

        int angle_index = 2.0 * angle / atan(1);

        return R"(--/||\--)"[angle_index % 8];
    }

};

完整清單

生活在Coliru

(簡化功能選擇):

#include <iostream>
#include <array>
#include <cmath>

template <size_t Columns = 100, size_t Rows = 50>
struct BasicCanvas {
    using Line   = std::array<char, Columns>;
    using Screen = std::array<Line, Rows>;
    struct Coord { size_t x, y; };

    static constexpr size_t rows() { return Rows; }
    static constexpr size_t cols() { return Columns; }

    Screen screen;
    Coord origin;

    BasicCanvas(Coord origin = {Columns/2, Rows/2}) : origin(origin) {
        Line empty;
        std::fill(empty.begin(), empty.end(), ' ');
        std::fill(screen.begin(), screen.end(), empty);
    }

    friend std::ostream& operator<<(std::ostream& os, BasicCanvas const& c) {
        for (auto& line : c.screen) {
            os.write(line.data(), line.size()) << "\n";
        }
        return os;
    }

    Line&       operator[](size_t y)          { return screen.at(screen.size()-(y+1)); }
    Line const& operator[](size_t y) const    { return screen.at(screen.size()-(y+1)); }
    char&       operator[](Coord coord)       { return operator[](coord.y).at(coord.x); }
    char const& operator[](Coord coord) const { return operator[](coord.y).at(coord.x); }

    void axes() {
        for (auto& line : screen)
            line.at(origin.x) = '|';

        auto& y_axis = operator[](origin.y);

        for (auto& cell : y_axis)
            cell = '-';

        y_axis.at(origin.x) = '+';
    }

    template <typename F>
    void plot(F f, double scaleX = 1.0, double scaleY = 1.0) {
        for (size_t x_tick = 0; x_tick < Columns; ++x_tick) {
            auto x = (x_tick * scaleX) - origin.x;
            auto y = f(x);
            auto y_ = derivative(f, x, scaleX/2);

            size_t y_tick = (y / scaleY) + origin.y;
            if (y_tick < Rows)
                operator[]({x_tick, y_tick}) = glyph(y_);
        }
    }

  private:
    template <typename F>
    auto derivative(F const& f, double x, double dx = 0.01) {
        return (f(x+dx)-f(x-dx))/(2*dx);
    }

    char glyph(double tangent) {
        auto angle = atan(tangent);

        while (angle < 0) 
            angle += 2*M_PI;

        int angle_index = 2.0 * angle / atan(1);

        return R"(--/||\--)"[angle_index % 8];
    }

};

int main() {
    using Canvas = BasicCanvas<60, 30>;
    Canvas canvas;
    //canvas.origin = {canvas.cols()/3, canvas.rows()/3};

    canvas.axes();

    canvas.plot([](double x) { return  x; });
    //canvas.plot([](double  ) { return -8; });
    canvas.plot([](double x) { return 3*log(x); });
    canvas.plot([](double x) { return 4*sin(x/2); });
    //canvas.plot([](double x) { return 24*cos(x/12); });

    std::cout << canvas;
}

打印

                              |             /               
                              |            /                
                              |           /                 
                              |          /                  
                              |         /                  -
                              |        /           -------- 
                              |       /      ------         
                              |      /   ----               
                              |     / ---                   
                              |    /--                      
                              |   --                        
       ---          --\       | /--          --\         /--
      /   \        /          | /  \        /               
                  /    \      |/                \       /   
-----/-----\------------------/|----\------/----------------
                 /      \    /|                  \     /    
    /       \               //|      \    /                 
\               /        \ /  |          /        \   /     
 --/         \--          --/ |       \--          ---      
                         /    |                             
                        /     |                             
                       /      |                             
                      /       |                             
                     /        |                             
                    /         |                             
                   /          |                             
                  /           |                             
                 /            |                             
                /             |                             
               /              |                             

我看着你的“ C”問題。

如果要使用終端並在屏幕上放置字符,請為您的系統找到一個ansi終端仿真器,然后嘗試使用Ansi_t:

class Ansi_t   // use ansi features of gnome-terminal
{
   // note: Ubuntu 15.10 gnome-terminal ansi term cursor locations 
   // are 1-based with origin 1,1 at top left corner

   enum ANSI : char { ESC = 27 };

public:

   static inline std::string clrscr(void)
      {
         std::stringstream ss;
         ss << static_cast<char>(ESC) << "[H"   // home
            << static_cast<char>(ESC) << "[2J"; // clrbos
         return(ss.str());
      }

   //              r/c are 0 based------v------v------0 based
   static inline std::string gotoRC(int r, int c)
      {
         std::stringstream ss;
         // Note: row/col of GameOfLife_t is 0 based (as in C++)
         ss << static_cast<char>(ESC) << "[" 
            << (r+1) << ';' << (c+1) << 'H';
         // xy of ansi terminal is 1 based -------^^--------------^^
         return(ss.str());
      }


   // tbr - add more ansi functions as needed

}; // Ansi_t

典型用法是“

std::cout << Ansi_t::clrscr() << std::flush; // clears the screen

std::cout << Ansi_t::gotoRC(5, 25) << '*' << std::flush;
// position the cursor, and output a single 'dot':

現在用它畫一條線,等等。

注-在ubuntu上,終端仿真通常具有熱鍵以減小字體大小-對於某些終端,此鍵為“ Ctrl減號”。 重復應用可將字體大小減小為不可讀,因此每個字符越來越像點。

我已經成功地將Ansi_t用於GameOfLife ...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM