经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C++ » 查看文章
<c++控制台>用gotoxy()函数实现方向键进行选择
来源:cnblogs  作者:coolight7  时间:2021/5/31 9:12:53  对本文有异议

0.效果图

 

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

 

1.引入:

这是我经常写的选择:

 

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

的确这个简单容易写。

 

但!是!

人要有理想,控制台也是

 

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

所以就有了这篇博文,

接下来让我们进入正题。

 

2.思路

我们首先把这部分cout出来

 

 

 

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

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

 

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

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

  1. 1 void gotoxy(int x, int y)//光标移动函数, 且在这里把x定义为纵坐标,y为横坐标
  2. 2 {
  3. 3 COORD pos = { y,x };
  4. 4 HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); // 获取标准输出设备句柄
  5. 5 SetConsoleCursorPosition(hOut, pos); //两个参数分别是指定哪个窗体,具体位置
  6. 6 }

因为之前写一个小游戏的时候习惯了x为纵坐标,

如果你喜欢x为横坐标的话可以把函数里的第一行代码的{y,x}改为{x,y}即可。

 

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

 

怎么移动呢??

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

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

 

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

 

就会有这样的效果:

 

怎么样,看起来是不是有感觉了!

 

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

 

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

 

但!是!

 

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

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

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

 

我们是要把它搞成一个可以经常用的函数,不可能每次需要就自己数数在哪一行,

 

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

  1. 1 int lightgetxy(int i) //获取光标位置,0为获取x,1为获取y,失败返回-1
  2. 2 {
  3. 3 HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
  4. 4 COORD coordScreen = { 0, 0 }; //光标位置
  5. 5 CONSOLE_SCREEN_BUFFER_INFO csbi;
  6. 6
  7. 7 if (GetConsoleScreenBufferInfo(hConsole, &csbi))
  8. 8 {
  9. 9 if (i) // 0为获取y,1为获取x
  10. 10 return csbi.dwCursorPosition.X;
  11. 11 else // 获取y
  12. 12 return csbi.dwCursorPosition.Y;
  13. 13 }
  14. 14 else
  15. 15 return -1;
  16. 16 }

所以现在就是利用lightgetxy()来获取选择之前光标的位置,把行数+1那就是下一行,然后开始cout我们我们的选项就可以了。

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

 

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

 

  1. 1 /*
  2. 2 选项选择函数;返回选择的contentstr[]的位置,默认1开始
  3. 3 max:contentstr的数组大小,contentstr[]:选项内容, tipstr:选择前提示
  4. 4 */
  5. 5 int switchcase(const int max, const string contentstr[], const string tipstr)
  6. 6 {
  7. 7 if (tipstr != "") //判断是否有提示字符串
  8. 8 cout << tipstr << endl;
  9. 9 cout << "<< 请用上下方向键选择..." << endl;
  10. 10 int nowi = 1, nowx = lightgetxy(0) - 1;
  11. 11 //nowi 记录选择的选项编号
  12. 12 cout << ">>> " << contentstr[0] << endl;
  13. 13 for (int i = 2; i <= max; ++i) //先打印选项内容
  14. 14 cout << " " << contentstr[i - 1] << endl;
  15. 15
  16. 16 while (1)
  17. 17 {
  18. 18 while (_kbhit()) //判断是否有按键按下
  19. 19 {
  20. 20 gotoxy(nowx + nowi, 0); //移动到原来的编号选项前
  21. 21 cout << " "; //覆盖掉它的">>>"
  22. 22 switch (_getch()) //获取按下的按键的ask2值
  23. 23 {
  24. 24 case 13: //Enter键确定
  25. 25 {
  26. 26 gotoxy(nowx + max + 1, 0);
  27. 27 return nowi; //返回当前选项编号
  28. 28 }break;
  29. 29 case 72: //
  30. 30 {
  31. 31 if (nowi > 1) //在第一个再按上键会到最后一个
  32. 32 --nowi;
  33. 33 else
  34. 34 nowi = max;
  35. 35
  36. 36 }break;
  37. 37 case 80: //
  38. 38 {
  39. 39 if (nowi < max) //在最后一个按下键会到第一个
  40. 40 nowi++;
  41. 41 else
  42. 42 nowi = 1;
  43. 43 }break;
  44. 44 }
  45. 45 gotoxy(nowx + nowi, 0); //移动到目标位置
  46. 46 cout << ">>>";
  47. 47 gotoxy(nowx + max + 1, 0); //记得把光标移动回输出的最后
  48. 48 }
  49. 49 Sleep(50);
  50. 50 }
  51. 51 }

 

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

 

