#edu017. 第 3 节 利用顺序、循环、分支绘图
第 3 节 利用顺序、循环、分支绘图
本节利用顺序、循环、分支控制画笔绘制图形,快速高效掌握顺序、循环、分支三种基本结构。
pen.fd(length)
可以控制画笔前进 单位,pen.rt(angel)
控制画笔右转 度,画笔经过的地方就会留下线条,“前进100 - 右转90度”做 次就可以绘制一个正方形。
那么程序就很容易实现:
int main()
{
pen.fd(100); //C/C++中";"是语句结束标志
pen.rt(90);
pen.fd(100);
pen.rt(90);
pen.fd(100);
pen.rt(90);
pen.fd(100);
pen.rt(90);
return 0;
}
同理,绘制正 边形,控制画笔”前进-右转“ 次就可以了,只不过右转角度为 度(注意画笔旋转是正 边形的外角,正 边形外角为:).但是重复次数过多,这种方式就无能为力了(比如重复十万次),最好就是利用循环。
C++ 中最简单的循环控制方式就是 while()
, 中就是条件,条件成立执行循环体,条件不成立,跳出循环,执行过程如下图:

while循环
循环体是单个语句:

循环体是单个语句
循环体是多个语句,多个语句用大括号括起来,构成一个整体,想一想如果去掉大括号会怎么样?:

循环体是多个语句
while(true)
条件始终为真,循环就会一直执行下去,执行后可以绘制出正 边形,但是程序无法停止;我们可以利用 显示画笔, 降低画笔速度,可以清晰看到画笔一直“前进-右转”。
int main()
{
pen.show(); //显示画笔
pen.speed(5); //括号中填1-10,数字越大画笔越快
while(true)
{
pen.fd(100);
pen.rt(90);
}
return 0;
}
如何精准的控制循环进行 次?
如果有一个计数器,记录循环次数,那么就可以精准控制循环次数了,能够存储数字的计数器在程序设计中就是变量,如何得到一个变量了?
“数据类型 变量名” 就是定义变量的格式,例如定义了一个名字为 的变量: int i;
有了变量,让变量记录循环的次数,就可以精准控制循环次数了。首先,让变量有一个明确的初值,例如 ,循环体执行 次,变量增大 ,循环体执行 次后,变量 就为 ,需要跳出循环,那么循环条件就为 , 对应关键代码就为:
int i=1;
while(i<=4)
{
pen.fd(100);
pen.rt(90);
i=i+1; //'='是赋值运算符,后面表达式的值赋给前面的变量i
}
想一想:记录变量 为什么需要给初值,初值一定要赋值为 吗?
例1:绘制一个周长为 1000 的正 边形。
【分析】:我们可以定义一个变量 ,存储边数,定义变量 控制循环次数,循环 次,那么变量 从 开始,循环到 ,循环条件就为 . 右转角度就为 ,周长为 1000 ,那么边长就为 ,程序如下:
int n=8; //n存储边数
int i=1;
while(i<=n) //循环条件为i<=n
{
pen.fd(1000/n);
pen.rt(360/n); //正n变形的外角为 180-(n-2)*180/n=360/n
i=i+1;
}
如果可以从键盘输入数据,就可以直接从键盘上输入边数到变量 中,从而避免每次都修改源程序。可以使用 cin>>n
从键盘上输入一个数值到变量 n 中, cout<<n
将变量 n 输出来。
输入: cin>>n;
输出: cout<<n;
int n;
cin>>n; //边数从键盘上输入
int i=1;
while(i<=n)
{
pen.fd(1000/n);
pen.rt(360/n);
i=i+1;
}
输入不同的整数 ,有的时候正 变形不闭合,例如当输入 , 时绘制的正 边形如下图:

当n=13时不闭合
为何会出现无法闭合的情况?可以多输入几组数据,就会发现问题出在 处,当输入的能够整除正变形是闭合的,否则不闭合。
运行 cout<<5/2;
发现输出结果为 ,并不是 ,发现此处发生的是整除运算。
在 中参与运算都是 型整数时,中间计算都会按照 类型处理,结果只会保留整数,也就是进行了向下取整(实际是向零取整),这种整除运算很有用,会在后面很多时候用到。
知道了“参与运算都是整数,中间结果也按照整数处理”原理后,我们只需要将参与运算的对象改变类型就可以解决问题,例如 cout<<5.0/2;
输出结果为 2.5, 那么就可以修改程序如下:
int main()
{
pen.show(); //显示画笔
pen.speed(5); //括号中填1-10,数字越大画笔越快
int n; //n存储边数
cin>>n; //边数从键盘上输入
int i=1;
while(i<=n) //循环条件为i<=n
{
pen.fd(1000.0/n);
pen.rt(360.0/n); //正8变形的外角为 180-(n-2)*180/n=360/n
i=i+1;
}
pen.hide(); //隐藏画笔
return 0;
}
当输入的值比较大时,例如输入,正边形接近一个圆形,利用计算机模拟出“正边形,越大,就越接近圆形”,体会小学生微元法求圆形面积的过程。
例2:绘制一个周长为 1000 的彩色的正 n 边形
分析:利用 ,可以改变画笔的颜色,循环时可以将循环控制变量 作为颜色参数,但是参赛范围 至 ,当参数 超过了范围将会是默认的颜色,可以有多种方法解决这个问题:
**方法一:**利用 条件判断,再定义一个单独表示颜色的变量,每循环一次变量自增 ,当大于 时,将这个表示颜色的变量强制改为 ,重新开始计数。
语句的执行过程如下图:

