广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >利用C语言绘制一个正方体
  • 137
分享到

利用C语言绘制一个正方体

C语言绘制正方体C语言 正方体 2023-01-06 09:01:24 137人浏览 独家记忆
摘要

目录程序截图操作方法个人思路代码实现程序截图 操作方法 鼠标拖动。左键拖动及滚轮能看到不同角度下正方体的形状,右键拖动能将最近的正方体顶点挪到这个投影面的相应位置。 按键控制。wa

程序截图

操作方法

鼠标拖动。左键拖动及滚轮能看到不同角度下正方体的形状,右键拖动能将最近的正方体顶点挪到这个投影面的相应位置。

按键控制。wasd 控制投影面旋转,ws 关于 x 轴旋转,ad 关于 y 轴旋转。

个人思路

首先投影面的确立需要两个量,一个 x 轴方向的单位向量,一个 y 轴方向的单位向量,求原点与三维空间中的点的连线到这两个单位向量的投影就能得到三维空间中的点在二维投影面中的坐标。记 x 轴方向单位向量为 X,y 轴方向单位向量为 Y,X 与 Y 互相垂直,模都为 1。

正方体的八个顶点位置随意,X,Y 两个单位向量只需是互相垂直的非零向量即可。

鼠标横向拖动时,X 关于 Y 旋转,这是怎么做到的呢。要做到这一点,就需要一个新的向量,也就是投影面的法向量,投影面的法向量可以根据两向量叉乘得到。叉乘的推法用的是线性代数的方法,但是不好理解,我用我的方法推出来,希望能方便理解。

设投影面法向量为 Z(x2, y2, z2),X(x0, y0, z0) 和 Y(x1, y1, z1) 与 Z 的点乘为 0,这就能列出两个式子:

① x0x2+y0y2+z0z2 = 0

② x1x2+y1y2+z1z2 = 0

将①式转化为以 x2 和 y2 表示的 z2 得

③ z2 = - (x0x2 + y0y2) / z0

将②式和③式结合转化为以 x2 表示的 y2 得

④ y2 = (x0z1 - x1z0) / (y1z0 - y0z1) * x2

④式代回③式得

⑤ z2 = (x1y0 - x0y1) / (y1z0 - y0z1) * x2 (推这一步时负号别忘了看)

也就是 Z = [x2, (x0z1 - x1z0) / (y1z0 - y0z1) * x2, (x1y0 - x0y1) / (y1z0 - y0z1) * x2]

仔细观察 Z 只有一个变量 x2,不妨先放大(y1z0 - y0z1)倍,得到

Z = [(y1z0 - y0z1) * x2, (x0z1 - x1z0) * x2, (x1y0 - x0y1) * x2]

把 x2 提取出来,Z 就是 Z = x2 * [(y1z0 - y0z1), (x0z1 - x1z0), (x1y0 - x0y1)]

令 x2 = 1,Z[(y1z0 - y0z1), (x0z1 - x1z0), (x1y0 - x0y1)] 就是投影面的法向量。到这一步还没有结束,因为垂直于一个面的法向量有两个,一个符合右手坐标系,一个符合左手坐标系,将 X(1, 0, 0),Y(0, 1, 0) 代入得 Z(0, 0, -1),所以这个 Z 是符合左手坐标系的投影面法向量,要转换成右手坐标系只需乘个 -1 就行,也就是 Z 最终为 (y0z1 - y1z0, x1z0 - x0z1, x0y1 - x1y0)。

由于 X,Y 都是单位向量,这个 Z 还是投影面的单位法向量。

Z 求出来了,X 关于 Y 旋转可以看做 X 在 XOZ 平面上旋转,问题转化成了求平面中某个向量转过θ度后的向量,如下图,将 X 看做下图中的红色向量,Z 看做下图中的绿色向量,虚线为向量旋转后θ度后的向量,可以发现 cos(θ)X - sin(θ)Z,就能求出 X 顺时针转动θ度后的向量,而 cos(θ)Z + sin(θ)X 就能求出 Z 顺时针转动θ度后的向量。

其它的旋转方式皆可以此类推。

代码实现

TCW_GUI.h:

#pragma once
#include<graphics.h>
#include<string>
#include<list>
#include<functional>
#define TCW_GUI_BUTTON_MYSELF 0
 
 
namespace TCW_GUI
{
    enum class State
    {
        general = 0,
        touch = 1,
        press = 2,
        release = 3,
        forbidden = 4
    };
 
    class Vec2
    {
    public:
        double x, y;
        Vec2() :x(0), y(0) {}
        Vec2(double xx, double yy) :x(xx), y(yy) {};
        Vec2 operator+(Vec2 num)
        {
            return Vec2(x + num.x, y + num.y);
        }
        Vec2 operator-(Vec2 num)
        {
            return Vec2(x - num.x, y - num.y);
        }
        Vec2 operator/(double num)
        {
            return Vec2(x / num, y / num);
        }
        Vec2 operator*(double num)
        {
            return Vec2(x * num, y * num);
        }
    };
 
    class Rect
    {
    public:
        Rect() :size(), position() {}
        Rect(Vec2 position, Vec2 size) :size(size), position(position) {}
        Vec2 size;
        Vec2 position;
        bool isInRect(Vec2 point)
        {
            Vec2 left_top = position - size / 2.0;
            Vec2 right_buttom = position + size / 2.0;
            if (point.x >= left_top.x && point.y >= left_top.y &&
                point.x <= right_buttom.x && point.y <= right_buttom.y)return true;
            return false;
        }
    };
 
    class Button
    {
    private:
        double textsize = 20;
        double textareasize = 0.9;
        Vec2 defaultsize = Vec2(textwidth(L"...") / textareasize, textheight(L"...") / textareasize);
        Vec2 defaulttext = Vec2(textwidth(L"..."), textheight(L"..."));
        State nowstate = State::general;
        void DrawButton_General();
        void DrawButton_Touch();
        void DrawButton_Press();
        void DrawButton_Forbidden();
        bool isPress = false;
    public:
        Button() :boundingbox(), buttontext() {}
        Button(Rect boundingbox, std::wstring buttontext, std::function<int(void*)> releaseFunc, void* releaseParam) :
            boundingbox(boundingbox), buttontext(buttontext), releaseFunc(releaseFunc), releaseParam(releaseParam) {}
        std::wstring buttontext;
        Rect boundingbox;
        std::function<int(void*)> releaseFunc = nullptr;
        void* releaseParam = nullptr;
        void DrawButton();
        void receiver(ExMessage* msg);
        void ForbidButton() { this->nowstate = State::forbidden; }    // 禁用按钮
        void RefreshButton() { this->nowstate = State::general; }    // 恢复按钮
        void SetTextSize(double size)
        {
            textsize = size;
            defaultsize = Vec2(textsize * 1.5 / textareasize, textsize / textareasize);
            defaulttext = Vec2(textsize * 1.5, textsize);
        }
        void SetTextAreaSize(double size)
        {
            textareasize = size;
            defaultsize = Vec2(textsize * 1.5 / textareasize, textsize / textareasize);
            defaulttext = Vec2(textsize * 1.5, textsize);
        }
    };
 
