(图书介绍:童晶:《C和C++游戏趣味编程》新书预告)
这学期的线下C语言课程,大一同学们学完旋转蛇案例后(童晶:第4章 旋转蛇(《C和C++游戏趣味编程》配套教学视频)),布置了一次错觉图片生成实验的PBL,给了大家5天时间分组完成代码、ppt报告。
这次,介绍王翌骏、陈凯、马学强同学实现的正方形错觉。由于同学们学习C语言刚一个月,还没有正式学习数组、函数等语法知识,因此代码可能不够完善。以下提供了分步骤的实现思路、代码,大家可以参考。
首先是同学们调研的目标效果:
斜向方块的边看起来是弧线,实际上是直线,受黑白条纹影响产生是弧线边的错觉。
STEP 1:划出线
●利用函数在不同两点间划出直线
●代码行数(不算变量的定义)10
●难度:较简单
●PS:其实这线画出来对于最后的效果没有影响,但可以用来作为判断第二步骤的标准
STEP 2:画出大背景
●利用solidrectangle以及判断和循环来做出
●代码行数:约70行
●难度:一般,但是繁琐,需要大量的循环判断。
STEP 3:挖空中间部分
●利用clearpolygon函数进行清除
●代码行数:约十行
●难度:简单(简单的循环,但是所用到新的函数以及数据类型POINT,通过easy_x查询)
STEP 4:画出中间部分
●利用坐标,想逃循环判断画出中间部分的
●代码行数:约45行
●难度:困难(尝试多次未果,因为直接用函数确定范围会十分复杂,但我在easyx上看到了setorigin函数用来定义原点,这样在菱形中的函数是一样的,省去了很多麻烦 )
STEP5:结合
将第四步和第三步结合,便得到了错觉图形
#include<stdio.h>
#include<graphics.h>
#include<conio.h>
int main()
{
int site_x, site_y;
int screen_x, screen_y;
int length = 160;
int width = 8;
int left,top;
int count1, count2;
int x = 1, y = 1, t = 1,k;
screen_x = 640, screen_y = 640;
initgraph(screen_x, screen_y);
cleardevice();
for (t;t < 8;t++)//输出直线
{
if (t <= 4)
{
line(0, 160 * t - 80, 160 * t - 80, 0);
line(0, 160 * t - 80, 720 - 160*t , 640);
line(720 - 160 * t, 640, 640, 720 - 160 * t);
line(640, 720 - 160 * t, 160 * t - 80, 0);
}
}
for (y = 1;y <= 4;y++)
{
for (x=1;x <= 40;x++)
{
if (y % 2 != 0)
{
if (x <= 10)//第一个方块以及向下平移
{
left = 16 * x - 8;
top = length * (y - 1);
fillrectangle(left, top, left + width, top+length);
}
if (x > 10 && x <= 20)//第二个
{
left = 160;
top = 16 * (x - 11)+ length * (y - 1);
fillrectangle(left, top, left + length, top + width);
}
if (x <= 30 && x > 20)//第三个
{
left = 16 * x - 16;
top = top = length * (y - 1);
fillrectangle(left, top, left + width, top+length);
}
if (x > 30)//第四个
{
left = 480;
top = 16 * (x - 31)+8 + length * (y - 1);
fillrectangle(left, top, left + length, top + width);
}
}
else
{
if(x<=10)
{
left = 0;
top = length * (y - 1) + 8+16*(x-1);
fillrectangle(left,top,left+length,top+width);
}
if(x > 10 && x <= 20)
{
left = 160 +16* (x - 11);
top=length*(y-1);
fillrectangle(left, top, left + width, top + length);
}
if(x <= 30 && x > 20)
{
top = length * (y - 1) + 16 * (x - 21);
left = 320;
fillrectangle(left, top, left + length, top + width);;
}
if(x > 30)
{
top = length*(y-1);
left = 480 + 8 + 16 * (x - 31);
fillrectangle(left, top, left + width, top + length); ;
}
}
}
}
int r = 80;//清除中间部分
for (x = 80; x <= 560; x = x + 160)
{
for (y = 80; y <= 560; y = y + 160)
{
POINT pts[] = { {x, y - r}, {x - r,y}, {x, y + r},{x + r,y} };
clearpolygon(pts, 4);
}
}
for (count1 = 1;count1 <= 4;count1++)//重新绘制内部图形
{
for (count2 = 1;count2 <= 4;count2++)
{
setorigin(80 + 160 * (count1 - 1), 80 + 160 * (count2 - 1));
for (x = -80;x <= 80;x++)
{
for (y = -80; y <= 80;y++)
{
for (k = 1;k <= 10;k++)
{
if ((x + y <= 80) && (x + y >= -80) && (y - x <= 80) && (y - x >= -80))
{
if ((count1 + count2) % 2 == 0)
{
if (count1 == 1 || count1 == 4)
if (x > -80 + 16 * (k - 1) && x <= 16 * (k - 1) - 72)
putpixel(x, y, WHITE);
else
;
else if (count1 == 2 || count1 == 3)
if (x > -72 + 16 * (k - 1) && x <= 16 * (k - 1) - 64)
putpixel(x, y, WHITE);
}
else
{
if (count1 == 1 || count1 == 4)
if (y >= -80 + 16 * (k - 1) && y <= 16 * (k - 1) - 72)
putpixel(x, y, WHITE);
else
;
if (count1 == 2 || count1 == 3)
if (y >= -72 + 16 * (k - 1) && y <= 16 * (k - 1) - 64)
putpixel(x, y, WHITE);
}
}
}
}
}
}
}
_getch();
return 0;
}
感想
1:分步骤逐一解决,有目的性地去写代码是不二法门
2:看起来很难完成的步骤,需要查找相关的资料以及运用一些数学思维
3:团队协作统筹很重要