3.测试代码 

 

  1.  

   1 #define _CRT_SECURE_NO_WARNINGS

   2 #include<string>

  1. 3 #include<iostream>
  2. 4 #include<windows.h>
  3. 5 #include<conio.h>
  4. 6 using namespace std;
  5. 7
  6. 8 //光标移动函数, 且在这里把x定义为纵坐标,y为横坐标
  7. 9 void gotoxy(int x, int y)
  8. 10 {
  9. 11 COORD pos = { y,x };
  10. 12 HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); // 获取标准输出设备句柄
  11. 13 SetConsoleCursorPosition(hOut, pos); //两个参数分别是指定哪个窗体,具体位置
  12. 14 }
  13. 15
  14. 16 //获取光标位置。i为0获取x,非零获取y,执行失败返回-1
  15. 17 int lightgetxy(int i)
  16. 18 {
  17. 19 HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
  18. 20 COORD coordScreen = { 0, 0 }; //光标位置
  19. 21 CONSOLE_SCREEN_BUFFER_INFO csbi;
  20. 22
  21. 23 if (GetConsoleScreenBufferInfo(hConsole, &csbi))
  22. 24 {
  23. 25 if (i) // 0获取y,非零获取x
  24. 26 return csbi.dwCursorPosition.X;
  25. 27 else // y
  26. 28 return csbi.dwCursorPosition.Y;
  27. 29 }
  28. 30 else
  29. 31 return -1;
  30. 32 }
  31. 33
  32. 34 //选择函数,返回以contentstr的位置+1
    //max是选项数量,contentstr[]是选项的内容,注意这是个数组,tipstr是在选项前的提示内容
  33. 35 int switchcase(const int max, const string contentstr[], const string tipstr)
  34. 36 {
  35. 37 if (tipstr != "") //判断是否有提示字符串
  36. 38 cout << tipstr << endl;
  37. 39 cout << "<< 请用上下方向键选择..." << endl;
  38. 40 int nowi = 1, nowx = lightgetxy(0) - 1;
  39. 41 //nowi 记录选择的选项编号
  40. 42 cout << ">>> " << contentstr[0] << endl;
  41. 43 for (int i = 2; i <= max; ++i) //先打印选项内容
  42. 44 cout << " " << contentstr[i - 1] << endl;
  43. 45
  44. 46 while (1)
  45. 47 {
  46. 48 while (_kbhit()) //判断是否有按键按下
  47. 49 {
  48. 50 gotoxy(nowx + nowi, 0); //移动到原来的编号选项前
  49. 51 cout << " "; //覆盖掉它的">>>"
  50. 52 switch (_getch()) //获取按下的按键的ask2值
  51. 53 {
  52. 54 case 13: //Enter键确定
  53. 55 {
  54. 56 gotoxy(nowx + max + 1, 0);
  55. 57 return nowi; //返回当前选项编号
  56. 58 }break;
  57. 59 case 72: //
  58. 60 {
  59. 61 if (nowi > 1) //在第一个再按上键会到最后一个
  60. 62 --nowi;
  61. 63 else
  62. 64 nowi = max;
  63. 65
  64. 66 }break;
  65. 67 case 80: //
  66. 68 {
  67. 69 if (nowi < max) //在最后一个按下键会到第一个
  68. 70 nowi++;
  69. 71 else
  70. 72 nowi = 1;
  71. 73 }break;
  72. 74 }
  73. 75 gotoxy(nowx + nowi, 0); //移动到目标位置
  74. 76 cout << ">>>";
  75. 77 gotoxy(nowx + max + 1, 0); //记得把光标移动回输出的最后
  76. 78 }
  77. 79 Sleep(50);
  78. 80 }
  79. 81 }
  80. 82
  81. 83 int main()
  82. 84 {
  83. 85 cout << "歪比巴布占用了这一行" << endl;
  84. 86 cout << "玛卡巴卡占用了这一行" << endl;
  85. 87 cout << "反冲斗士芭芭拉也需要一行" << endl;
  86. 88 string str[] =
  87. 89 {
  88. 90 "自动模式",
  89. 91 "手动模式",
  90. 92 };
  91. 93 cout << "\n<< 您选择了选项" << switchcase(2, str, "<< 您希望以什么模式开始游戏?") << endl;
  92. 94 return 0;
  93. 95 }

 

运行结果:

 

 

注意:在switchcase()函数的最后有gotoxy(nowx + max + 1, 0);

如果不加这个移动,那么在调用这个函数后,你的光标会停留在某一个选项前,

然后你再cout什么东西的话就会在那一行进行覆盖,导致看起来很乱。

 

 

4.其他

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

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

 

coolight大字打印动画:

 

进度条:

原文链接:http://www.cnblogs.com/coolight7/p/14792049.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号