創意控制臺:下雨動畫特效(ASCII 雨滴下落)

在編程的世界里,控制臺不僅僅是輸出文本信息的工具,通過巧妙的代碼設計,我們還能在其中創造出充滿趣味的動態畫面。本文將帶領大家使用 C 語言打造一個創意控制臺下雨動畫特效,利用 ASCII 字符模擬雨滴下落的過程,為單調的控制臺增添一份靈動與趣味。

一、實現思路

實現控制臺下雨動畫特效,主要圍繞以下幾個核心步驟展開:

  1. 定義雨滴狀態:使用結構體來存儲每一滴雨滴的位置、下落速度等信息,方便后續對雨滴進行管理和更新。
  2. 初始化雨滴:在程序開始時,隨機生成一定數量的雨滴,并為它們設置初始位置和下落速度。
  3. 繪制雨滴:根據雨滴的當前狀態,在控制臺相應位置輸出表示雨滴的 ASCII 字符,呈現雨滴下落的視覺效果。
  4. 更新雨滴狀態:不斷改變雨滴的位置,模擬下落過程。當雨滴到達控制臺底部時,重新設置其位置,實現循環下落的效果。
  5. 控制動畫節奏:通過設置合適的時間間隔,控制雨滴下落的速度和動畫的流暢度,讓下雨效果更加逼真。

二、代碼實現詳解

1. 引入頭文件

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>  // 用于Windows系統控制臺操作
  • stdio.h:提供標準輸入輸出函數,如printf用于在控制臺輸出雨滴。
  • stdlib.h:包含內存分配、隨機數生成等函數,用于初始化雨滴狀態和動態內存管理。
  • time.h:用于獲取系統時間,作為隨機數種子,使每次運行程序時雨滴的初始狀態不同。
  • windows.h:在 Windows 系統下,用于控制臺相關操作,如設置光標位置、清屏等。若在 Linux 或 macOS 系統,需使用其他函數實現類似功能,后續會進行說明。

2. 定義雨滴結構體

#define WIDTH 80  // 控制臺寬度
#define HEIGHT 25 // 控制臺高度
#define NUM_RAIN 100 // 雨滴數量typedef struct {int x;  // 雨滴x坐標int y;  // 雨滴y坐標int speed; // 雨滴下落速度
} Raindrop;
  • 定義了WIDTHHEIGHT常量,分別表示控制臺的寬度和高度,方便控制雨滴的顯示范圍。
  • NUM_RAIN常量指定了雨滴的總數。
  • Raindrop結構體用于存儲每一滴雨滴的信息,包括在控制臺中的x坐標、y坐標以及下落速度。

3. 初始化雨滴函數

