问题描述:
使用*在控制台打印平行四边形
例如:平行四边形中最长的一行输出的*是5个,则平行四边为:
*
**
***
****
*****
****
***
**
*
方法1:
把平行四边形分成上下两个部分,循环打印。
参考代码:
#include<stdio.h>
int main()
{
int nStarNumber, i, j;
printf("输入平行四边形最长的那一行*的个数: ");
scanf_s("%d", &nStarNumber);
if (nStarNumber <= 1)
{
printf("为了能看出是个平行四边形,请保证最长的那一行*的个数大于1\n");
return 0;
}
for (i = 1; i <= nStarNumber; i++)
{
for (j = 1; j <= i; j++) //控制上半部分的*输出
printf("* ");
printf("\n");
}
for (i = 1; i <= nStarNumber - 1; i++)
{
for (j = 1; j <= 2 * i; j++)//控制下半部分的空格输出
printf(" ");
for (j = nStarNumber - i; j > 0; j--) //控制上半部分的*输出
printf("* ");
printf("\n");
}
return 0;
}
方法2:
根据平行四边形的性质,求出边框的范围,然后输出内部的所有点。
参考代码:
#include<stdio.h>
int main()
{
int nStarNumber, i, j, k, mini, maxi;
printf("输入平行四边形最长的那一行*的个数: ");
scanf_s("%d", &nStarNumber);
if (nStarNumber <= 1)
{
printf("为了能看出是个平行四边形,请保证最长的那一行*的个数大于1\n");
return 0;
}
nStarNumber--;//建立直角坐标系,下标从0开始
for (i = 0; i <= 2 * nStarNumber; i++)//行数
{
maxi = 0; mini = nStarNumber;
for (j = 0; j <= nStarNumber; j++)
{
if ((i >= 0 && i <= nStarNumber && j == 0) ||
(i >= nStarNumber && i <= 2 * nStarNumber && j == nStarNumber) ||
(i == j && i >= 0 && i <= nStarNumber) ||
(i - j == nStarNumber && i >= nStarNumber && i <= 2 * nStarNumber))
{
if (j < mini)
mini = j;
if (j > maxi)
maxi = j;
}
}
for (k = 0; k < mini; k++)
printf(" ");
for (k = mini; k <= maxi; k++)
printf("*");
printf("\n");
}
return 0;
}
方法3:
分别写两个函数判断当前点是否位于平行四边形上和平行四边形内部,判断位于平行四边形内部的方法思路参看代码注释。
参考代码:
#include<stdio.h>
#define MINI(a, b) (a < b ? a : b)
#define MAXI(a, b) (a > b ? a : b)
typedef struct POINT
{
int x;
int y;
}POINT;
int IsPointInPolygon(POINT pt, POINT p1, POINT p2, POINT p3, POINT p4)
{
//判断某个点是否在多边形内部(不包括边上),如果是返回1,否则返回0
//这种方法比方法2要通用,可以使用任意凸多边形
//有个地方需要注意一下:参数传递点的时候,需要按照依次连接四边形的点来给
//思路:以当前点像x轴做平行线,判断和四变形有几个交点,如果交点为奇数在内部,为偶数在外部
if (pt.x == 4 && pt.y == 3)
{
int zzz = 0;
}
POINT arr[] = { {p1.x, p1.y},{p2.x, p2.y}, {p3.x, p3.y}, {p4.x, p4.y} };
int nPointCount = sizeof(arr) / sizeof(arr[0]);
int nCrossCount = 0, i;
for (i = 0; i < nPointCount; i++)
{
POINT startPt = arr[i];
POINT endPt = arr[(i + 1) % nPointCount];
if (startPt. y == endPt. y)
continue;
if (pt.y < MINI(startPt.y, endPt.y) && pt.y > MAXI(startPt.y, endPt.y))
continue;
double x = (double)(pt.y - startPt.y) * (double)(endPt.x - startPt.x) / (double)(endPt.y - startPt.y) + startPt.x;
if (x > pt.x)
nCrossCount++;
}
//交点个数为奇数则在多边形内部
return nCrossCount % 2 == 1;
}
int IsOnEdge(int i, int j, int nStarNumber)
{
if ((i >= 0 && i <= nStarNumber && j == 0) ||
(i >= nStarNumber && i <= 2 * nStarNumber && j == nStarNumber) ||
(i == j && i >= 0 && i <= nStarNumber) ||
(i - j == nStarNumber && i >= nStarNumber && i <= 2 * nStarNumber))
return 1;
return 0;
}
int main()
{
int nStarNumber, i, j;
POINT p1, p2, p3, p4, curPt;
printf("输入平行四边形最长的那一行*的个数: ");
scanf_s("%d", &nStarNumber);
if (nStarNumber <= 1)
{
printf("为了能看出是个平行四边形,请保证最长的那一行*的个数大于1\n");
return 0;
}
nStarNumber--;//建立直角坐标系,下标从0开始
p1.x = 0; p1.y = 0;
p2.x = nStarNumber; p2.y = 0;
p3.x = 2 * nStarNumber; p3.y = nStarNumber;
p4.x = nStarNumber; p4.y = nStarNumber;
for (i = 0; i <= 2 * nStarNumber; i++)//行数
{
for (j = 0; j <= nStarNumber; j++)
{
curPt.x = i;
curPt.y = j;
if (IsOnEdge(i, j, nStarNumber) || IsPointInPolygon(curPt, p1, p2, p3, p4))
printf("*");
else
printf(" ");
}
printf("\n");
}
return 0;
}
方法4:
通过4条直线的方程,锁定区域的范围
参考代码:
#include<stdio.h>
int main()
{//思路:通过直线锁定区域范围
int nStarNumber, i, j;
printf("输入平行四边形最长的那一行*的个数: ");
scanf_s("%d", &nStarNumber);
if (nStarNumber <= 1)
{
printf("为了能看出是个平行四边形,请保证最长的那一行*的个数大于1\n");
return 0;
}
nStarNumber--;//建立直角坐标系,下标从0开始
for (i = 0; i <= 2 * nStarNumber; i++)//行数
{
for (j = 0; j <= nStarNumber; j++)
{
if (i >= j && j <= nStarNumber && j >= 0 && j >= i - nStarNumber)
printf("*");
else
printf(" ");
}
printf("\n");
}
return 0;
}
运行结果: