# Hello World 旋轉

## 前置
### 1.打開vscode

### 2.開啟任意資料夾

### 3.點擊信任

### 4.創建檔案test.c(檔名隨意)

## 詳細步驟
### 1.先寫出基礎的Hello, World!
```c
int main() {
printf("Hello, World!");
return 0;
}
```
記得按CTRL+S儲存檔案之後再點擊右上方的執行


然後你會發現報錯了,因為系統不知道`printf`是什麼
所以我們要加上一個函式庫`<stdio.h>`(標準輸入輸出)
```c
#include <stdio.h>
int main() {
printf("Hello, World!");
return 0;
}
```
:::warning
:warning: `return 0` 表示程式結束,有時候不加不會報錯,但加了一定不會錯
:::
### 2.開始寫各種函式
為了程式碼的簡潔,如果是會多次使用到的「同一段程式邏輯」,就會寫成函式。(`printf`也是一個函式)
* 隱藏游標的函式
為了讓輸出畫面沒有多餘的游標
```c
#include <windows.h>
void hideCursor() {
CONSOLE_CURSOR_INFO cursorInfo;
GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursorInfo);
cursorInfo.bVisible = FALSE;
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursorInfo);
}
```
* 清除畫面的函式
每一次的閃爍其實都是清除畫面再輸出內容,避免和上一次重疊或干擾
```c
#include <stdlib.h>
void clearScreen() {
system("cls");
}
```
* 繪製旋轉的文字
這裡就是統一用來計算旋轉弧度以及輸出文字的函式
```c
void drawRotatedText(char* text, int centerX, int centerY, int angle) {
int len = strlen(text); // 計算文字長度
double radian = angle * 3.14159 / 180.0; // 將角度轉換為弧度
// 逐個字元計算旋轉後的位置並顯示
for (int i = 0; i < len; i++) {
// 計算每個字元相對於中心點的偏移量
// 讓字串的幾何中心作為旋轉中心
double charOffset = (double)i - (double)(len - 1) / 2.0;
// 增加字元間距,讓每個字元都有足夠的空間顯示
double spacing = 1.5; // 字元間距係數
// 使用三角函數計算旋轉後的座標
int x = centerX + (int)(charOffset * spacing * cos(radian));
int y = centerY + (int)(charOffset * spacing * sin(radian));
// 確保座標在螢幕範圍內(80x25 控制台)
if (x >= 0 && x < 80 && y >= 0 && y < 25) {
gotoxy(x, y); // 移動游標到計算後的位置
printf("%c", text[i]); // 顯示原始字元
}
}
}
```
### 3.最後主程式的樣子
```c
int main() {
char message[] = "Hello World"; // 要顯示的訊息
int angle = 0; // 初始旋轉角度
int centerX = 40; // 螢幕中心 X 座標(80/2)
int centerY = 12; // 螢幕中心 Y 座標(25/2)
hideCursor(); // 隱藏游標
// 無限迴圈,持續顯示旋轉動畫
while (1) {
clearScreen(); // 清除螢幕
drawRotatedText(message, centerX, centerY, angle); // 繪製旋轉文字
angle = (angle + 5) % 360; // 每次增加 5 度
Sleep(50); // 暫停 50 毫秒
}
return 0; // 程式結束
}
```
::: spoiler 完整code
```c=
// 標準輸入輸出函式庫
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#ifdef _WIN32
#include <windows.h>
#define CLEAR_SCREEN() system("cls")
#define SLEEP_MS(ms) Sleep(ms)
static void gotoxy(int x, int y) {
COORD c; c.X = (SHORT)x; c.Y = (SHORT)y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
}
static void hideCursor(void) {
CONSOLE_CURSOR_INFO ci;
GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &ci);
ci.bVisible = FALSE;
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &ci);
}
static void showCursor(void) {
CONSOLE_CURSOR_INFO ci;
GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &ci);
ci.bVisible = TRUE;
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &ci);
}
#else
#include <unistd.h>
#define CLEAR_SCREEN() printf("\x1b[2J\x1b[H") /* 清屏 + 游標回到左上 */
#define SLEEP_MS(ms) usleep((ms) * 1000)
static void gotoxy(int x, int y) {
/* ANSI 座標從 1 開始,且先列(行/y)後行(列/x) */
printf("\x1b[%d;%dH", y + 1, x + 1);
fflush(stdout);
}
static void hideCursor(void) { printf("\x1b[?25l"); fflush(stdout); }
static void showCursor(void) { printf("\x1b[?25h"); fflush(stdout); }
#endif
/* 清除螢幕(包一層方便呼叫) */
static void clearScreen(void) { CLEAR_SCREEN(); }
/* 繪製旋轉的文字 */
static void drawRotatedText(const char* text, int centerX, int centerY, int angle) {
int len = (int)strlen(text);
double rad = angle * 3.14159265358979323846 / 180.0;
for (int i = 0; i < len; i++) {
double charOffset = (double)i - (double)(len - 1) / 2.0;
double spacing = 1.5;
int x = centerX + (int)(charOffset * spacing * cos(rad));
int y = centerY + (int)(charOffset * spacing * sin(rad));
/* 簡單限制在 80x25,若要自動讀取終端大小可再加強 */
if (x >= 0 && x < 80 && y >= 0 && y < 25) {
gotoxy(x, y);
putchar(text[i]);
}
}
fflush(stdout);
}
int main(void) {
const char* message = "Hello World";
int angle = 0;
int centerX = 40; /* 80/2 */
int centerY = 12; /* 25/2 */
hideCursor();
while (1) {
clearScreen();
drawRotatedText(message, centerX, centerY, angle);
angle = (angle + 5) % 360;
SLEEP_MS(50);
}
showCursor();
return 0;
}
```
:::