    class ButtonManager
    {
        std::list<Button> buttonlist;
    public:
        Button* AddButton(Button button);
        void ReceiveMessage(ExMessage* msg);
        void DrawButton();
    };
 
    void Rectangle_TCW(Vec2 left_top, Vec2 right_buttom)
    {
        rectangle(left_top.x, left_top.y, right_buttom.x, right_buttom.y);
    }
 
    void Fillrectangle_TCW(Vec2 left_top, Vec2 right_buttom)
    {
        fillrectangle(left_top.x, left_top.y, right_buttom.x, right_buttom.y);
    }
 
    void Outtextxy_TCW(Vec2 position, const WCHAR* str)
    {
        outtextxy(position.x, position.y, str);
    }
 
    void Button::DrawButton_General()
    {
        LOGFONT log;
        COLORREF textcol;
        COLORREF linecol;
        COLORREF fillcol;
        int bkmode;
        gettextstyle(&log);
        bkmode = getbkmode();
        textcol = gettextcolor();
        linecol = getlinecolor();
        fillcol = getfillcolor();
 
        settextstyle(textsize, 0, TEXT("微软雅黑"));
        settextcolor(BLACK);
        setbkmode(TRANSPARENT);
        setlinecolor(BLACK);
        setfillcolor(WHITE);
        Vec2 size_button = Vec2(this->boundingbox.size * textareasize);
        Vec2 size_text = Vec2(textwidth(this->buttontext.c_str()), textsize);
 
        if (boundingbox.size.x > defaultsize.x && boundingbox.size.y > defaultsize.y)
        {
            Rectangle_TCW(this->boundingbox.position - this->boundingbox.size / 2.0,
                this->boundingbox.position + this->boundingbox.size / 2.0);
            Fillrectangle_TCW(this->boundingbox.position - this->boundingbox.size / 2.0,
                this->boundingbox.position + this->boundingbox.size / 2.0);
            if (size_button.x >= size_text.x && size_button.y >= size_text.y)
            {
                Outtextxy_TCW(this->boundingbox.position - size_text / 2.0, buttontext.c_str());
            }
            else
            {
                int Wordnum = size_button.x / textwidth(buttontext.c_str()) * buttontext.size() - 2;
                std::wstring realstr = buttontext.substr(0, wordnum);
                realstr += L"...";
                size_text = Vec2(textwidth(realstr.c_str()), textsize);
                Outtextxy_TCW(this->boundingbox.position - size_text / 2.0, realstr.c_str());
            }
        }
        else
        {
            Rectangle_TCW(this->boundingbox.position - this->defaultsize / 2.0,
                this->boundingbox.position + this->defaultsize / 2.0);
            Fillrectangle_TCW(this->boundingbox.position - this->defaultsize / 2.0,
                this->boundingbox.position + this->defaultsize / 2.0);
            if (defaulttext.x >= size_text.x && defaulttext.y >= size_text.y)
                Outtextxy_TCW(this->boundingbox.position - size_text / 2.0, buttontext.c_str());
            else Outtextxy_TCW(this->boundingbox.position - defaulttext / 2.0, TEXT("..."));
        }
 
        settextstyle(&log);
        settextcolor(textcol);
        setbkmode(bkmode);
        setlinecolor(linecol);
        setfillcolor(fillcol);
    }
 
    void Button::DrawButton_Touch()
    {
        LOGFONT log;
        COLORREF textcol;
        COLORREF linecol;
        COLORREF fillcol;
        int bkmode;
        gettextstyle(&log);
        bkmode = getbkmode();
        textcol = gettextcolor();
        linecol = getlinecolor();
        fillcol = getfillcolor();
 
        settextstyle(textsize, 0, TEXT("微软雅黑"));
        settextcolor(BLACK);
        setbkmode(TRANSPARENT);
        setlinecolor(BLACK);
        setfillcolor(RGB(240, 240, 240));
        Vec2 size_button = Vec2(this->boundingbox.size * textareasize);
        Vec2 size_text = Vec2(textwidth(this->buttontext.c_str()), textsize);
 
        if (boundingbox.size.x > defaultsize.x && boundingbox.size.y > defaultsize.y)
        {
            Rectangle_TCW(this->boundingbox.position - this->boundingbox.size / 2.0,
                this->boundingbox.position + this->boundingbox.size / 2.0);
            Fillrectangle_TCW(this->boundingbox.position - this->boundingbox.size / 2.0,
                this->boundingbox.position + this->boundingbox.size / 2.0);
            if (size_button.x >= size_text.x && size_button.y >= size_text.y)
            {
                Outtextxy_TCW(this->boundingbox.position - size_text / 2.0, buttontext.c_str());
            }
            else
            {
                int wordnum = size_button.x / textwidth(buttontext.c_str()) * buttontext.size() - 2;
                std::wstring realstr = buttontext.substr(0, wordnum);
                realstr += L"...";
                size_text = Vec2(textwidth(realstr.c_str()), textsize);
                Outtextxy_TCW(this->boundingbox.position - size_text / 2.0, realstr.c_str());
            }
        }
        else
        {
            Rectangle_TCW(this->boundingbox.position - this->defaultsize / 2.0,
                this->boundingbox.position + this->defaultsize / 2.0);
            Fillrectangle_TCW(this->boundingbox.position - this->defaultsize / 2.0,
                this->boundingbox.position + this->defaultsize / 2.0);
            if (defaulttext.x >= size_text.x && defaulttext.y >= size_text.y)
                Outtextxy_TCW(this->boundingbox.position - size_text / 2.0, buttontext.c_str());
            else Outtextxy_TCW(this->boundingbox.position - defaulttext / 2.0, TEXT("..."));
        }
 
        settextstyle(&log);
        settextcolor(textcol);
        setbkmode(bkmode);
        setlinecolor(linecol);
        setfillcolor(fillcol);
    }
 
