C&C++   发布时间:2022-04-01  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了<c++控制台>用光标移动函数gotoxy()实现方向键进行选择大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

0.效果图

<c++控制台>用光标移动函数gotoxy()实现方向键进行选择

 

可以用方向键进行选择,看起来高级点而且可以防止乱输入。

 

1.引入:

这是我以前经常写的选择:

<c++控制台>用光标移动函数gotoxy()实现方向键进行选择

 

相信这应该也是很多人在控制台的时候会用的吧,

的确这个简单容易写。

 

但!是!

人要有理想,控制台也是

 

所以我开始想把它写成一般游戏那种上下选择的样子:

<c++控制台>用光标移动函数gotoxy()实现方向键进行选择

所以就有了这篇博文

 

 

//------接下来让我们进入正题-----

 

2.思路

 

注意:内容代码中使用了我自定义的命名空间coolfun

如果必要请自行修改

 

我们首先把这部分cout出来

<c++控制台>用光标移动函数gotoxy()实现方向键进行选择

 

然后我们需要使用到控制台里的光标移动函数gotoxy()(头文件:<windows.h>)

 

图中最后的白块就是光标,光标在哪,cout输出的东西就会从那开始。(应该都是懂的吧...)

 

注意:gotoxy()并不是c++标准库里的,windows.h里其实也没有这玩意,

所以我们需要借助<windows.h>来自己“写一个”。

void light_gotoxy(int x, int y)
{
    COORD pos = { (short)x,(short)y };
    HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsolecursorPosition(hOut, pos);
}

这里的x是横坐标,Y 是纵坐标。

 

借助gotoxy()移动到选项前的空白

<c++控制台>用光标移动函数gotoxy()实现方向键进行选择

 

怎么移动呢??

 

直接看图里,选项“自动模式”是在第3行,我们编程老传统默认0为开始,所以这应该认为是第2行。

 

gotoxy(0,2);//把光标移动到第2(实际第3)行第0(实际第1)个。

 

然后在这里cout << ">>>" ;

 

就会有这样的效果:

<c++控制台>用光标移动函数gotoxy()实现方向键进行选择

 

看起来已经有点感觉了!

 

然后我们只需要监控键盘的方向键,控制“>>>”的上下就可以了。

 

怎么样,听起来是不是简简单单!

 

但!是!

 

仅仅依靠这一个移动光标的函数是不够的,

 

因为在让选择的这部分字打印之前经常是会有一些其他的提示,

 

抑或是之前已经有了一些输出了,例如:

<c++控制台>用光标移动函数gotoxy()实现方向键进行选择

 

我们是要把它搞成一个可以经常用的函数

 

不可能每次需要就自己数数在哪一行开始输出选项并移动

 

所以我们需要一个函数来获取在这之前光标的位置。

 

light_getxy() :  获取当前光标所在位置

void light_getxy(int& x, int& y)
{
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    GetConsoleScreenBufferInfo(hConsole, &csbi);
    x = csbi.dwcursorPosition.X;
    y = csbi.dwcursorPosition.Y;
}

 

把行数+1那就是下一行,然后开始cout我们我们的选项就可以了。

 

到这解决了输出位置的问题了

 

具体的让我们来看看实现代码吧。

 

这就是我们这篇博文的主体函数:

 

    template<typename T>
    int switch_case(int case_num, const T* content_str)
    {
        int nowi = 1, nowx, nowy;//nowi 记录选择的选项编号
        coolfun::light_getxy(nowx, nowy);
        cout << "<--请用上下键选择 | Enter键确定-->";
        coolfun::light_gotoxy(nowx, nowy + 1);
        const T* p = content_str;
        cout << ">>> " << *(p++);
        for (int i = 2; i <= case_num; ++i)  //先打印选项内容
        {
            coolfun::light_gotoxy(nowx, nowy + i);
            cout << "    " << *(p++);
        }
        coolfun::light_gotoxy(nowx, nowy + case_num + 1);
        coolfun::kbhit_remove();//清除残留按键
        for (int getnum;;) //等待按键按下,getnum记录按键asc
        {
            getnum = coolfun::kbhit_wait_getasc();
            coolfun::light_gotoxy(nowx, nowy + nowi); //移动到原来的编号选项前
            cout << "   ";  //覆盖掉它的">>>"
            switch (getnum) //获取按下的按键的ask2值
            {
            case 72: //
            {
                if (nowi > 1)   //在第一个再按上键会到最后一个
                    --nowi;
                else
                    nowi = case_num;
            }break;
            case 80: //
            {
                if (nowi < case_num)  //在最后一个按下键会到第一个
                    ++nowi;
                else
                    nowi = 1;
            }break;
            case 13:  //Enter键确定
            {
                coolfun::light_gotoxy(nowx, nowy + nowi);
                cout << "-->";
                coolfun::light_gotoxy(nowx, nowy + case_num + 1);
                return nowi;  //返回当前选项编号
            }break;
            }
            coolfun::light_gotoxy(nowx, nowy + nowi);//移动到修改后的位置
            cout << ">>>";
            coolfun::light_gotoxy(nowx, nowy + case_num + 1); //把光标移动回输出的最后
        }
        return 0;
    }

 

