打印沙漏
题目
顾名思义,就是要输出一个沙漏
,那么什么是沙漏呢,就是下面的样子了
*****
***
*
***
*****
也就是要给我们n个*
,这个沙漏每一行的 符号 数量都是奇数,因此是有规律的。
输入例子
19 //多少个符号 *
输出例子
//打印出一个沙漏
*****
***
*
***
*****
2 //剩余没有用掉的符号数量
解题思路
这个解题思路是我在网上看到的,他把这个沙漏 具像化,*号用坐标来显示,那么上面的例子就是
(0,0)(0,1)(0,2)(0,3)(0,4)
(1,1)(1,2)(1,3)
(2,2)
(3,1)(3,2)(3,3)
(4,0)(4,1)(4,2)(4,3)(4,4)
这样的话,继续观察一下,发现他可以上下对折,左右对折变成下面这样
(0,0)(0,1)(0,2)
(1,1)(1,2)
(2,2)
发现了什么,列 >= 行,然后接下来左右对称,上下对称
当 行坐标 > 行数 / 2 也就是过半的时候, 这时的行坐标 = 总行数 - 当前行数 - 1,比如下一行 行坐标 3 = 5 - 3 -1 = 1 所以 行坐标 3 的行和行坐标 1 的行对称。
列也是一样 因为列数 = 行数 所以
当 列坐标 > 行数 / 2 也就是过半的时候, 这时的列坐标 = 总行数 - 当前列数 - 1,比如下一列 列坐标 3 = 5 - 3 - 1 = 1 所以列坐标 3 的列和列坐标 1 的列对称。
当然了,中间那一行(列)没有对称
代码
下面是 我用 php
实现的代码,任何语言都大同小异。
<?php
function test($count, $symbol)
{
$maxRow = 1; //最大行 即 最小行
$maxCount = 1; //最大个数 即 最小个数
//先判断 数量 如果是小于 最小个数 那么输出 数量
if ($count < $maxCount) {
printf($count);
} else {
//循环 算出 最大行数 统计最大个数 后面用来算剩余个数
while (true) {
//可以输出
//下一行的数量 = 之前的数量 + 下一行所需的数量((行数 + 2) 是下一行的数量,但是沙漏需要上下两行,所以 * 2)
$nextCount = ($maxRow + 2) * 2 + $maxCount;
//判断不够了 结束
if ($count < $nextCount) {
break;
} elseif ($count == $nextCount) {
//刚好够 数量增加 行增加
$maxRow += 2;
$maxCount = $nextCount;
break;
} else {
//完全够 数量增加 行增加 然后继续循环
$maxRow += 2;
$maxCount = $nextCount;
}
}
//开始输出
for ($i = 0; $i < $maxRow; $i++) {
//循环所有行
$row = $i; //当前行
//判断 当前行 到一半了,那么把行数倒过来,让它向上跑
if ($i > $maxRow / 2) {
$row = $maxRow - $row - 1;
}
for ($j = 0; $j < $maxRow; $j++) {
//循环所有列
$col = $j;
//列和行一样 做个判断
if ($col > $maxRow / 2) {
$col = $maxRow - $col - 1;
}
//如果 当前列 < 当前行
if ($col < $row) {
//如果 到了 最后 就要换行 在 前面 则输出 空格
if ($j > $maxRow / 2) {
printf("\n");
break;
} else {
printf(" ");
}
} else {
//列 > 行 直接输出 符号
printf($symbol);
}
//输出完 最后一个符号后 换行 当列 = 最后一行的时候
if ($j == $maxRow - 1) {
printf("\n");
}
}
}
//输出 剩余的 符号数量
printf($count - $maxCount);
}
}
参考资料
我只是略作更改,最小使用1个*,和一些变量使用上的微调 下面原文c语言的链接
https://blog.csdn.net/hcy2319964421/article/details/53103641