void init_raindrops(Raindrop raindrops[]) {srand(time(NULL));for (int i = 0; i < NUM_RAIN; i++) {raindrops[i].x = rand() % WIDTH;raindrops[i].y = 0;raindrops[i].speed = rand() % 3 + 1;  // 速度范圍1 - 3}
}

  • init_raindrops函數接受一個Raindrop類型的數組作為參數。
  • 使用time(NULL)作為隨機數種子,確保每次運行程序時雨滴的初始位置和速度都不相同。
  • 通過循環為每一滴雨滴隨機生成在控制臺寬度范圍內的x坐標,初始y坐標設為 0(從控制臺頂部開始下落),并隨機賦予 1 到 3 之間的速度。

4. 繪制雨滴函數

void draw_raindrops(Raindrop raindrops[]) {COORD pos;  // 用于設置光標位置HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);  // 獲取控制臺句柄system("cls");  // 清屏for (int i = 0; i < NUM_RAIN; i++) {pos.X = raindrops[i].x;pos.Y = raindrops[i].y;SetConsoleCursorPosition(hConsole, pos);  // 設置光標位置printf("|");  // 輸出雨滴}
}

  • draw_raindrops函數用于在控制臺繪制雨滴。
  • 通過GetStdHandle(STD_OUTPUT_HANDLE)獲取控制臺句柄,使用system("cls")清屏,清除上一幀的雨滴。
  • 遍歷雨滴數組,利用SetConsoleCursorPosition函數設置光標的位置到每一滴雨滴對應的坐標處,然后輸出|字符模擬雨滴。

5. 更新雨滴狀態函數

void update_raindrops(Raindrop raindrops[]) {for (int i = 0; i < NUM_RAIN; i++) {raindrops[i].y += raindrops[i].speed;if (raindrops[i].y >= HEIGHT) {raindrops[i].y = 0;raindrops[i].x = rand() % WIDTH;}}
}
  • update_raindrops函數用于更新每一滴雨滴的狀態。
  • 通過循環,根據每滴雨滴的速度增加其y坐標,模擬下落過程。
  • 當雨滴的y坐標超出控制臺高度時,將其y坐標重新設為 0(回到頂部),并隨機生成新的x坐標,實現雨滴循環下落的效果。

6. 主函數

int main() {Raindrop raindrops[NUM_RAIN];init_raindrops(raindrops);while (1) {draw_raindrops(raindrops);update_raindrops(raindrops);Sleep(50);  // 控制動畫速度,單位毫秒}return 0;
}
  • main函數中,首先定義了一個Raindrop類型的數組raindrops,用于存儲所有雨滴的信息。
  • 調用init_raindrops函數初始化雨滴。
  • 通過一個無限循環,不斷調用draw_raindrops函數繪制雨滴,調用update_raindrops函數更新雨滴狀態,并使用Sleep(50)函數控制每次循環的時間間隔為 50 毫秒,從而控制動畫的速度,使下雨效果更加自然流暢。

7. Linux 或 macOS 系統適配

如果要在 Linux 或 macOS 系統上運行該程序,需要對與 Windows 控制臺操作相關的代碼進行修改。

  • 清屏操作:將system("cls")替換為system("clear")
  • 設置光標位置:在 Linux 或 macOS 系統中,可以使用 ANSI 轉義序列來設置光標位置,定義如下函數:
#include <unistd.h>void set_cursor_position(int x, int y) {printf("\033[%d;%dH", y, x);
}

然后將draw_raindrops函數中設置光標位置的部分修改為:

void draw_raindrops(Raindrop raindrops[]) {system("clear");  // 清屏for (int i = 0; i < NUM_RAIN; i++) {set_cursor_position(raindrops[i].x, raindrops[i].y);printf("|");  // 輸出雨滴}
}

同時,由于 Linux 和 macOS 系統中沒有Sleep函數,需要使用usleep函數(單位為微秒)來控制動畫速度,將Sleep(50)修改為usleep(50000)(50 毫秒 = 50000 微秒)。

三、完整代碼

Windows 系統版本

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>#define WIDTH 80
#define HEIGHT 25
#define NUM_RAIN 100typedef struct {int x;int y;int speed;
} Raindrop;void init_raindrops(Raindrop raindrops[]);
void draw_raindrops(Raindrop raindrops[]);
void update_raindrops(Raindrop raindrops[]);void init_raindrops(Raindrop raindrops[]) {srand(time(NULL));for (int i = 0; i < NUM_RAIN; i++) {raindrops[i].x = rand() % WIDTH;raindrops[i].y = 0;raindrops[i].speed = rand() % 3 + 1;}
}void draw_raindrops(Raindrop raindrops[]) {COORD pos;HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);system("cls");for (int i = 0; i < NUM_RAIN; i++) {pos.X = raindrops[i].x;pos.Y = raindrops[i].y;SetConsoleCursorPosition(hConsole, pos);printf("|");}
}void update_raindrops(Raindrop raindrops[]) {for (int i = 0; i < NUM_RAIN; i++) {raindrops[i].y += raindrops[i].speed;if (raindrops[i].y >= HEIGHT) {raindrops[i].y = 0;raindrops[i].x = rand() % WIDTH;}}
}int main() {Raindrop raindrops[NUM_RAIN];init_raindrops(raindrops);while (1) {draw_raindrops(raindrops);update_raindrops(raindrops);Sleep(50);}return 0;
}

Linux 或 macOS 系統版本

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>#define WIDTH 80
#define HEIGHT 25
#define NUM_RAIN 100typedef struct {int x;int y;int speed;
} Raindrop;void init_raindrops(Raindrop raindrops[]);
void draw_raindrops(Raindrop raindrops[]);
void update_raindrops(Raindrop raindrops[]);
void set_cursor_position(int x, int y);void init_raindrops(Raindrop raindrops[]) {srand(time(NULL));for (int i = 0; i < NUM_RAIN; i++) {raindrops[i].x = rand() % WIDTH;raindrops[i].y = 0;raindrops[i].speed = rand() % 3 + 1;}
}void set_cursor_position(int x, int y) {printf("\033[%d;%dH", y, x);
}void draw_raindrops(Raindrop raindrops[]) {system("clear");for (int i = 0; i < NUM_RAIN; i++) {set_cursor_position(raindrops[i].x, raindrops[i].y);printf("|");}
}void update_raindrops(Raindrop raindrops[]) {for (int i = 0; i < NUM_RAIN; i++) {raindrops[i].y += raindrops[i].speed;if (raindrops[i].y >= HEIGHT) {raindrops[i].y = 0;raindrops[i].x = rand() % WIDTH;}}
}int main() {Raindrop raindrops[NUM_RAIN];init_raindrops(raindrops);while (1) {draw_raindrops(raindrops);update_raindrops(raindrops);usleep(50000);}return 0;
}