if 逻辑过程
单语句情况:

if 单语句
多个语句情况:

if 多语句
想一想:多语句情况,去掉大括号会怎样?
参考代码如下:
int n;
cin>>n;
int i=1;
int col=0; //变量col表示颜色编号
while(i<=n)
{
pen.color(col);
col=col+1;
if(col>15)col=0;
pen.fd(1000.0/n);
pen.rt(360.0/n);
i=i+1;
}
方法二: 颜色编号的范围是 ,可以利用取余数的方法,控制变量 取 的余数,那么如何进行取余了?可以利用之前的整除获得余数。
整数 除以整数 ,商 ,余数为 ,存在等式: ,可以得到余数 ,那么 取 的余数就等于 。
当然 里面有直接求余数的运算符 ,也可以直接 。
方法三: 利用随机数取余,获得随机颜色, 函数可以产生一个 到 之间的整数值。不过默认 随机种子相同,多次运行会产生相同的随机数序列,可以利用 修改随机种子以产生不同的随机数序列。
注: 和 出自于库 stdlib.h
, 出自于库 time.h
,返回值是从 年 月 日至今所经历的时间(以秒为单位)。
参考代码如下:
int n;
cin>>n;
int i=1;
srand(time(0)); //改变随机种子
while(i<=n)
{
pen.color(rand()%16); //利用随机数改变边的颜色
pen.fd(1000.0/n);
pen.rt(360.0/n);
i=i+1;
}
例3:绘制 n 个正 n 边形
: 个正 变形围绕原点均匀分布;
: 个正 变形在一个圆上均匀分布;
: 利用 循环实现以上程序;
分析:在例2中,利用 循环和变量绘制了一个正 边形,如果这个过程重复 次,那就可以再套一重循环,循环 次;但是如果绘制完一个正 边形,如果在原始位置绘制第二个,两个正 边形会重合在一起,对于 绘制完第一个正 变形,让画笔旋转一个角度 ,然后绘制第二个,就可以让 个正 边形围绕原点均匀分布。对于 ,可以让画笔先往前移动一段距离,然后再绘制,绘制结束后,让画笔后退相同距离,这样正 变形就分布在圆周上,前进后退不留下痕迹,可以使用 抬笔,绘制正 边形再落笔 。
参考代码如下:
int n;
cin>>n;
int i=1;
while(i<=n)
{
int j=1;
while(j<=n)
{
pen.color(j%16);
pen.fd(1000.0/n).rt(360.0/n);
j=j+1;
}
pen.rt(360.0/n);
i=i+1;
}
对于 读者可自行尝试,参考代码见附件。
对于 控制循环,有 个地方很关键:
(1) int i=1; 控制变量起点;
(2) 循环条件 i<=n ;
(3) i=i+1 控制变量自增;
这三点控制着整个循环开始、结束、中间变化过程,但是当程序比较复杂,对于 循环阅读起来很繁琐, 可以将上述三点合在一起,使得程序更加简洁。
循环 次 循环的写法 for(int i=1;i<=n;i=i+1)
循环体 , 基本在执行过程如下:

for循环执行过程
参考程序如下:
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
pen.color(j%16);
pen.fd(1000.0/n).rt(360.0/n);
}
pen.rt(360.0/n);
}
**思考:**绘制 个正 边形,画笔前进了多少次?
附: 参考代码:
int main()
{
int n;
cin>>n;
int i=1;
while(i<=n)
{
pen.up();
pen.fd(100);
pen.down();
int j=1;
while(j<=n)
{
pen.color(j%16);
pen.fd(1000.0/n).rt(360.0/n);
j=j+1;
}
pen.up();
pen.bk(100);
pen.rt(360.0/n);
i=i+1;
}
return 0;
}