软件工程专业在读,,收到了老师的作业 qwq
第一次碰算法题以外的东西,,有点有趣诶 (๑Ő௰Ő๑)
就是让做一个这种菜单:
<img src="https://s1.ax1x.com/2020/10/15/0TO3kT.png" width="500px">
敲一下回车是这样子:
<img src = "https://s1.ax1x.com/2020/10/15/0TXTVx.png" width = "500px" >
看上去不是很难的亚子,,get 到键盘输入的时候,直接清屏再输出新的菜单样子即可,,
getch()
会获取键盘事件并返回按键的 ASCII 码值,,按下方向键需要读两次,第一次是 - 32 (224)(八位存储,正负区别在有无符号 qwq) 第二次对应向上 80, 向下 72 。
随手写了一下伪代码:
i = 1 //行数
print //输出菜单1
while (1)
char op = getch();
if (op == -32) //方向键
char op1 = getch(); //获取方向
if (op1 == 80)
i++;
//记得控制 i 范围
else if (op1 == 72)
同上
system("cls");
switch (i)
输出对应菜单
if (op == 13) //回车
system("cls");
if (i == 4) //选择了退出
break;
else
输出“选择了i”,按回车返回
while (getch() == 13)
switch (i)
输出对应菜单
break;
好像这样就完事了的说 (๑°3°๑)
不过 "输出对应菜单" 那个地方好像要把那个长长的菜单复 制 四 次 _(:з」∠)_
这样写起来根本不优雅啊喂 (ノ =Д=) ノ
破案:被同学用辣 —— 么长的宏 搞掉了需要复制四次的问题 %%%
咱就稍微找了找,好像有个控制光标位置的东西,,
那岂不是就可以拆成两块了欸嘿嘿,,
- 输出菜单(不含 '>'‘)
- 在指定位置输出 '>' 符号
有个 Windows API 中定义的结构体类型 COORD 表示字符在控制台屏幕上的坐标
typedef struct_COORD | |
{ | |
SHORT X; // 水平坐标(第几列) | |
SHORT Y; // 垂直坐标(第几行) | |
} COORD; |
再加上一堆 Windows API 函数,就能搞这个了:
void Cur_Print(int p) // 改变光标位置,输出 '>',p 表示在 '>' 在菜单的第行 | |
{ | |
int x = 13, y = 3; | |
y += p; | |
COORD pos = {x, y}; | |
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE); // 获取标识设备的句柄(看不懂呜呜呜.. | |
SetConsoleCursorPosition(hOutput, pos); // 定位光标位置 | |
printf("\b>"); | |
} |
光标一直在闪,好难受,隐藏掉:
void Hide_Cursor() // 隐藏光标闪烁 | |
{ | |
HANDLE Handle = GetStdHandle(STD_OUTPUT_HANDLE); | |
CONSOLE_CURSOR_INFO CursorInfo; | |
GetConsoleCursorInfo(Handle, &CursorInfo); // 获取控制台光标信息 | |
CursorInfo.bVisible = 0; // 不可见 | |
SetConsoleCursorInfo(Handle, &CursorInfo); // 设置控制台光标状态 | |
} |
加上一堆魔改,,就搞出来了。。虽然还是百行。。不过看上去优雅多啦 (´▽`) ノ♪
初次体验使用系统 API 诶,,
code: (血的教训以后一定要加注释 orz)
#include <stdio.h> | |
#include <stdlib.h> | |
#include <windows.h> | |
#include <conio.h> | |
#include <time.h> | |
void Menu_Print() // 打印没 '>' 的菜单框框 | |
{ | |
puts("*********************************************\n* *\n* 游标式屏幕菜单示例 *\n* *\n* 菜单项一 *\n* 菜单项二 *\n* 菜单项三 *\n* 退出 *\n* *\n*********************************************\n按上下方向键改变选择的菜单项,按回车键执行选择的功能...:\n"); | |
} | |
void Cur_Print(int p) // 改变光标位置,输出 '>' | |
{ | |
int x = 13, y = 3; | |
y += p; | |
COORD pos = {x, y}; | |
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE); | |
SetConsoleCursorPosition(hOutput, pos); | |
printf("\b>"); | |
} | |
void Hide_Cursor() // 隐藏光标闪烁 | |
{ | |
HANDLE Handle = GetStdHandle(STD_OUTPUT_HANDLE); | |
CONSOLE_CURSOR_INFO CursorInfo; | |
GetConsoleCursorInfo(Handle, &CursorInfo); | |
CursorInfo.bVisible = 0; | |
SetConsoleCursorInfo(Handle, &CursorInfo); | |
} | |
void Result_Print(int x) | |
{ | |
system("cls"); | |
if (x == 1) | |
printf("选择了第1项菜单,按回车键返回...\n"); | |
else if (x == 2) | |
printf("选择了第2项菜单,按回车键返回...\n"); | |
else if (x == 3) | |
printf("选择了第3项菜单,按回车键返回...\n"); | |
else | |
exit(0); | |
} | |
void Enter_() | |
{ | |
while (1) | |
{ | |
if (kbhit()) | |
{ | |
char op1 = getch(); | |
if (op1 == 13) | |
return; | |
} | |
Sleep(200); | |
} | |
} | |
void Cur_Process(int move) // 处理光标移动 | |
{ | |
static int Pos = 1; | |
if (move == 233) | |
{ | |
Result_Print(Pos); | |
Enter_(); | |
return; | |
} | |
Pos += move; | |
if (Pos <= 0) // 保证范围在 1 至 4 | |
Pos = 4; | |
if (Pos >= 5) | |
Pos = 1; | |
Cur_Print(Pos); | |
} | |
void Update() // 持续获取键盘信息,更新地图 | |
{ | |
while (1) | |
{ | |
if (kbhit()) | |
{ | |
char op1 = getch(); | |
if (op1 == 13) | |
{ | |
Cur_Process(233); | |
system("cls"); | |
Menu_Print(); | |
Cur_Process(0); | |
continue; | |
} | |
char op = getch(); | |
system("cls"); | |
Menu_Print(); | |
if (op == 72) | |
Cur_Process(-1); | |
else if (op == 80) | |
Cur_Process(1); | |
else | |
Cur_Process(0); | |
} | |
Sleep(200); | |
} | |
} | |
int main() | |
{ | |
Menu_Print(); | |
Cur_Print(1); //'>' 位置初始化为 1 | |
Hide_Cursor(); | |
Update(); | |
return 0; | |
} |