    void Button::DrawButton_Press()
    {
        LOGFONT log;
        COLORREF textcol;
        COLORREF linecol;
        COLORREF fillcol;
        int bkmode;
        gettextstyle(&log);
        bkmode = getbkmode();
        textcol = gettextcolor();
        linecol = getlinecolor();
        fillcol = getfillcolor();
 
        settextstyle(textsize, 0, TEXT("微软雅黑"));    // 设置字体为宽高 20 的字,有一些字体的中文宽度为字母的两倍
        settextcolor(BLACK);
        setbkmode(TRANSPARENT);
        setlinecolor(BLACK);
        setfillcolor(RGB(240, 240, 240));
        Vec2 size_button = Vec2(this->boundingbox.size * textareasize);
        Vec2 size_text = Vec2(textwidth(this->buttontext.c_str()), textsize);
 
        if (boundingbox.size.x > defaultsize.x && boundingbox.size.y > defaultsize.y)
        {
            Rectangle_TCW(this->boundingbox.position - this->boundingbox.size / 2.0,
                this->boundingbox.position + this->boundingbox.size / 2.0);
            Fillrectangle_TCW(this->boundingbox.position - this->boundingbox.size / 2.0,
                this->boundingbox.position + this->boundingbox.size / 2.0);
            if (size_button.x >= size_text.x && size_button.y >= size_text.y)
            {
                Outtextxy_TCW(this->boundingbox.position - size_text / 2.0 + Vec2(2, 2), buttontext.c_str());
            }
            else
            {
                int wordnum = size_button.x / textwidth(buttontext.c_str()) * buttontext.size() - 2;
                std::wstring realstr = buttontext.substr(0, wordnum);
                realstr += L"...";
                size_text = Vec2(textwidth(realstr.c_str()), textsize);
                Outtextxy_TCW(this->boundingbox.position - size_text / 2.0, realstr.c_str());
            }
        }
        else
        {
            Rectangle_TCW(this->boundingbox.position - this->defaultsize / 2.0,
                this->boundingbox.position + this->defaultsize / 2.0);
            Fillrectangle_TCW(this->boundingbox.position - this->defaultsize / 2.0,
                this->boundingbox.position + this->defaultsize / 2.0);
            if (defaulttext.x >= size_text.x && defaulttext.y >= size_text.y)
                Outtextxy_TCW(this->boundingbox.position - size_text / 2.0 + Vec2(2, 2), buttontext.c_str());
            else Outtextxy_TCW(this->boundingbox.position - defaulttext / 2.0 + Vec2(2, 2), TEXT("..."));
        }
 
        settextstyle(&log);
        settextcolor(textcol);
        setbkmode(bkmode);
        setlinecolor(linecol);
        setfillcolor(fillcol);
    }
    
    void Button::DrawButton_Forbidden()
    {
        LOGFONT log;
        COLORREF textcol;
        COLORREF linecol;
        COLORREF fillcol;
        int bkmode;
        gettextstyle(&log);
        bkmode = getbkmode();
        textcol = gettextcolor();
        linecol = getlinecolor();
        fillcol = getfillcolor();
 
        settextstyle(textsize, 0, TEXT("微软雅黑"));
        settextcolor(RGB(128, 128, 128));
        setbkmode(TRANSPARENT);
        setlinecolor(BLACK);
        setfillcolor(WHITE);
        Vec2 size_button = Vec2(this->boundingbox.size * textareasize);
        Vec2 size_text = Vec2(textwidth(this->buttontext.c_str()), textsize);
 
        if (boundingbox.size.x > defaultsize.x && boundingbox.size.y > defaultsize.y)
        {
            Rectangle_TCW(this->boundingbox.position - this->boundingbox.size / 2.0,
                this->boundingbox.position + this->boundingbox.size / 2.0);
            Fillrectangle_TCW(this->boundingbox.position - this->boundingbox.size / 2.0,
                this->boundingbox.position + this->boundingbox.size / 2.0);
            if (size_button.x >= size_text.x && size_button.y >= size_text.y)
            {
                Outtextxy_TCW(this->boundingbox.position - size_text / 2.0, buttontext.c_str());
            }
            else
            {
                int wordnum = size_button.x / textwidth(buttontext.c_str()) * buttontext.size() - 2;
                std::wstring realstr = buttontext.substr(0, wordnum);
                realstr += L"...";
                size_text = Vec2(textwidth(realstr.c_str()), textsize);
                Outtextxy_TCW(this->boundingbox.position - size_text / 2.0, realstr.c_str());
            }
        }
        else
        {
            Rectangle_TCW(this->boundingbox.position - this->defaultsize / 2.0,
                this->boundingbox.position + this->defaultsize / 2.0);
            Fillrectangle_TCW(this->boundingbox.position - this->defaultsize / 2.0,
                this->boundingbox.position + this->defaultsize / 2.0);
            if (defaulttext.x >= size_text.x && defaulttext.y >= size_text.y)
                Outtextxy_TCW(this->boundingbox.position - size_text / 2.0, buttontext.c_str());
            else Outtextxy_TCW(this->boundingbox.position - defaulttext / 2.0, TEXT("..."));
        }
 
        settextstyle(&log);
        settextcolor(textcol);
        setbkmode(bkmode);
        setlinecolor(linecol);
        setfillcolor(fillcol);
    }
 
    void Button::DrawButton()
    {
        switch (this->nowstate)
        {
        case State::general:
            DrawButton_General();
            break;
        case State::touch:
            DrawButton_Touch();
            break;
        case State::press:
            DrawButton_Press();
            break;
        case State::release:
            DrawButton_Touch();
            if (releaseFunc != nullptr)
            {
                if (releaseParam == TCW_GUI_BUTTON_MYSELF)releaseFunc(this);
                else releaseFunc(releaseParam);
            }
            this->nowstate = State::touch;
            break;
        case State::forbidden:
            DrawButton_Forbidden();
            break;
        default:
            break;
        }
    }
 
    void Button::receiver(ExMessage* msg)
    {
        if (this->nowstate == State::forbidden)return;
        // 先 general 后 touch 再 press 一个 release 后重新 general
        if (!isPress && !this->boundingbox.isInRect(Vec2(msg->x, msg->y)))
        {
            this->nowstate = State::general;
        }
        else if (!isPress && this->boundingbox.isInRect(Vec2(msg->x, msg->y)))
        {
            if (!msg->lbutton)
                this->nowstate = State::touch;
            else if (this->nowstate == State::touch)
            {
                isPress = true;
                this->nowstate = State::press;
            }
        }
        else if (isPress && this->boundingbox.isInRect(Vec2(msg->x, msg->y)))
        {
            if (!msg->lbutton)
            {
                isPress = false;
                this->nowstate = State::release;
            }
            else this->nowstate = State::press;
        }
        else if (isPress && !this->boundingbox.isInRect(Vec2(msg->x, msg->y)))
        {
            if (!msg->lbutton)
            {
                isPress = false;
                this->nowstate = State::general;
            }
            else this->nowstate = State::press;
        }
    }
 