將上述對應系統的代碼保存為.c文件(如rain_animation.c),使用gcc編譯器進行編譯。例如在命令行中輸入gcc rain_animation.c -o rain_animation,生成可執行文件后運行,就能在控制臺欣賞到精彩的下雨動畫特效了。通過這個項目,我們不僅掌握了 C 語言在控制臺動畫方面的應用,還了解了不同操作系統下控制臺操作的差異,為今后更多創意編程項目打下堅實基礎。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/78266.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/78266.shtml
英文地址,請注明出處:http://en.pswp.cn/web/78266.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

MySQL--索引入門

MySQL官方對索引的定義為&#xff1a;索引&#xff08;Index&#xff09;是幫助MySQL高效獲取數據的數據結構。 Mysql在存儲數據之外&#xff0c;數據庫系統各種還維護著滿足特定查找算法的數據結構&#xff0c;這些數據結構以某種引用&#xff08;指向&#xff09;表中的數據…

MIT XV6 - 1.2 Lab: Xv6 and Unix utilities - pingpong

接上文 MIT XV6 - 1.1 Lab: Xv6 and Unix utilities - user/_sleep 是什么&#xff1f;做什么&#xff1f; pingpong 不務正業了那么久(然而并沒有&#xff0c;雖然還在探索sleep&#xff0c;但是教材我已經看完了前三章了)&#xff0c;讓我們趕緊繼續下去 在進行本實驗之前請務…

前端面經-VUE3篇(二)--vue3組件知識(一)組件注冊、props 與 emits、透傳、插槽(Slot)

組件允許我們將 UI 劃分為獨立的、可重用的部分&#xff0c;并且可以對每個部分進行單獨的思考。在實際應用中&#xff0c;組件常常被組織成一個層層嵌套的樹狀結構&#xff1a; 一、注冊 Vue 組件本質上是一個可以復用的 自定義 HTML 元素&#xff0c;為了在其他組件中使用一…

LeetCode —— 102. 二叉樹的層序遍歷

&#x1f636;?&#x1f32b;?&#x1f636;?&#x1f32b;?&#x1f636;?&#x1f32b;?&#x1f636;?&#x1f32b;?Take your time ! &#x1f636;?&#x1f32b;?&#x1f636;?&#x1f32b;?&#x1f636;?&#x1f32b;?&#x1f636;?&#x1f32b;?…

Linux第20節 --- inode和文件系統

一、沒有被打開的文件 如果一個文件沒有被打開&#xff0c;那么該文件存儲在哪里&#xff1f; 該文件是存儲在磁盤當中的&#xff01; 文件 文件內容 文件屬性&#xff01; 文件的內容是按照數據塊存儲的&#xff1b;文件的屬性其實就是inode&#xff08;是一個128字節的…

1.PowerBi保姆級安裝教程

1.進入power bi網站 PowerBi下載鏈接 2.下載power bi軟件 3.雙擊安裝 4.下一步 5.下一步 6.下一步 7.下一步 8.安裝 9.雙擊桌面圖標

Android Studio中OpenCV應用詳解:圖像處理、顏色對比與OCR識別

文章目錄 一、OpenCV在Android中的集成與配置1.1 OpenCV簡介1.2 在Android Studio中集成OpenCV1.2.1 通過Gradle依賴集成1.2.2 通過模塊方式集成1.2.3 初始化OpenCV 1.3 OpenCV基礎類介紹 二、指定區域圖像抓取與對比2.1 圖像抓取基礎2.2 指定區域圖像抓取實現2.2.1 從Bitmap中…

前端面試每日三題 - Day 22

今天我們將深入探討 JavaScript 中的 Set 和 Map 數據結構&#xff0c;了解它們的特性及應用場景。接下來&#xff0c;我們會分析 React 的 Suspense 和 Concurrent Mode 的工作原理&#xff0c;探索它們如何提升應用的性能和用戶體驗。最后&#xff0c;我們將學習如何設計一個…

[Vue]編程式導航

在 Vue 中&#xff0c;編程式導航是通過 JavaScript 代碼&#xff08;而非 <router-link> 標簽&#xff09;動態控制路由跳轉的核心方式。這個方法依賴于 Vue Router 提供的 API&#xff0c;能更靈活地處理復雜場景&#xff08;如異步操作、條件跳轉等&#xff09;。 一、…

鄒曉輝教授十余年前關于圍棋程序與融智學的思考,體現了對復雜系統本質的深刻洞察,其觀點在人工智能發展歷程中具有前瞻性意義。我們可以從以下三個維度進行深入解析:

