[Lập trình C] In tam giác ngôi sao

Saturday, January 27, 2024
Edit this post


Tiếp theo chuỗi bài tập kỹ thuật lập trình cơ bản là một bài tập vô cùng kinh điển mà hầu như bất cứ ai khi học lập trình đều phải làm, đó là in các tam giác ngôi sao (hay còn gọi là kim tự tháp). Cũng tương tự như các bài tập khác, chúng ta sẽ cùng giải dạng cơ bản trước khi đến với dạng nâng cao của đề bài. Với bài tập này, bạn sẽ nắm được cách sử dụng kết hợp giữa vòng lặp và câu lệnh điều kiện.

Dạng cơ bản

Đề bài: Nhập vào n, in ra tam giác cân bằng các ký tự * có độ cao n như các ví dụ bên dưới:

n=2
  *  
* * * 

n=3
    *     
  * * *   
* * * * *

n=4
      *       
    * * *     
  * * * * *   
* * * * * * *

n=5
        *         
      * * *       
    * * * * *     
  * * * * * * *   
* * * * * * * * *

n=6
          *           
        * * *         
      * * * * *       
    * * * * * * *     
  * * * * * * * * *   
* * * * * * * * * * *

n=7
            *             
          * * *           
        * * * * *         
      * * * * * * *       
    * * * * * * * * *     
  * * * * * * * * * * *   
* * * * * * * * * * * * *

Bây giờ, hãy cùng lấy giấy phút ra phân tích trên giấy cách một tam giác được tạo ra như thế nào. Một khi đã nắm được quy luật, chúng ta có thể dễ dàng chuyển hóa thành mã lệnh để máy tính có thể vẽ ra được hình theo mong muốn của chúng ta.

Dễ thấy n chính là độ cao (hay còn gọi là số hàng rows) của tam giác, còn độ dài cạnh đáy (hay số cột columns - cols) được tính bằng công thức cols = n * 2 - 1. Ví dụ khi n = 5 thì rows=5 và cols=9.

Bây giờ, cần xác định với mỗi dòng được in ra, làm sao biết được ở vị trí nào sẽ in ra dấu * và vị trí nào sẽ in ra khoảng trắng? Hãy thử vẽ hình ra trên giấy như bên dưới cho trường hợp n=5.
- Với hàng row=0, những vị trí in ra dấu * là: 4
- Với hàng row=1, những vị trí in ra dấu * là: 3, 4, 5
- Với hàng row=2, những vị trí in ra dấu * là: 2, 3, 4, 5, 6
- Với hàng row=3, những vị trí in ra dấu * là: 1, 2, 3, 4, 5, 6, 7
- Với hàng row=4, những vị trí in ra dấu * là: 0, 1, 2, 3, 4, 5, 6, 7, 8


Nếu chịu khó suy luận, chúng ta sẽ nhận thấy những vị trí in ra dấu sao luôn nằm trong khoảng [n-1-row, n-1+row], những vị trí còn lại sẽ được in ra khoảng trắng. Đến đây thì chúng ta đã có đủ dữ kiện để bắt đầu viết code như sau:

#include <stdio.h>

int main()
{
    int n;
    printf("n=");
    scanf("%d", &n);
    
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n*2-1; j++) {
            if (j >= n-1-i && j <= n-1+i)
                printf("* ");
            else
                printf("  ");
        }
        printf("\n");
    }

    return 0;
}

Đoạn code trên đã có thể chạy ổn. Tuy nhiên, nhìn vẫn còn hơi dài dòng, hãy áp dụng toán tử 3 ngôi (ternary operator) để đoạn code được gọn gàng hơn nhé:

#include <stdio.h>

int main()
{
    int n;
    printf("n=");
    scanf("%d", &n);
    
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n*2-1; j++) {
            printf(j >= n-1-i && j <= n-1+i ? "* " : "  ");
        }
        printf("\n");
    }

    return 0;
}

Dạng nâng cao

Và bây giờ chúng ta hãy cùng tăng độ khó của bài tập lên một chút. Vẫn là in ra tam giác theo độ cao đầu vào n, nhưng lần này tam giác được in ra sẽ là tam giác rỗng.

n=3
    *     
  *   *   
* * * * *

n=5
        *         
      *   *       
    *       *     
  *           *   
* * * * * * * * *

n=7
            *             
          *   *           
        *       *         
      *           *       
    *               *     
  *                   *   
* * * * * * * * * * * * *

Với dạng nâng cao này, chúng ta chỉ cần dựa trên dạng thông thường, suy luận thêm một chút là sẽ có được cách giải như sau. Tôi sẽ không đi sâu vào giải thích, các bạn hãy tự nghiền ngẫm và tự code trước khi xem bài giải nhé.

#include <stdio.h>

int main()
{
    int n;
    printf("n=");
    scanf("%d", &n);
    
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n*2-1; j++) {
            if (i < n-1)
                printf(j == n-1-i || j == n-1+i ? "* " : "  ");
            else
                printf("* ");
        }
        printf("\n");
    }
    return 0;
}

Kết luận

Những cách giải trên đây có thể chưa phải là những cách làm tốt nhất (best practices), tuy nhiên, tôi hy vọng chúng sẽ giúp bạn có được những ý tưởng ban đầu nhằm bổ trợ và phát triển cho những cách làm tốt hơn. Chúc các bạn thành công!

.
Xin vui lòng chờ đợi
Dữ liệu bài viết đang được tải về

© Copyright by CUỘC SỐNG TỐI GIẢN
Loading...