    Button* ButtonManager::AddButton(Button button)
    {
        this->buttonlist.push_back(button);
        return &buttonlist.back();
    }
 
    void ButtonManager::ReceiveMessage(ExMessage* msg)
    {
        for (Button& button : this->buttonlist)
        {
            button.receiver(msg);
        }
    }
 
    void ButtonManager::DrawButton()
    {
        for (Button& button : this->buttonlist)
        {
            button.DrawButton();
        }
    }
}

main.cpp:

 
// 程序:一个正方体
// 编译环境:Visual Studio 2019,EasyX_20211109
// 
 
#include<math.h>
#include<coNIO.h>
#include"TCW_GUI.h"
#define WIDTH 640						// 窗口宽度
#define HEIGHT 480						// 窗口高度
#define PI 3.14159265					// π
#define SIDE (min(WIDTH, HEIGHT) / 4)	// 正方体边长
#define GAMEPAD (SIDE / 2)				// 手柄,控制面旋转幅度的量
#define DISPLAY 3						// 展示出来顶点的尺寸
#define ARROWS 3						// 箭头尺寸
#define PIECE 360
double FocalLength = 6;					// 观察点到投影面的距离
 
// 8 个顶点的颜色,用于分辨 8 个不同的点
COLORREF VertexColor[8] =
{
	RED, YELLOW, BLUE, GREEN, BROWN, MAGENTA, CYAN, WHITE
};
 
struct Vec2
{
	double x, y;
};
 
Vec2 operator*(Vec2 a, double num)
{
	return { a.x * num, a.y * num };
}
 
Vec2 operator+(Vec2 a, Vec2 b)
{
	return { a.x + b.x, a.y + b.y };
}
 
Vec2 operator-(Vec2 a, Vec2 b)
{
	return { a.x - b.x, a.y - b.y };
}
 
double operator*(Vec2 a, Vec2 b)
{
	return a.x * b.x + a.y * b.y;
}
 
Vec2 operator/(Vec2 a, double num)
{
	return { a.x / num, a.y / num };
}
 
// 三维向量,也可以表示一个坐标
struct Vec3
{
	double x, y, z;
};
typedef struct Vec3;
 
// 求两向量相减
Vec3 operator-(Vec3 a, Vec3 b)
{
	return { a.x - b.x, a.y - b.y, a.z - b.z };
}
 
// 求两向量相加
Vec3 operator+(Vec3 a, Vec3 b)
{
	return { a.x + b.x, a.y + b.y, a.z + b.z };
}
 
// 得到两向量点乘的值
double operator*(Vec3 a, Vec3 b)
{
	return a.x * b.x + a.y * b.y + a.z * b.z;
}
 
// 得到向量缩短 num 倍后的向量
Vec3 operator/(Vec3 a, long double num)
{
	Vec3 result;
	result.x = a.x / num;
	result.y = a.y / num;
	result.z = a.z / num;
	return result;
}
 
// 得到向量延长 num 倍后的向量
Vec3 operator*(Vec3 a, long double num)
{
	Vec3 result;
	result.x = a.x * num;
	result.y = a.y * num;
	result.z = a.z * num;
	return result;
}
 
// 得到一个向量的模长
double GetVec3Length(Vec3 vec)
{
	return sqrt(vec.x * vec.x + vec.y * vec.y + vec.z * vec.z);
}
 
// 得到向量 a 与向量 b 的夹角余弦值
double GetCosineOfTheAngle(Vec3 a, Vec3 b)
{
	return a * b / GetVec3Length(a) / GetVec3Length(b);
}
 
// 得到向量 A 在向量 B 上的投影
Vec3 GetProjectionAOntoB(Vec3 A, Vec3 B)
{
	double num = GetCosineOfTheAngle(A, B);				// 得到向量 A,B 的夹角余弦值
	double length = GetVec3Length(A) * num;					// 向量 A 的模长乘 num 为向量 A 在向量 B 上投影的模长
	Vec3 result = B * (abs(length) / GetVec3Length(B));	// 向量 B 延长 length 倍再缩短 B 的模长倍就是向量 A 在向量 B 上的投影
	// 如果 length 比 0 小说明 num 小于 0,也就是两向量夹角大于 90 度,结果要变为相反向量
	if (length > 0)return result;
	return result * (-1.0);
}
 
// 根据投影面 x,y 轴正方向向量求出投影面法向量
Vec3 getVerticalAxis(Vec3 AuxiliaryVector[2])
{
	double x0 = AuxiliaryVector[0].x;
	double y0 = AuxiliaryVector[0].y;
	double z0 = AuxiliaryVector[0].z;
	double x1 = AuxiliaryVector[1].x;
	double y1 = AuxiliaryVector[1].y;
	double z1 = AuxiliaryVector[1].z;
	Vec3 result = { y0 * z1 - y1 * z0, x1 * z0 - x0 * z1, x0 * y1 - x1 * y0 };
	return result;
}
 
// 将三维的点的值转换为在对应 xoy 面上的投影的坐标
typedef Vec3 DoubleVec3[2];
Vec2 TransfORM3DTo2D(Vec3 vertex, DoubleVec3 AuxiliaryVector, bool isParallel)
{
	Vec2 result;
	Vec3 tempX = GetProjectionAOntoB(vertex, AuxiliaryVector[0]);	// 得到三维向量在 x 轴上的投影
	Vec3 tempY = GetProjectionAOntoB(vertex, AuxiliaryVector[1]);	// 得到三维向量在 y 轴上的投影
	result.x = GetVec3Length(tempX);								// 得到 tempX 的模长,模长就是结果的 x 值的绝对值
	result.y = GetVec3Length(tempY);								// 得到 tempY 的模长,模长就是结果的 y 值的绝对值
	if (tempX * AuxiliaryVector[0] < 0)result.x *= -1;				// 如果 tempX 向量与 x 轴正方向的向量夹角大于 90 度,也就是向量点乘为负数,那么结果的 x 值为负数
	if (tempY * AuxiliaryVector[1] < 0)result.y *= -1;				// 如果 tempY 向量与 y 轴正方向的向量夹角大于 90 度,也就是向量点乘为负数,那么结果的 y 值为负数
	if (isParallel)return result;
	Vec3 Vec_Z = getVerticalAxis(AuxiliaryVector) * SIDE * FocalLength;
	Vec3 target = vertex - Vec_Z;
	return result * (SIDE * FocalLength / GetVec3Length(GetProjectionAOntoB(target, Vec_Z)));
}
 