鄒曉輝教授十余年前關于圍棋程序與融智學的思考&#xff0c;體現了對復雜系統本質的深刻洞察&#xff0c;其觀點在人工智能發展歷程中具有前瞻性意義。我們可以從以下三個維度進行深入解析&#xff1a; 一、圍棋程序的二元解構&#xff1a;數據結構與算法的辯證關系 1.1.形式…

The Traitor King (10 player 25 player)

The Traitor King 十字軍試煉尾王成就。叛變的國王&#xff1a;在30秒內殺死40只蟲群甲蟲。考驗團隊配合的成就。比不朽者&#xff0c;黑曜石31等等強度大&#xff0c;甚至感覺比寶庫地風火難。

數據結構一 單鏈表

1.單鏈表 1.數據結構簡介 程序數據結構算法 數據 數據&#xff08;data&#xff09;是客觀事物的一個符號表示 數據元素&#xff08;data element&#xff09;是數據的基本單位&#xff0c;一 個數據元素可以由若干個數據項&#xff08;data item&#xff09;組成。數據項…

GPU集群監控系統開發實錄:基于Prometheus+Grafana的算力利用率可視化方案

一、科研場景下的GPU監控痛點 在深度學習模型訓練、分子動力學模擬等科研場景中&#xff0c;GPU集群的算力利用率直接影響著科研效率。筆者在參與某高校計算中心的運維工作時&#xff0c;發現以下典型問題&#xff1a; 資源黑洞現象&#xff1a;多課題組共享GPU時出現"搶…

【計算機視覺】三維重建: MVSNet:基于深度學習的多視圖立體視覺重建框架

MVSNet&#xff1a;基于深度學習的多視圖立體視覺重建框架 技術架構與核心算法1. 算法流程2. 關鍵創新 環境配置與實戰指南硬件要求安裝步驟數據準備&#xff08;DTU數據集&#xff09; 實戰流程1. 模型訓練2. 深度圖推斷3. 點云生成 常見問題與解決方案1. CUDA內存不足2. 特征…

智能家居的OneNet云平臺

一、聲明 該項目只需要創建一個產品&#xff0c;然后這個產品里面包含幾個設備&#xff0c;而不是直接創建幾個產品 注意&#xff1a;傳輸數據使用到了不同的power&#xff0c;還有一定要手機先聯網才能使用云平臺 二、OneNet云平臺創建 &#xff08;1&#xff09;Temperatur…

aidermacs開源程序使用 Aider 在 Emacs 中進行 AI 配對編程

一、軟件介紹 文末提供程序和源碼下載 Aidermacs 通過集成 Aider&#xff08;最強大的開源 AI 配對編程工具之一&#xff09;為 Emacs 帶來了 AI 驅動的開發。如果您缺少 Cursor&#xff0c;但更喜歡生活在 Emacs 中&#xff0c;Aidermacs 提供了類似的 AI 功能&#xff0c;同…

加密算法(一)-對稱加密(DES、AES、3DES、Blowfish、Twofish)一篇了解所有主流對稱加密,輕松上手使用。

一、對稱加密算法 對稱加密算法采用相同的密鑰來進行加密和解密操作。其優點是加密和解密速度快&#xff0c;不過密鑰的管理和分發存在一定的安全風險。 1.1、DES(已不推薦使用) 這是早期的對稱加密算法&#xff0c;密鑰長度為 56 位。但由于密鑰長度較短&#xff0c;如今已不…

深度優先VS廣度優先:算法選擇的核心邏輯與實戰指南

摘要 深度優先搜索&#xff08;DFS&#xff09;與廣度優先搜索&#xff08;BFS&#xff09;是圖結構遍歷與路徑分析的基礎算法&#xff0c;也是最常見的搜索框架&#xff0c;在路徑規劃、社交網絡分析、游戲AI等領域均有廣泛應用。本文從算法思想、數據結構選擇、時空復雜度和…

2025深圳杯、東三省數學建模B題數模AI全網專業性第一

為什么選擇使用我的數模AI&#xff1f; 1.輕松輔導學生 2.小白也能翻身碾壓大佬 3.突破知識壁壘&#xff0c;縮短與大佬的差距&#xff0c;打破不公平的教學資源&#xff0c;扭轉差距 4.輔助商業服務&#xff0c;成本低 5.大模型本身有一定隨機性&#xff0c;所以也不用擔心…

使用MGeo模型高精度實現文本中地址識別

一、功能與安裝 1、模型地址 模型是阿里開發的門址高精度識別模型。 https://modelscope.cn/models/iic/mgeo_geographic_elements_tagging_chinese_base/summary 注意&#xff1a;不能自己安裝包&#xff0c;沒法解決依賴問題&#xff0c;直接按照官方要求安裝下面的包&am…