版权所有:无缰之马chhuach(优快云和博客源),转载请注明出处,谢谢!
一 题目描述
去哪儿网一面的编程题,还挺有意思的,面试官打开笔记本电脑。h----------m----------l中h、m、l左右来回震荡。看了看屏幕和面试官交流了下,发现以下规律和要求:
1)其中h速度最快,一个时间间隔走一步;m速度其次,2个时间间隔走一步;l速度最慢,3个时间间隔走一步;
2)时间间隔为100ms;
3)字符串总长度(包括h、m、l)为23;
4)起始位置,h位于最左端,m位于中间,l位于最右端;
5)起始时,h、m、l都是向右走的。
二 思路
1) 如何在同一行反复重绘?
cout<<endl是回车换行,就到下一行。起始cout<<’\r’;输出回车即可,回车表示光标移到行首,换行表示另取一行。因此字符串末尾只输出回车即可回到同一行的行首。
2)100ms的时间间隔怎么获得?
最简单的当然就是延时啊,当然不太准啊。还可以用多线程常用的Sleep()函数,单线程中让主线程睡眠,不就是延时等待吗?
3) 如何实现h、m、l的动态移动效果?
看过电视剧、电影的同学都知道,所谓的动态效果其实是图片一副副的连续播放。这个效果也同样适用。把每一种状态当车一副图片,图片的连续循环播放就有了所要求的效果。(本文的设计方案就是每隔一个时间间隔(可直接调用windows.h中的Sleep(100)),按要求有规律地更新字符串“h----------m----------l” 中h、m、l的位置,并在同一行cout出来)
三 编程实现
#include <iostream>
#include <Windows.h>
#include <string>
using namespace std;
class print_hml
{
private:
int count;//时间间隔的计数
string my_str;//表示要循环打印的字符串
bool hflag;//表示h移动方向,0表示向右,1表示向左,下同
bool mflag;
bool lflag;
int hpos; //表示h在字符串中的位置,下同
int mpos;
int lpos;
public:
print_hml(int cnt,string str)//构造函数
{
count=cnt;
my_str=str;
hpos=str.find('h');
mpos=str.find('m');
lpos=str.find('l');
hflag=mflag=0;//to right;
lflag=1;//to left
}
void print_update(char a,int step,bool &flag,int &pos)//对h、m、l的位置进行更新,a是待更新的字符,step表示多少间隔更新一次
{
if (count%step==0) //flag表示更新的方向向左or向右,pos表示上一次字符a的位置。
{
my_str[pos]='-';
if (!flag) //to right
{
++pos;
my_str[pos]=a;
if (pos==22)
{
flag=1;
}
}
else //to left
{
--pos;
my_str[pos]=a;
if (pos==0)
{
flag=0;
}
}
}
}
void print_all()
{
Sleep(100);
count++;
if (count==0x7fffffff)
{
count=0;
}
print_update('l',3,lflag,lpos);//先更新l、再更新m,然后更新h----h可以覆盖m,m可以覆盖l。
print_update('m',2,mflag,mpos);
print_update('h',1,hflag,hpos);
cout<<" "<<my_str<<'\r';
}
};
int main()
{
print_hml test(0,"h----------m----------l") ;
while (1)
{
test.print_all();
}
return 0 ;
}
四 效果和总结
因为是动态效果,无法完全展示,现仅用图片说明:
总结:以上代码,可以从通用性和复用性上进行抽象,可把时间间隔的具体数值、h、m、l的位置,以及字符的个数等抽象出来,将一个字符的基本运动作为基本类,提高扩展的灵活性。