// 画一个正方体
void drawCube(Vec3 Vertex[8], Vec3 AuxiliaryVector[2], Vec2 pericenter, bool isParallel)
{
	Vec2 Temp[8];
	for (int i = 0; i < 8; i++)
	{
		Vec2 temp = Transform3DTo2D(Vertex[i], AuxiliaryVector, isParallel);
		Temp[i] = temp;
		setfillcolor(VertexColor[i]);
		solidcircle(temp.x + pericenter.x, temp.y + pericenter.y, DISPLAY);
	}
	line(Temp[0].x + pericenter.x, Temp[0].y + pericenter.y, Temp[3].x + pericenter.x, Temp[3].y + pericenter.y);
	line(Temp[0].x + pericenter.x, Temp[0].y + pericenter.y, Temp[1].x + pericenter.x, Temp[1].y + pericenter.y);
	line(Temp[0].x + pericenter.x, Temp[0].y + pericenter.y, Temp[4].x + pericenter.x, Temp[4].y + pericenter.y);
	line(Temp[1].x + pericenter.x, Temp[1].y + pericenter.y, Temp[2].x + pericenter.x, Temp[2].y + pericenter.y);
	line(Temp[1].x + pericenter.x, Temp[1].y + pericenter.y, Temp[5].x + pericenter.x, Temp[5].y + pericenter.y);
	line(Temp[2].x + pericenter.x, Temp[2].y + pericenter.y, Temp[3].x + pericenter.x, Temp[3].y + pericenter.y);
	line(Temp[2].x + pericenter.x, Temp[2].y + pericenter.y, Temp[6].x + pericenter.x, Temp[6].y + pericenter.y);
	line(Temp[3].x + pericenter.x, Temp[3].y + pericenter.y, Temp[7].x + pericenter.x, Temp[7].y + pericenter.y);
	line(Temp[4].x + pericenter.x, Temp[4].y + pericenter.y, Temp[5].x + pericenter.x, Temp[5].y + pericenter.y);
	line(Temp[4].x + pericenter.x, Temp[4].y + pericenter.y, Temp[7].x + pericenter.x, Temp[7].y + pericenter.y);
	line(Temp[5].x + pericenter.x, Temp[5].y + pericenter.y, Temp[6].x + pericenter.x, Temp[6].y + pericenter.y);
	line(Temp[6].x + pericenter.x, Temp[6].y + pericenter.y, Temp[7].x + pericenter.x, Temp[7].y + pericenter.y);
	char arr[128];
	WCHAR ano[128];
	settextstyle(0, 0, _T("Consolas"));
	settextcolor(WHITE);
	sprintf_s(arr, "x:(%f, %f, %f)", AuxiliaryVector[0].x, AuxiliaryVector[0].y, AuxiliaryVector[0].z);
	MultiByteToWideChar(CP_ACP, 0, arr, -1, ano, 128);
	outtextxy(10, HEIGHT / 6 * 5, ano);
	sprintf_s(arr, "y:(%f, %f, %f)", AuxiliaryVector[1].x, AuxiliaryVector[1].y, AuxiliaryVector[1].z);
	MultiByteToWideChar(CP_ACP, 0, arr, -1, ano, 128);
	outtextxy(10, HEIGHT / 9 * 8, ano);
}
 
