这里说到的两个内容差不多都可以用在控制台上运行的一些小游戏里,控制某一部分的字体颜色和背景色以达到高亮显示强调的效果,这个选择菜单就是通过方向键或者自定义按键然后进行选项的选择。
比较简单,但是挺好玩的,就随便看看吧。
修改控制台的前景色和背景色
这里直接调用系统的函数,system(“color ef”);
,即可实现,这个代码就是在控制台调用color
指令,可以通过在控制台运行color …
或者在代码中直接插入system(“color …”);
,他就会输出有关这个指令的相关信息,包括每个数字表示什么颜色。
有两点需要注意的,一点是color
后面跟的数是两位十六进制,分别表示前景色和背景色,第二点需要注意的是,这里修改的是全局设置,也就是说调用一次之后,整个控制台都会发生改变,而并不是针对某一位置或者某一段字符进行设置,如果像针对某一个字符串进行设置,看下面。
printf彩色输出
是通过控制台的转义序列来实现的,这是文本模式下的系统显示功能,似乎和语言没有太大联系。转义序列是以ESC
开始的,即\033
,ESC
的十进制是27,转为八进制就是33了。
通用格式大致为ESC[{attr1};{attr2};…;{attrn}m
,其中attr表示的是属性,也是属性值,通常直接就是数字表示了。在此我们进行三个常用属性的设置,主要是显示方式、字体颜色和背景色。
显示方式
- 0(默认值)
- 1(高亮显示,顺便加粗?不确定)
- 2(暗淡)
- 22(非粗体,不确定)
- 4(下划线)
- 5(闪烁,但是我没看出有什么效果。。)
- 25(非闪烁)
- 7(反显,我也没看出效果)
- 27(非反显)
- 8(隐藏)
字体颜色
- 30(黑色)
- 31(红色)
- 32(绿色)
- 33(黄色)
- 34(蓝色)
- 35(品红)
- 36(青色)
- 37(白色)
背景色
- 40(黑色)
- 41(红色)
- 42(绿色)
- 43(黄色)
- 44(蓝色)
- 45(品红)
- 46(青色)
- 47(白色)
大致使用的示例代码如下
printf("\033[4;31;42m 输出红色绿背景下划线字符 \033[0m");
这里我写了个函数可以直接拿来用,我写的比较啰嗦,你可以去把它优化一下,后面两个设置为NoneType的话就是默认显示方式而且结尾没有换行符或者回车。
#define HighLight 1
#define Underline 4
#define Spark 5
#define Contrary 7
#define Miss 8
#define NONETYPE 0
#define PTab 11
#define PEnter 12
...
void print(char *Message, char *ForeColor, char *BackgroundColor, int flag,int End) {
//参数分别为输出的信息,字体颜色,背景色,显示方式和结尾标志
char ColorArray[8][10] = { "black","red","green","yellow","blue","purple","deepgreen","white" };
int ForeNum, BackgroundNum;
for (int i = 0; i < 8; i++) {
if (strcmp(ColorArray[i], ForeColor) == 0)
ForeNum = i;
else if (strcmp(ColorArray[i], BackgroundColor) == 0)
BackgroundNum = i;
}
if (End == NONETYPE) {
if (flag==NONETYPE)
printf("\033[%d;%dm%s\033[0m",40+BackgroundNum,30+ForeNum,Message);
else
printf("\033[%dm\033[%d;%dm%s\033[0m",flag, 40 + BackgroundNum, 30 + ForeNum,Message);
}
else if (End == PTab) {
if (flag == NONETYPE)
printf("\033[%d;%dm%s\033[0m\t", 40 + BackgroundNum, 30 + ForeNum, Message);
else
printf("\033[%dm\033[%d;%dm%s\033[0m\t", flag, 40 + BackgroundNum, 30 + ForeNum,Message);
}
else if (End == PEnter) {
if (flag == NONETYPE)
printf("\033[%d;%dm%s\033[0m\n", 40 + BackgroundNum, 30 + ForeNum, Message);
else
printf("\033[%dm\033[%d;%dm%s\033[0m\n", flag, 40 + BackgroundNum, 30 + ForeNum,Message);
}
}
控制台菜单选择的实现
这个的灵感是来自控制台的文字游戏,如果总是让用户去输入字符或者数字来进行选项的选择的话,肯定会有些繁琐而且不太顺手,就萌生了一个简单的菜单的制作。
在此我选择的是利用方向键进行选项的选择,横向放置的菜单,纵向当然也很容易就改了,使用getch()
获取字符,这个函数的特点是,不需要回车,而且也不会有字符的回显,非常适合进行游戏的输入。
首先需要知道使用getch()
函数得到的是什么,这个函数返回值可以认为是接收到字符的ascii码,但是做一个小测试就会发现,其实并不是得到的值就可以直接用,看下面
while (1) {
ch = getch();
printf("%d\t%c\n", ch,ch);
}
其实他是有一个输入的,但是我觉得他是在我后面还多获取了一个表示结束的东西吧,所以他第二次循环的时候默认就读取了这个,ascii码值为0,如果把printf
换成putchar
就可以正常显示字符了,因为0不会被认为是可显示的字符。
因此在获取输入的时候需要进行判断其是否为0,可以使用if (ch=getch())
,也可以while (ch=getch())
。
之后就要说一下,在读取方向键的时候,第一次并不会返回正常的值,有第地方说可能是0或者224,我这里测试是第一个返回值为-32,这也能解释当上一步使用getch()
读取方向键的时候,如果输出ascii码会发现输出为?-32
,因为第一个返回值为-32。需要使用两次该函数才可以成功获取到方向键,如下所示
while (1) {
if (c1 = getch()) {
c2 = getch();
}
printf("%d\t%d\n", c1, c2);
}
测试数据分别是a、A、↑、↓、←、→、E,可以发现,字符的第二个返回值都默认是0,方向键的第一个返回值都是-32,因此可以获取两次,根据两个返回值的不同判断读取的是字符还是方向键。
这是已经实现的简单的菜单选择方式,别忘了#include <Windows.h>
,这里实现了gotoxy()
。
#include <Windows.h>
...
#define UpKey 35
#define DownKey 43
#define LeftKey 38
#define RightKey 40
...
void gotoxy(int x, int y) {
COORD pos = { x,y };
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOut, pos);
}
int main() {
char str[5][10] = { "菜单1","菜单2","菜单3","菜单4","菜单5" };
int Number = 5;
int Chosen = 0;
char c1 = 'a', c2 = 'a',ch='a';
printf("请选择:");
while (ch != 'q') {
gotoxy(10, 0);
for (int i = 0; i < Number; i++) {
if (Chosen == i)
print(str[i], "white", "black", Underline, PTab);
else
printf("%s\t", str[i]);
}
if (c1 = getch()) {
c2 = getch();
}
//判断按键
if (c1 > 0)
ch = c1;
else
ch = c2-37;
switch (ch) {
case UpKey:printf("上\n"); break;
case DownKey:printf("下\n"); break;
case LeftKey:
if (Chosen > 0)
Chosen--;
break;
case RightKey:
if (Chosen < Number-1)
Chosen++;
break;
default:printf("字符:%c\n", ch); break;
}
}
return 0;
}
效果如下图所示
实现方式就是设置一个选择标记,每次利用gotoxy
定位到文本位置,进行输出,即覆盖了原来的输出,根据选择标记对当前选中的选项进行高亮标记,我这里用的是下划线,也可以改成利用不同的字体颜色或者背景色进行高亮,比较简单。
今天就先到这吧,有点晚了,等改天再写写利用前缀显示的选择菜单的样子。