打印菱形

曾经是老师上课出的一道题,当天给了老师一个答案之后,老师说还有更好的解,于是又给了一个答案之后,还说有更好的解,于是上网学习,又搞出了各种解,算是学习了降低循环次数的一些基本方法吧,记录一下

题目:用单重循环打印菱形,要求,输入k,打印k层菱形

1、解法零

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int k,n,i,j,l,a;
    while(scanf("%d",&k),k)   //输入数字k,可多次输入
    {
        n=1+2*(k-1);          //k其实是没有意义的,用k求出n,即整个图形所需的二维点阵列个数
        k=0;                    //置k初始值为0
        while(k<n*n)           //单程循环,0到n*n-1
        {
            i=k/n>(n-1)/2 ? (n-1-k/n) : k/n;    //判断当前点所在行数(超过半数的行数是没有意义的,这里相当于进行了一个模处理)
            j=k%n;                               //判断当前点所在列数
            a=1+i*2;                             //通过当前行数求的当前行的*的个数
            l=(n-a)/2;                          //如果列数满足当前行应该输出*的条件则输出*
            if((l-1)<j && j<(n-l))
                printf("*");                   //否则输出‘ ’
            else
                printf(" ");
            if(j==(n-1))                       //换行控制
                printf("\n");
            ++k;                        //计数器加1
        }
    }
    return 0;
}

解法一:

//单循环输出菱形
#include <stdio.h>
#include <string>
using namespace std;
int   main()
{
        /*
        变量:
        n:接收菱形编号
        i:循环计数器
        m: 最长一行的星号个数
        */
        int n,i,m;
        while(scanf("%d",&n),n)
        {
            //通过菱形编号获得菱形最长一行星号数
            m=n-1+n%2;
            string s(m,'*');
            //输出菱形,通过所在行和最长星号数的计算获得改行输出位置与输出星号个数
            for(i=1;i<=n;i++)
                printf("%*.*s\n",i<=(m+1)/2?i+(m+1)/2:(n+1-i)+(m+1)/2,i<=(m+1)/2?2*(i-1)+1:(n-i)*2+1,s.c_str());
        }
        return 0;
}

解法二:

#include<stdio.h>
int main()
{
    /*
    变量声明
    i:单行循环计数器
    j:每行应输出星号加空格个数
    k:每行应输出空格个数
    n:输入菱形编号
    m:最大边长
    flag:菱形中点的控制
    */
    int i,j,n,m,k;
    int flag;
    while(scanf("%d",&n),n)
    {
        m=n-1+n%2;
        j=(m+1)/2;
        k=j-1;
        i=1;
        flag=0;
        for(;i<=j;i++)
        {
            //输出处理,如果i在k和j之间,输出星号,否则输出空格
            if(k<i)
                printf("*");
            else
                printf(" ");
            //换行处理,如果i==j,则换行,并将行计数器i清0
            if(i==j)
            {
                printf("\n");
                i=0;
                if(j==m)
                    flag++;
                /*
                转折控制,第一个if情况说明在菱形上半部分,行元素总数j增加,空格数k减少
                后两种if情况说明在菱形下半部分,行元素总数j减少,空格数k增加
                */
                if(flag==0)
                {
                    j++;
                    k--;
                }
                if(flag==1 && n%2)
                {
                    j--;
                    k++;
                }
                if(flag==2)
                {
                    j--;
                    k++;
                }
                //退出控制
                if(!(j>k))
                    break;
            }
        }
    }
    return 0;
}

解法三:(把循环全换成递归。。。。)

#include<stdio.h>
#include<stdlib.h>
#include<string>
using namespace std;
int n,m;
/*
行控制函数
输出菱形函数
参数:count:星号个数,pos星号位置(右对齐)
*/
void role_contrl_work( int count, int pos)
{
    if(pos==0)
    {
        printf("\n");
        return;
    }
  if(pos>count)
    printf(" ");
  else
    printf("*");
  role_contrl_work(count,pos-1);
}
/*
列控制函数
输出菱形函数
参数:count:星号个数,pos星号位置(右对齐)
*/
void line_contrl_work(int count,int pos)
{
    if(count==m)
    {
        role_contrl_work(count,pos);
        if(!(n%2))
            role_contrl_work(count,pos);
        return;
    }
    role_contrl_work(count,pos);
    line_contrl_work(count+2,pos+1);
    role_contrl_work(count,pos);
}
/*
主函数
*/
int main()
{
    while(scanf("%d",&n),n)
    {
        m=n-1+n%2;
        line_contrl_work(1,(m+1)/2);
    }
    return 0;
}