// 得到两个点之间的距离(二维)
double getTwoPointDistance(Vec2 a, Vec2 b)
{
	return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
 
// 得到 8 个顶点中距离 point 这个二维点最近的点,p 是判断两点间距离是否符合要求的
int getNearestIndex(Vec3 Vertex[8], Vec3 AuxiliaryVector[2], Vec2 point, bool isParallel, bool (*p)(double) = nullptr)
{
	int result = 0;
	double nearestDistance = getTwoPointDistance(Transform3DTo2D(Vertex[0], AuxiliaryVector, isParallel), point);
	for (int i = 1; i < 8; i++)
	{
		double temp = getTwoPointDistance(Transform3DTo2D(Vertex[i], AuxiliaryVector, isParallel), point);
		if (temp < nearestDistance)
		{
			result = i;
			nearestDistance = temp;
		}
	}
	if (p != nullptr && !p(nearestDistance))return -1;
	return result;
}
 
void Line(Vec2 begin, Vec2 end)
{
	line(begin.x, begin.y, end.x, end.y);
}
 
// grading 是粒度,一条线分为几份,0.1 是 10 份
void progressiveLine(Vec3 begincol, Vec3 endcol, Vec2 started, Vec2 finaled, double grading = 0.1)
{
	Vec2 AddLine = (finaled - started) * grading;
	Vec3 AddCol = (endcol - begincol) * grading;
	Vec3 nowcol = begincol;
	for (int i = 0; i < 1 / grading; i++)
	{
		nowcol = nowcol + AddCol;
		setlinecolor(RGB(nowcol.x, nowcol.y, nowcol.z));
		Line(started + AddLine * i, started + AddLine * (i + 1));
	}
}
 
// 画坐标轴,pericenter 是中心点,size 是一个单位长度的长度
void drawCoordinateAxis(Vec2 pericenter, double size)
{
	setlinestyle(PS_SOLID, 1);
	setlinecolor(WHITE);
	settextcolor(WHITE);
	settextstyle(20, 0, _T("Consolas"));
	double index_X = size * sqrt(3) / sqrt(5);
	double index_Y = size * sqrt(2) / sqrt(5);
	progressiveLine({ 0, 0, 0 }, { 255, 255, 255 }, pericenter + Vec2({ -index_X, -index_Y }),
		pericenter + Vec2({ index_X, index_Y }));
	line(pericenter.x + index_X - ARROWS, pericenter.y + index_Y, pericenter.x + index_X, pericenter.y + index_Y);
	line(pericenter.x + index_X, pericenter.y + index_Y - ARROWS, pericenter.x + index_X, pericenter.y + index_Y);
	outtextxy(pericenter.x + index_X, pericenter.y + index_Y, L"y");
 
	progressiveLine({ 0, 0, 0 }, { 255, 255, 255 }, pericenter + Vec2({ index_X, -index_Y }),
		pericenter + Vec2({ -index_X, +index_Y }));
	line(pericenter.x - index_X + ARROWS, pericenter.y + index_Y, pericenter.x - index_X, pericenter.y + index_Y);
	line(pericenter.x - index_X, pericenter.y + index_Y - ARROWS, pericenter.x - index_X, pericenter.y + index_Y);
	outtextxy(pericenter.x - index_X, pericenter.y + index_Y, L"x");
 
	progressiveLine({ 0, 0, 0 }, { 255, 255, 255 }, pericenter + Vec2({ 0, index_X }),
		pericenter + Vec2({ 0, -index_X }));
	line(pericenter.x + ARROWS, pericenter.y - index_X + ARROWS, pericenter.x, pericenter.y - index_X);
	line(pericenter.x - ARROWS, pericenter.y - index_X + ARROWS, pericenter.x, pericenter.y - index_X);
	outtextxy(pericenter.x, pericenter.y - index_X - 20, L"z");
}
 
// 画出辅助向量
void drawAuxiliaryVector(Vec3 AuxiliaryVector[2], Vec2 pericenter, double size, bool isParallel)
{
	settextstyle(20, 0, _T("Consolas"));
	Vec3 Auxiliary[2] = { {-1, 1, 0}, {-1, -1, 1} };
	Auxiliary[0] = Auxiliary[0] / GetVec3Length(Auxiliary[0]);
	Auxiliary[1] = Auxiliary[1] / GetVec3Length(Auxiliary[1]);
	Vec2 temp[2];
	temp[0] = Transform3DTo2D(AuxiliaryVector[0] * size, Auxiliary, isParallel);	// x 轴
	temp[1] = Transform3DTo2D(AuxiliaryVector[1] * size, Auxiliary, isParallel);	// y 轴
	double Cos_XX = GetCosineOfTheAngle(getVerticalAxis(Auxiliary), AuxiliaryVector[0]);
	double Cos_YY = GetCosineOfTheAngle(getVerticalAxis(Auxiliary), AuxiliaryVector[1]);
	if (Cos_XX < 0.0 && Cos_YY < 0.0)
	{
		setlinestyle(PS_SOLID, 2);
		progressiveLine({ 127, 0, 0 }, { 127 + 127 * Cos_XX, 0, 0 }, pericenter,
			pericenter + Vec2({ temp[0].x, -temp[0].y }));
		progressiveLine({ 127, 0, 0 }, { 127 + 127 * Cos_YY, 0, 0 }, pericenter,
			pericenter + Vec2({ temp[1].x, -temp[1].y }));
		drawCoordinateAxis(pericenter, size);
	}
	else if (Cos_XX >= 0.0 && Cos_YY < 0.0)
	{
		setlinestyle(PS_SOLID, 2);
		progressiveLine({ 127, 0, 0 }, { 127 + 127 * Cos_YY, 0, 0 }, pericenter,
			pericenter + Vec2({ temp[1].x, -temp[1].y }));
		drawCoordinateAxis(pericenter, size);
		setlinestyle(PS_SOLID, 2);
		progressiveLine({ 127, 0, 0 }, { 127 + 127 * Cos_XX, 0, 0 }, pericenter,
			pericenter + Vec2({ temp[0].x, -temp[0].y }));
	}
	else if (Cos_XX < 0.0 && Cos_YY >= 0.0)
	{
		setlinestyle(PS_SOLID, 2);
		progressiveLine({ 127, 0, 0 }, { 127 + 127 * Cos_XX, 0, 0 }, pericenter,
			pericenter + Vec2({ temp[0].x, -temp[0].y }));
		drawCoordinateAxis(pericenter, size);
		setlinestyle(PS_SOLID, 2);
		progressiveLine({ 127, 0, 0 }, { 127 + 127 * Cos_YY, 0, 0 }, pericenter,
			pericenter + Vec2({ temp[1].x, -temp[1].y }));
	}
	else if (Cos_XX >= 0.0 && Cos_YY >= 0.0)
	{
		drawCoordinateAxis(pericenter, size);
		setlinestyle(PS_SOLID, 2);
		progressiveLine({ 127, 0, 0 }, { 127 + 127 * Cos_XX, 0, 0 }, pericenter,
			pericenter + Vec2({ temp[0].x, -temp[0].y }));
		progressiveLine({ 127, 0, 0 }, { 127 + 127 * Cos_YY, 0, 0 }, pericenter,
			pericenter + Vec2({ temp[1].x, -temp[1].y }));
	}
	settextcolor(RED);
	outtextxy(pericenter.x + temp[0].x, pericenter.y - temp[0].y, L"X");
	outtextxy(pericenter.x + temp[1].x, pericenter.y - temp[1].y, L"Y");
	setlinestyle(PS_SOLID, 1);
	setlinecolor(WHITE);
}
 
// x 轴固定在 xoy 平面上,旋转 x 轴和 z 轴就能看到这个三维物体的所有角度!!!
int main()
{
	bool isExit = false;
	initgraph(WIDTH, HEIGHT);
	BeginBatchDraw();
	Vec3 AuxiliaryVector[2] = { { sqrt(2) / 2.0, sqrt(2) / 2.0, 0 },
		{ -sqrt(3) / 3.0, sqrt(3) / 3, sqrt(3) / 3.0 } };	// 辅助向量,分别是 x 轴,y 轴的单位向量
 
	bool isParallel = false;
 
	TCW_GUI::Button* button_param[2];
 
	TCW_GUI::ButtonManager manager;
	TCW_GUI::Button* button_temp = manager.AddButton(TCW_GUI::Button(TCW_GUI::Rect(TCW_GUI::Vec2(WIDTH * 5 / 6.0, HEIGHT / 6.0),
		TCW_GUI::Vec2(WIDTH / 7.0, HEIGHT / 7.0)), L"透视投影",
		[&](void* param)
		{
			TCW_GUI::Button** button = (TCW_GUI::Button**)param;
			if (isParallel)
			{
				button[0]->buttontext = L"透视投影";
				button[1]->RefreshButton();
				isParallel = false;
			}
			else
			{
				button[0]->buttontext = L"平行投影";
				button[1]->ForbidButton();
				isParallel = true;
			}
			return 0;
		}, nullptr));
	button_temp->releaseParam = button_param;
	button_param[0] = button_temp;
 
	button_param[1] = manager.AddButton(TCW_GUI::Button(TCW_GUI::Rect(TCW_GUI::Vec2(WIDTH * 5 / 6.0, HEIGHT / 3.0),
		TCW_GUI::Vec2(WIDTH / 7.0, HEIGHT / 7.0)), L"透视距离",
		[&](void* param)
		{
			WCHAR arr[128];
			char ano[128];
			InputBox(arr, 128, L"请输入透视距离(推荐 1~10, 可小数)");
			WideCharToMultiByte(CP_UTF8, 0, arr, -1, ano, 128, NULL, FALSE);
			sscanf(ano, "%lf", &FocalLength);
			return 0;
		}, nullptr));
 
	manager.AddButton(TCW_GUI::Button(TCW_GUI::Rect(TCW_GUI::Vec2(WIDTH * 5 / 6.0, HEIGHT / 2.0),
		TCW_GUI::Vec2(WIDTH / 7.0, HEIGHT / 7.0)), L"结束程序",
		[](void* param)
		{
			bool* isExit = (bool*)param;
			*isExit = true;
			return 0;
		}, &isExit));
 
	Vec3 Vertex[8];										// 8 个顶点的坐标
	// 初始化 8 个顶点,这 8 个顶点是固定的,可以改变为任意坐标值,我们只是从不同的角度看这 8 个顶点
	Vertex[0] = { -GAMEPAD, -GAMEPAD, -GAMEPAD };
	Vertex[1] = { GAMEPAD, -GAMEPAD, -GAMEPAD };
	Vertex[2] = { GAMEPAD, GAMEPAD, -GAMEPAD };
	Vertex[3] = { -GAMEPAD, GAMEPAD, -GAMEPAD };
	Vertex[4] = { -GAMEPAD, -GAMEPAD, GAMEPAD };
	Vertex[5] = { GAMEPAD, -GAMEPAD, GAMEPAD };
	Vertex[6] = { GAMEPAD, GAMEPAD, GAMEPAD };
	Vertex[7] = { -GAMEPAD, GAMEPAD, GAMEPAD };
	ExMessage msg;							// 鼠标信息
	bool ispress = false;					// 是否按下
	bool isLpress = false;					// 是否按下左键
	bool isRpress = false;					// 是否按下右键
	double originalX = 0, originalY = 0;		// 原来的坐标
	int vertexIndex = 0;					// 右键点击时要操作的顶点的坐标
	while (!isExit)
	{
		while (peekmessage(&msg, EM_MOUSE))
		{
			if (!ispress && (msg.lbutton || msg.rbutton))
			{
				ispress = true;
				if (msg.lbutton)isLpress = true;										// 左键按下
				else if (msg.rbutton)													// 右键按下
				{
					isRpress = true;
					vertexIndex = getNearestIndex(Vertex, AuxiliaryVector, 				// 得到距离按下的位置最近的正方体顶点的下标
						{ (double)msg.x - WIDTH / 2, (double)msg.y - HEIGHT / 2 }, isParallel,
						[](double num) {if (num < DISPLAY)return true; return false; });	// 这个 lambda 表达式是为了让点到的地方距离最近的正方体顶点距离小于展示出来正方体顶点的尺寸才能生效
				}
				originalX = msg.x;
				originalY = msg.y;
			}
			else if (isLpress && msg.lbutton)
			{
				double DelFi = (msg.y - originalY) / 6 / GAMEPAD * PI;
				double DelTh = (msg.x - originalX) / GAMEPAD / 6 * PI;
				Vec3 tempVectorX = AuxiliaryVector[0];
				Vec3 tempVectorY = AuxiliaryVector[1];
				Vec3 tempVectorZ = getVerticalAxis(AuxiliaryVector);
 
				AuxiliaryVector[0] = tempVectorX * cos(DelTh) + tempVectorZ * sin(DelTh);	// 改变 x 轴向量
				tempVectorZ = tempVectorZ * cos(DelTh) - tempVectorX * sin(DelTh);
				AuxiliaryVector[1] = tempVectorY * cos(DelFi) + tempVectorZ * sin(DelFi);	// 改变 y 轴向量
				originalX = msg.x;
				originalY = msg.y;
			}
			else if (isRpress && msg.rbutton && vertexIndex != -1)
			{
				double lengthX = msg.x - originalX;			// 在投影面横坐标上移动的距离
				double lengthY = msg.y - originalY;			// 在投影面纵坐标上移动的距离
				// 对于选中的顶点,它变为它自身的向量加上投影面上的向量
				Vertex[vertexIndex] =
					Vertex[vertexIndex] +
					AuxiliaryVector[0] * lengthX / GetVec3Length(AuxiliaryVector[0]) +
					AuxiliaryVector[1] * lengthY / GetVec3Length(AuxiliaryVector[1]);
				originalX = msg.x;
				originalY = msg.y;
			}
			else if (ispress && !msg.lbutton)
			{
				ispress = false;
				isLpress = false;
				isRpress = false;
			}
			else if (msg.wheel)
			{
				double DelTh = msg.wheel / 120.0 * PI / 60.0;	// 滚动 120 度旋转 3 度
				Vec3 tempVectorX = AuxiliaryVector[0];
				Vec3 tempVectorY = AuxiliaryVector[1];
				Vec3 tempVectorZ = getVerticalAxis(AuxiliaryVector);
				AuxiliaryVector[0] = tempVectorX * cos(DelTh) + tempVectorY * sin(DelTh);	// 改变 x 轴向量
				AuxiliaryVector[1] = tempVectorY * cos(DelTh) - tempVectorX * sin(DelTh);	// 改变 y 轴向量
			}
		}
		// 用鼠标不能进行精密控制,在这里用 wasd 实现键盘控制
		if (_kbhit())
		{
			// 按一下移动 3 度
			double DelFi = 0, DelTh = 0;
			Vec3 tempVectorX = AuxiliaryVector[0];
			Vec3 tempVectorY = AuxiliaryVector[1];
			Vec3 tempVectorZ = getVerticalAxis(AuxiliaryVector);
			switch (_getch())
			{
			case 'w':DelFi -= PI / 60.0;	break;
			case 'a':DelTh += PI / 60.0;	break;
			case 's':DelFi += PI / 60.0;	break;
			case 'd':DelTh -= PI / 60.0;	break;
			default:
				break;
			}
			AuxiliaryVector[0] = tempVectorX * cos(DelTh) + tempVectorZ * sin(DelTh);	// 改变 x 轴向量
			tempVectorZ = tempVectorZ * cos(DelTh) - tempVectorZ * sin(DelTh);
			AuxiliaryVector[1] = tempVectorY * cos(DelFi) + tempVectorZ * sin(DelFi);	// 改变 y 轴向量
		}
		cleardevice();
		drawCube(Vertex, AuxiliaryVector, { WIDTH / 2.0, HEIGHT / 2.0 }, isParallel);
		drawAuxiliaryVector(AuxiliaryVector, { WIDTH / 6 * 5, HEIGHT / 6 * 5 }, min(WIDTH, HEIGHT) / 9,
			isParallel);
		manager.ReceiveMessage(&msg);
		manager.DrawButton();
		FlushBatchDraw();
	}
	closegraph();
	return 0;
}

到此这篇关于利用C语言绘制一个正方体的文章就介绍到这了,更多相关C语言绘制正方体内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: 利用C语言绘制一个正方体

本文链接: https://www.lsjlt.com/news/176899.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 利用C语言绘制一个正方体
    目录程序截图操作方法个人思路代码实现程序截图 操作方法 鼠标拖动。左键拖动及滚轮能看到不同角度下正方体的形状,右键拖动能将最近的正方体顶点挪到这个投影面的相应位置。 按键控制。wa...
    99+
    2023-01-06
    C语言绘制正方体 C语言 正方体
  • 利用R语言怎么绘制一个折线图
    这篇文章将为大家详细讲解有关利用R语言怎么绘制一个折线图,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。R语言中的plot()函数用于创建折线图。语法在R语言中创建折线图的基本语法是 -plo...
    99+
    2023-06-14
  • 使用R语言怎么绘制一个直方图
    使用R语言怎么绘制一个直方图?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。语法使用R语言创建直方图的基本语法是hist(v,main,xlab,xlim,ylim,brea...
    99+
    2023-06-14
  • 怎么用c语言输出一个空心正方形
    include int main() { int side; printf("请输入正方形的边长:"); scanf("%d", ...
    99+
    2023-10-27
    c语言
  • C语言利用EasyX绘制小企鹅表情包
    使用 C 语言调用 EasyX 绘图库绘制小企鹅表情包,简直太可爱了! 简单分析一下,这个小企鹅的构成,主要是由黑白颜色和简单的圆与椭圆构成,也不是很复杂,如果...
    99+
    2022-12-21
    C语言EasyX绘制表情包 C语言绘制表情包 C语言 EasyX
  • 使用R语言怎么绘制一个折线图
    这篇文章给大家介绍使用R语言怎么绘制一个折线图,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。在R中的通过使用plot()函数来创建线形图,语法如下:plot(v,type,col,xlab,ylab)参数描述如下:v ...
    99+
    2023-06-14
  • 使用R语言怎么绘制一个饼状图
    今天就跟大家聊聊有关使用R语言怎么绘制一个饼状图,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。什么是R语言R语言是用于统计分析、绘图的语言和操作环境,属于GNU系统的一个自由、免费、...
    99+
    2023-06-14
  • 利用Java和c语言写一个计算器
    目录一、java计算器1、类名计算器2、类名sum3、示例图4、代码4.1计算器类4.2sum类下二、C语言下的计算器2、代码一、java计算器 步骤:   1.建包 ...
    99+
    2022-11-12
  • 利用C语言编写一个扫雷游戏
    本篇文章为大家展示了利用C语言编写一个扫雷游戏,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。C语言是什么C语言是一门面向过程的、抽象化的通用程序设计语言,广泛应用于底层开发,使用C语言可以以简易的方...
    99+
    2023-06-06
  • 利用C语言编写一个无限循环语句
    目录用C编写一个无限循环语句C语言进入无限循环的三种方法1、使用while语句2、使用for语句3、使用goto语句用C编写一个无限循环语句 今天比较无聊,看了些基本的for循环和w...
    99+
    2022-11-13
    C语言循环语句 无限循环语句 C语言无限循环语句
  • 利用C语言编写一个三子棋游戏
    这篇文章给大家介绍利用C语言编写一个三子棋游戏,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。具体内容如下说明:该游戏的实现需要用到三个文件1、test.c:放置主函数(main())和菜单函数(menu())和游戏函数...
    99+
    2023-06-06
  • 利用C语言如何实现一个扫雷游戏
    利用C语言如何实现一个扫雷游戏?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。菜单的实现代码:int main(){int input =&nb...
    99+
    2023-06-06
  • 使用C语言制作一个猜数字游戏
    本篇文章为大家展示了使用C语言制作一个猜数字游戏,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。C语言是什么C语言是一门面向过程的、抽象化的通用程序设计语言,广泛应用于底层开发,使用C语言可以以简易的...
    99+
    2023-06-15
  • C语言利用goto语句设计实现一个关机程序
    目录前言一、什么是goto语句二、goto语句的作用是什么三、goto语句的缺点四、goto语句的结构与用法五、goto语句的巧用实例——关机小程序总结撒花前...
    99+
    2023-01-28
    C语言 goto实现关机程序 C语言 goto 关机程序 C语言 goto
  • 使用C语言怎么制作一个扫雷游戏
    本篇文章给大家分享的是有关使用C语言怎么制作一个扫雷游戏,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。C语言是什么C语言是一门面向过程的、抽象化的通用程序设计语言,广泛应用于底...
    99+
    2023-06-14
  • 利用C语言实现一个最简单的飞机游戏
    目录前言一、利用scanf控制飞机移动二、getch控制飞机移动三、显示复杂的飞机图案四、发射激光五、打靶练习前言 在前面弹跳小球的基础上实现一个简单的飞机游戏,主要包括飞机的显示、...
    99+
    2022-11-13
  • C语言中如何利用循环嵌套输出一个菱形
    目录利用循环嵌套输出一个菱形C语言输出半个菱形总结利用循环嵌套输出一个菱形 #include<stdio.h> int main() { int i, j; for...
    99+
    2023-02-06
    C语言循环嵌套 循环嵌套输出菱形 C语言循环
  • 利用C语言实现一个可展开的扫雷小游戏
    利用C语言实现一个可展开的扫雷小游戏?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。C语言是什么C语言是一门面向过程的、抽象化的通用程序设计语言,广泛应用于底层开发,使用C语...
    99+
    2023-06-06
  • C语言如何得到一个结构体中field所占用的字节数
    这篇文章主要为大家展示了“C语言如何得到一个结构体中field所占用的字节数”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“C语言如何得到一个结构体中field所...
    99+
    2022-10-19
  • C#怎么利用资源文件开发一个多种语言版本的程序
    这篇文章主要讲解了“C#怎么利用资源文件开发一个多种语言版本的程序”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C#怎么利用资源文件开发一个多种语言版本的程序”吧!C#语言还是比较常见的东西...
    99+
    2023-06-17
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作