Windows控製台下繪製簡單圖形
最近接觸到一個很有意思的問題,如何在Windows控製台下畫圖,翻遍了C的頭文件也沒找到畫圖的函數,好吧,那就用Windows提供的API函數吧,看來想移植是沒戲了。先畫一個簡單的圖,類似心電圖那種吧,假設得到的數據是縱坐標的值,橫坐標默認從0開始,每隔512uS(微秒的那個符號不會打)得到一個縱坐標值,要求將所有縱坐標值連起來,就以這個簡單的程序為例吧。既然有了需求,實現起來就簡單了,首先我們應該有一個控製台窗口的上下文(device context)句柄,然後使用MoveToEx和LineTo函數連線就行了。代碼如下:
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include "data.h" //聲明了名為point的二維數組,以及記錄數組元素個數的NUMBER常量
//
//下列X-Y坐標平麵的值取決於控製台的尺寸,需要根據實際情況進行調整
//
//起始X坐標
#define X_START 10
//結束X坐標
#define X_END 650
//每個值的X坐標增量,相當於512uS
#define X_INC 10
//Y坐標
#define Y 250
int main()
{
HWND hwnd;
HDC hdc;
int i;
//獲取console的設備上下文句柄
hwnd = GetConsoleWindow();
hdc = GetDC(hwnd);
//調整一下console背景顏色,否則看不清線條
system("color 3D");
//起始位置,Windows中窗口的坐標係相當於直角坐標係第一象限翻轉到第四象限
MoveToEx(hdc,X_START,Y,NULL);
//畫基準坐標線
LineTo(hdc,X_END,Y);
//開始繪圖
MoveToEx(hdc,X_START,Y,NULL);
for (i = 0; i < NUMBER; i++)
{
LineTo(hdc,point[i].x,point[i].y);
}
_getch();
return 0;
}
但是這個程序存在一個問題,就是如果控製台被其它窗口遮住後,已經繪製的線條不會重繪,也就意味著那部分線條看不見了,隻能重新運行程序,這個問題怎麼解決呢?我也不知道,不過可以將整個函數包含一個while循環裏,如果自己是頂層窗口就重新繪製,隻是這樣似乎代價太大了,嗬嗬。
來看一下這個程序繪製的圖形吧。
既然能繪製出線條自然就可以會繪製出柱形圖之類的圖形,稍微修改一下就可以了,代碼就不貼了,效果如下圖。
上麵這些都比較好畫,那麼如果畫圓呢?
我想到兩種方法,第一種方法是計算,首先分別計算出最大和最小的X、Y值(xmin,xmax,ymin,ymax),然後根據X^2+Y^2=R^2,在for (x = xmin; x <= xmax; x++)內部計算Y值,最後畫點就是了;這個應該是比較簡單的。
第二種方法是掃描,左上角(xmin,ymin)、右上角(xmax,ymin)、左下角(xmin,ymax)和右下角(xmax,ymax)這四個點確定一個正方形,對正方形內部對每個點進行運算,也是根據X^2+Y^2=R2,隻是現在根據X和Y算出R0,然後跟R對比而已,而且比第一種方法多了一個判斷——是否到達行末,若到達行末則跳到下一行,若已經到了最後一行的最後一列,那就跳出循環。不過這個方法顯然比較奢侈,如果半徑增大n倍的話,計算量增大了n^2倍。就貼這種方法的代碼吧。
void circle(POINT *center,int radius)
{
HWND hwnd;
HDC hdc;
int xmin = center->x - radius;
int xmax = center->x + radius;
int ymin = center->y - radius;
int ymax = center->y + radius;
POINT point;
hwnd = GetConsoleWindow();
hdc = GetDC(hwnd);
point.x = xmin;
point.y = ymin;
MoveToEx(hdc,center->x,center->y - radius,NULL);
while (TRUE)
{
if (fabs(sqrt(pow2(point.x - center->x) + pow2(point.y - center->y)) - radius) <= 1)
{
DrawPoint(hdc,&point);
}
//是否到達行末
if (point.x == xmax)
{
if (point.y == ymax)
{
break;
}
else
{
point.x = xmin;
point.y++;
continue;
}
}
point.x++;
}
}
繪製的圓如下圖:
最後更新:2017-04-03 12:56:27
上一篇:
UVA之10878 - Decode the tape
下一篇:
UVA之11078 - Open Credit System
Android開發12——Andorid中操作數據庫的insert的兩種方法以及nullColumnHack
《深入理解Elasticsearch(原書第2版)》一2.5.1 查詢方式分類
【最近麵試遇到的一些問題】運行時異常與一般異常有何異同
Kafka某topic無法消費處理
C連接MySQL數據庫開發之Linux環境完整示例演示(增、刪、改、查)
時間子係統16_soft lockup機製
HTAP數據庫 PostgreSQL 場景與性能測試之 20 - (OLAP) 用戶畫像圈人場景 - 多個字段任意組合條件篩選與透視
普通企業站的seo優化策略
中國企業移動管理市場勐增:創新和安全仍是核心
Sql查詢原理與Select執行順序(詳細)