四川招投标网,优化20条措施,看广告收益的正规平台,宝安中心网站建设[导读]本系列博文内容链接如下#xff1a; 【C】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值 【C】做一个飞机空战小游戏(二)——利用getch()函数实现键盘控制单个字符移动 在【C】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值一文中介绍了如何利用… [导读]本系列博文内容链接如下 【C】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值 【C】做一个飞机空战小游戏(二)——利用getch()函数实现键盘控制单个字符移动 在【C】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值一文中介绍了如何利用getch()获得键盘码和各个键盘符号的码值。
今天继续介绍利用wsad键和方向键两种方式实现控制单个字符的移动。 目录
一、第一个小坑
二、通过wsad按键控制单个字符的移动
一字符移动的原理
1、左右移动
2、上下移动
二清空屏幕函数和头文件
三程序代码
1、清屏
2、再调用location()重新显示字符
3、检测按键码值计算字符坐标值
三、通过方向按键控制单个字符的移动
一双码按键获取码值的方法
二实现代码
四、第二个小坑 一、第一个小坑
写程序要循序渐进先实现最基本的功能再不断深化。所以要先编写一个简单程序测试一下getch()函数在键盘上按下代表不同方向的按键然后根据不同的按键在屏幕上输出相应的方向信息模拟控制字符移动的方向。程序的具体目的是当按w键屏幕输出up当按s键屏幕输出down当按a键屏幕输出left当输入d键屏幕输出right。
根据以上想法编写程序代码如下
#include iostream
#include conio.h
using namespace std;int main()
{while(1) //循环等待输入字符 {if(getch()119) //如果输入字符w {coutupendl; //输出字符串up }else if(getch()115) //如果输入字符s {coutdownendl; //输出字符串down}else if(getch()97) //如果输入字符a {coutleftendl; //输出字符串left}else if(getch()100) //如果输入字符d {coutrightendl;//输出字符串right }else //如果输入其他字符{; //无响应 }}return 0;
}先简单测试一下基本的功能结果发现一些问题当每输入一次字符w时屏幕显示一次up这个按键是正常的。
但是当测试其他三个字符时却出现了异常输入字符s时需要按两次键盘才显示一次down需要输入3次a才显示一次left需要输入4次d才显示一次right。
up //按1次w
down //按2次s
left //按3次a
right //按4次d
本程序并没有完全实现按一次键盘就执行一次相应动作的目的。那么问题出在哪里了呢
经过分析发现程序当中if语句的前4个分支其判定条件都是直接调用了getch()函数而if语句执行的顺序是从第一个开始依次判定当找到判定条件为真的那一个if分支时才跳出整个if语句。那么也就是说无论按下了哪个按键程序都需要从第一个if语句分支开始依次进行检测和判断每一个分支都需要调用一次getch()而每次调用getch()都需要有按键按下才能触发。所以在第一个分支中的字符a按一次就能触发而在第二个分支中的字符s需要按2次才能触发在第三个分支中的字符a需要按3次触发在第四个分支的d需要按4次。
问题分析清楚了那么怎么解决呢解决的方案就是另外声明一个变量key_value用来存放每次按下按键利用getch()的值然后在4个if分支中判断key_value的值是否与4个字符的码值相等。调整后的程序如下图所示。
#include iostream
#include conio.h
using namespace std;int main()
{int key_value; //声明存放按键码值的变量 while(1) //循环等待输入字符 {key_valuegetch(); //获取按键码值 if(key_value119) //如果输入字符w {coutupendl; //输出字符串up }else if(key_value115) //如果输入字符s {coutdownendl; //输出字符串down}else if(key_value97) //如果输入字符a {coutleftendl; //输出字符串left}else if(key_value100) //如果输入字符d {coutrightendl;//输出字符串right }else //如果输入其他字符{; //无响应 }}return 0;
}再对以上程序进行测试发现运行正常了4个字符都只需按1次即可输出相应字段了。
up //按1次w
down //按1次s
left //按1次a
right //按1次d
二、通过wsad按键控制单个字符的移动
测试完按键控制的基本程序后就需要继续编写程序实现通过按键来控制图标进行移动的目标了我们还是由最简单的情形开始——图标只由一个特殊字符■组成。
一字符移动的原理
字符移动的原理就是当按键按下后根据按键的码值分辨出要移动的意图计算出字符的新位置用行号和列号的坐标对来表示位置然后将屏幕清空再在新位置上重新显示字符。这样就完成了图标的移动。
1、左右移动
左右移动是通过在字符前增加或者减少空格的数量来实现的。增加空格数量则字符向右移动减少空格的数量则向左移动。
2、上下移动
上下移动是通过增加或减少字符所在行的上一行的换行符数量来实现的增加换行符数量则字符向下移动减少换行符的数量则字符向上移动。
二清空屏幕函数和头文件
清屏函数system(cls)
所需头文件windows.h
三程序代码
程序代码预先自定义了字符定位显示函数location()函数有两个参量xy代表字符列号和行号。在主函数while(1)中循环进行以下操作
1、清屏
2、再调用location()重新显示字符
3、检测按键码值计算字符坐标值
本例通过单码按键来进行控制字符移动。检测是否有按键按下如果w键按下y值减1如果s键按下y值加1如果a键按下x值减1如果d键按下x值加1。
完整代码如下所示。
#include iostream
#include conio.h
using namespace std;void location(int x,int y) //预先定义字符定位显示函数x是列坐标y是行坐标原点(x0,y0)位于屏幕左上角
{int i,j;for(j0;jy;j) //输出y个换行符{coutendl;}for(i0;ix;i) //输出x个空格 {cout ;}cout■; //输出要显示的字符
} int main()
{int key_value; //声明存放按键码值的变量 int x0,y0; //声明字符坐标x代表列值y代表行值 while(1) //循环等待输入字符 {system(cls); //清屏location(x,y); //重新打印字符 key_valuegetch(); //获取按键码值 if(key_value119) //如果输入字符w {y--; //字符上移一行行值y减1if(y0) //限定y值最小值为0{y0;}}else if(key_value115) //如果输入字符s {y; //字符下移一行行值y加1if(y30) //限定y最大值为30{y30;}}else if(key_value97) //如果输入字符a {x--; //字符左移一列列值x减1if(x0){x0; //限定x最小值为0}}else if(key_value100) //如果输入字符d {x; //字符右移一列列值x加1if(x60){x60; //限定x最大值为60}}else //如果输入其他字符{; //无响应 }}return 0;
}三、通过方向按键控制单个字符的移动
以上介绍了使用四个单码按键w、s、a、d来控制字符移动下边再介绍一下如何利用双码按键↑、↓、←、→来进行控制。
一双码按键获取码值的方法
双码按键和单码按键的控制方法只再获取键码的时候有一点区别其他地方完全一样。双码按键的码值有两部分需要调用两次getch()函数来分别获取。
单码按键获取码值的代码
key_valuegetch(); //获取按键码值
双码按键获取码值的代码
key_value1getch(); //获取按键码值1
key_value2getch(); //获取按键码值2
二实现代码
#include iostream
#include conio.h
using namespace std;void location(int x,int y) //预先定义字符定位显示函数x是列坐标y是行坐标原点(x0,y0)位于屏幕左上角
{int i,j;for(j0;jy;j) //输出y个换行符{coutendl;}for(i0;ix;i) //输出x个空格 {cout ;}cout■; //输出要显示的字符
} int main()
{int key_value1,key_value2; //声明存放按键码值的两个变量 int x0,y0; //声明字符坐标x代表列值y代表行值 while(1) //循环等待输入字符 {system(cls); //清屏location(x,y); //重新打印字符 key_value1getch(); //获取按键码值1key_value2getch(); //获取按键码值2 if(key_value1224 key_value272)//如果输入字符↑ {y--; //字符上移一行行值y减1if(y0) //限定y值最小值为0{y0;}}else if(key_value1224 key_value280)//如果输入字符↓ {y; //字符下移一行行值y加1if(y30) //限定y最大值为30{y30;}}else if(key_value1224 key_value275) //如果输入字符← {x--; //字符左移一列列值x减1if(x0){x0; //限定x最小值为0}}else if(key_value1224 key_value277) //如果输入字符→ {x; //字符右移一列列值x加1if(x60){x60; //限定x最大值为60}}else //如果输入其他字符{; //无响应 }}return 0;
}四、第二个小坑
以上两种控制字符移动的代码经测试对于单码按键程序来说如果不小心按了其他单码按键或者双码按键对控制是没有影响的。可是对于双码按键程序来说如果不小心按了一次单码按键再按双码按键进行控制发现无论按哪个控制键无论按多少次图标都不再移动了。
这是因为假如按了一次单码键key_value1获得了码值但是key_value2没有获得码值再次按双码键时会把第一个码值赋值给了上一个key_value2第二个码值赋值给了当前的key_value1而当前的key_value2又未重新赋值还保持原来的值不变。这就相当于每次按下双码键获得的key_value1和key_value正好是相反的。因此控制程序才失效了。
也就是如果游戏再做得复杂些要同时用到单码按键和双码按键程序就会出问题所以程序必须区分出是单码键按下还是双码键按下然后确定出是哪个命令键按下了。
经优化调整后的最终程序如下所示
#include iostream
#include conio.h
using namespace std;void location(int x,int y) //预先定义字符定位显示函数x是列坐标y是行坐标原点(x0,y0)位于屏幕左上角
{int i,j;for(j0;jy;j) //输出y个换行符{coutendl;}for(i0;ix;i) //输出x个空格 {cout ;}cout■; //输出要显示的字符 } int main()
{int key_value1,key_value2; //声明存放按键码值的两个变量bool up_btn_pressfalse,down_btn_pressfalse,left_btn_pressfalse,right_btn_pressfalse;//四个方向键是否按下标志按下为true未按下为false int x0,y0; //声明字符坐标x代表列值y代表行值 while(1) //循环等待输入字符 {system(cls); //清屏location(x,y); //重新打印字符 key_value1getch(); //获取按键码值1if(key_value1224){key_value2getch();switch(key_value2){case 72:up_btn_presstrue; //置↑按下 标志 break;case 80:down_btn_presstrue;//置↓按下 标志break;case 75:left_btn_presstrue;//置←按下 标志break;case 77:right_btn_presstrue;//置→按下 标志break;}} if(up_btn_press)//如果输入字符↑ {y--; //字符上移一行行值y减1if(y0) //限定y值最小值为0{y0;}up_btn_pressfalse;}else if(down_btn_press)//如果输入字符↓ {y; //字符下移一行行值y加1if(y30) //限定y最大值为30{y30;}down_btn_pressfalse;}else if(left_btn_press) //如果输入字符← {x--; //字符左移一列列值x减1if(x0){x0; //限定x最小值为0}left_btn_pressfalse;}else if(right_btn_press) //如果输入字符→ {x; //字符右移一列列值x加1if(x60){x60; //限定x最大值为60}right_btn_pressfalse;}else //如果输入其他字符{; //无响应 }}return 0;
}