其中还用到两个按键相关的函数

头文件:<conio.h>

//清空按键缓冲区,防止之前的残留按键行为的影响
void coolfun::kbhit_remove()
{
    while (_kbhit())
        _getch();
}


//等待按键并读取按下按键的 ASC码
int coolfun::kbhit_wait_getasc()
{
    int num;
    do
    {
        num = _getch();
    } while (_kbhit());
    return num;
}

 

 

最后让我们来找给简单的例子测试一下。

 

3.测试代码 

 

使用时只需要把coolfun整个复制过去并加上头文件<windows.h>和<conio.h>

就可以调用switch_case()实现了

#include<conio.h>
#include<windows.h>


#include<iostream>

using namespace std;

namespace coolfun
{
    //清空按键缓冲区,防止之前的残留按键行为的影响
    void kbhit_remove()
    {
        while (_kbhit())
            _getch();
    }

    //等待按键并读取按下按键的 ASC码
    int kbhit_wait_getasc()
    {
        int num;
        do
        {
            num = _getch();
        } while (_kbhit());
        return num;
    }
/*光标移动函数
* x为横坐标,y为纵坐标
*/
    inline void light_gotoxy(int x, int y)
    {
        COORD pos = { (short)x,(short)y };
        HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
        SetConsolecursorPosition(hOut, pos);
    }

    /*获取光标位置
    * 同时获取xy,需要传入接受的xy变量引用
    * x为横坐标,y为纵坐标
    */
    inline void light_getxy(int& x, int& y)
    {
        HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
        CONSOLE_SCREEN_BUFFER_INFO csbi;
        GetConsoleScreenBufferInfo(hConsole, &csbi);
        x = csbi.dwcursorPosition.X;
        y = csbi.dwcursorPosition.Y;
    }

    /*选择函数
* 返回选择的content_str[]的位置,默认1开始
* case_num:contentstr的数组大小;contentstr[]:选项内容
* >支持偏移<
*/
    template<typename T>
    int switch_case(int case_num, const T* content_str)
    {
        int nowi = 1, nowx, nowy;//nowi 记录选择的选项编号
        coolfun::light_getxy(nowx, nowy);
        cout << "<--请用上下键选择 | Enter键确定-->";
        coolfun::light_gotoxy(nowx, nowy + 1);
        const T* p = content_str;
        cout << ">>> " << *(p++);
        for (int i = 2; i <= case_num; ++i)  //先打印选项内容
        {
            coolfun::light_gotoxy(nowx, nowy + i);
            cout << "    " << *(p++);
        }
        coolfun::light_gotoxy(nowx, nowy + case_num + 1);
        coolfun::kbhit_remove();//清除残留按键
        for (int getnum;;) //等待按键按下,getnum记录按键asc
        {
            getnum = coolfun::kbhit_wait_getasc();
            coolfun::light_gotoxy(nowx, nowy + nowi); //移动到原来的编号选项前
            cout << "   ";  //覆盖掉它的">>>"
            switch (getnum) //获取按下的按键的ask2值
            {
            case 72: //
            {
                if (nowi > 1)   //在第一个再按上键会到最后一个
                    --nowi;
                else
                    nowi = case_num;
            }break;
            case 80: //
            {
                if (nowi < case_num)  //在最后一个按下键会到第一个
                    ++nowi;
                else
                    nowi = 1;
            }break;
            case 13:  //Enter键确定
            {
                coolfun::light_gotoxy(nowx, nowy + nowi);
                cout << "-->";
                coolfun::light_gotoxy(nowx, nowy + case_num + 1);
                return nowi;  //返回当前选项编号
            }break;
            }
            coolfun::light_gotoxy(nowx, nowy + nowi);//移动到修改后的位置
            cout << ">>>";
            coolfun::light_gotoxy(nowx, nowy + case_num + 1); //把光标移动回输出的最后
        }
        return 0;
    }

}


int main()
{
    cout << "歪比巴布占用了这一行" << endl;
    cout << "玛卡巴卡占用了这一行" << endl;
    cout << "反冲斗士芭芭拉也需要一行" << endl;
    String str[] =
    {
       "1.自动模式",
       "2.手动模式",
    };

    cout << "<< 您希望以什么模式开始游戏?" << endl;

    cout << "\n<< 您选择了选项" << coolfun::switch_case(2, str) << endl;

    return 0;
}

 

 

运行结果:

 

<c++控制台>用光标移动函数gotoxy()实现方向键进行选择

 

 

 

4.其他

利用获取光标位置和移动光标的函数还能有其他一些不错的功能,

例如一些颜文字的打印动画,实现进度条等等,我们以后再聊聊。

 

coolight大字打印动画:

<c++控制台>用光标移动函数gotoxy()实现方向键进行选择

 

进度条:

<c++控制台>用光标移动函数gotoxy()实现方向键进行选择

大佬总结

以上是大佬教程为你收集整理的<c++控制台>用光标移动函数gotoxy()实现方向键进行选择全部内容,希望文章能够帮你解决<c++控制台>用光标移动函数gotoxy()实现方向键进行选择所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签: