尹蘭蘭 磨峰 熊水平



摘? 要:C語言課程中有眾多的算法,各種算法抽象且難以理解。如果能把幾個重要的算法以具體的圖形來呈現,則對于算法的理解掌握更為容易。本文主要介紹了在C語言課程中進行幾種算法的可視化圖形呈現。具體來說,即在C語言編譯環境中安裝插件easyX以獲得可視化圖形。通過幾種算法的可視化編程,產生具體直觀的圖形圖像。透過這種算法和圖形相結合的形式,激發了學生對學習C語言的熱情,同時加深了學生對算法的理解。
關鍵詞:easyX;可視化教學;斐波那契數列;笛卡爾函數
中圖分類號:TP399? ? ?文獻標識碼:A
Visual Teaching of Algorithms by Using easyX in the C Language Course
YIN? Lanlan,MO Feng,XIONG Shuiping
(College of Computer and Information Engineering,Hechi University,Hechi 546300,China)
Abstract:Many algorithms in C language are abstract and difficult to understand.Several important algorithms will be much easier to understand if presented in specific graphics.This paper describes the visual teaching of the algorithms in C language and proposes to install easyX software in C language compiler environment to obtain the graphics of algorithms.The visual programming of algorithms stimulates students' enthusiasm for learning C language and deepens the understanding of the algorithms.
Keywords:easyX;visual teaching;Fibonacci sequence;Cartesian function
1? ?引言(Introduction)
C語言是一門面向過程、抽象化的計算機程序設計語言。一直以來,它是高等院校計算機專業必修的一門基礎課程[1]。
在這門課程中,算法是最重要的知識點。它被稱為是程序設計的靈魂,也是學習編程的必備知識。一個優秀的程序需要高效、清晰的算法,但是,算法并不容易被學生掌握,因為它抽象難懂。如何能讓學生快速有效的學習算法?如何能讓學生對算法編程感興趣?如何能增強學生在算法編程中的自主思維和實踐創新精神?這一直是學生在學習程序設計過程中遇到的重點和難點問題。
本文作者在實際教學過程中發現,在C語言課程設計中進行算法的可視化教學可以很好地解決上述問題。
如何在C語言中引入可視化學習?作為C語言的圖形庫, easyX可以很好地完成這樣的任務。
2? ?easyX簡介(Brief introduction of easyX)
easyX是C語言進行圖形化編程和游戲編程的一種圖形庫。它主要提供了用于繪制圖形的常用函數庫及相應的頭文件。使用easyX非常簡單,只要從官方網站下載安裝包,解壓,并將其中的lib文件夾和include文件夾下的內容分別拷貝到Visual C++相應的目錄下即可開始使用[2]。EasyX庫采用動態鏈接的方式,不會增加任何額外的DLL依賴。
在使用easyX提供的函數前需要使用initgraph(int? width,int height,int flag=NULL)來初始化繪圖環境,設置顯示屏的寬度和高度。結束后使用closegraph()函數關閉圖形環境[3]。
3? ?算法介紹(Introduction of algorithms)
為了增加C語言課程的趣味性,這里我們設計了三種算法:階乘(Factorial)、斐波那契數列(Fibonacci sequence)和笛卡爾心形函數。其中前兩種算法用到了遞歸函數。編程語言中,函數Func(Type a,……)直接或間接調用函數本身,則該函數稱為遞歸函數。遞歸函數不能定義為內聯函數。在數學上,關于遞歸函數的定義如下:對于某一函數f(x),其定義域是集合A,那么若對于A集合中的某一個值X0,其函數值f(x0)由f(f(x0))決定,那么就稱f(x)為遞歸函數。
3.1? ?階乘
階乘派生于排列。比如3個人排隊,那么就有3!種排列。一個正整數的階乘是所有小于及等于該數的正整數的積,并且有0的階乘為1。自然數n的階乘可以寫作n!。
n!=1*2*3*...*n
5的階乘可以表示為:5!=5*4*3*2*1。
階乘的函數可以寫成:
int factorial (int x)
{
int y;
if (x<=1)
{
y=1;
}
else
{
y=x*factorial(x-1);
}
return y;
}
如何才能將階乘函數用easyX繪制出的圖形進行可視化教學?在easyX環境下,繪制圖形首先需要找到每個點的位置,即y=factorial(x),對應的坐標點為(x,y)也即(x,factorial(x))。5的階乘即x的值是5,y的值是factorial(5),計算出數值為
5!=120,所以在x=5時對應的坐標點為(5,120)。依次求出所有點的坐標如下:(0,1),(1,1),(2,2),(3,6),(4,24)。如何將所有的點在easyX環境下連成一條線表示出來呢?我們只需要在相鄰的兩個點之間畫一條直線,用easyX中的line函數可以實現。Line函數用于畫直線。它的定義為:
void line (int x1,int y1,int x2,int y2);
其中,x1為直線的起始點的x坐標;
y1為直線的起始點的y坐標;
x2為直線的終止點的x坐標;
y2為直線的終止點的y坐標。
畫出所有的線條,首尾相連,代碼如下:
initgraph(30,130);
for (int i=0;i<5;i++)
{
setcolor(GREEN);
line(i,factorial(i),(i+1),factorial(i+1));
Sleep (20);
}
做出的圖形如圖1所示。
圖1 0—5的階乘函數圖形
Fig.1 Graphics of factorial functions of 0—5
為了獲得更好的效果,可以適當調整x、y的參數,并且調整窗口大小,讓圖形更好地適應easyX的畫圖環境[4]。例如,y值不變,將x值的參數調整擴大100倍,窗口大小從(30,130)變成(630,730),另外設置顏色為藍色,x的取值范圍為0<=x<=5,代碼變為:
line(i*100,factorial(i),(i+1)*100,factorial(i+1));
畫出的圖形如圖2所示。
圖2 X參數調整后的階乘圖形
Fig.2 Factorial graphics with adjusted X parameters
階乘函數廣泛地應用在金融、計算機、建筑等行業。機器學習、AI技術中也有很多階乘的應用。
3.2? ?斐波那契數列
斐波那契數列又稱為黃金分割數列。它的定義為:F(0)=1,F(1)=1,F(n)=F(n-1)+F(n-2),其中,n>=2。
如果要求5的斐波那契數列,可以這樣計算:F(0)=1,
F(1)=1,F(2)=2,F(3)=3,F(4)=5,F(5)=8。它的函數可以寫成:
int fibonaci(int i)
{
int y=0;
if(i==0)
{
y=0;
}
else if(i==1)
{
y=1;
}
else
{
y=fibonaci(i-1)+fibonaci(i-2);
}
return y;
}
要畫出它的圖形,需要做如上分析:
1.計算每個坐標點的位置,如:(0,1),(1,1),(2,2),(3,3),(4,5),(5,8)。
2.用easyX的line函數將相鄰的點畫一條直線。
3.將所有的線條收尾相接,畫出easyX環境下的曲線。
代碼如下:
initgraph(30,130);
for (int k=0;k<5;k++)
{
setcolor(BLUE);
line(k,fibonaci(k),(k+1),fibonaci(k+1));
Sleep (20);
}
做出的圖形如圖3所示。
圖3 0—5的斐波那契數列圖形
Fig.3 Fibonacci sequence graphics of 0—5
這個圖形在0—5的x區間值的變化幅度不是很大,畫出的圖形效果不夠明顯。為了獲得更好的效果,可以適當調整x,y的參數,同時調整窗口的大小從(30,130)變為(630,730),讓圖形更好地適應easyX的畫圖環境。例如,將x值的參數調整擴大100倍,y值保持不變,代碼變為:
line(i*100,fibonaci(i),(i+1)*100,fibonaci(i));
畫出的圖形如圖4所示。
圖4 X參數調整后的斐波那契圖形
Fig.4 Fibonacci figure adjusted by X parameter
圖4的圖形y值變化不夠明顯。如何進一步調整y值,使其變化率高一些,不能被忽視?根據計算,x值越大,數列的變化率越大。窗口的高度是730,而斐波那契數列在5這個點的坐標是(5,8),列的值是8,列的變化率可以用下列公式計算出來:
(y2-y1)/(x2-x1)
0—5這6個點列的變化率可以計算出來分別為:0,1,1,2,3,……它同樣為一個斐波那契數列。經過計算,將y值的結果向右移9位可以獲得變化率更大,更適合easyX窗口的數據。即將代碼變為:
line(i*100,fibonaci(i+9),(i+1)*100,fibonaci(i+1+9));
所畫出的圖形如圖5所示。
圖5 X、Y參數調整后的斐波那契數列圖形
Fig.5 Fibonacci sequence graphics adjusted by X and Y
parameters
在我們日常生活中,斐波那契數列無處不在。比如松果、鳳梨、樹葉的排列;某些花朵的花瓣數(如向日葵);蜂巢;蜻蜓翅膀、超越數e、等角螺線、十二平均律等;在現代物理、準晶體結構、化學等領域也有應用廣泛。
以上兩種算法在程序設計中都用到了遞歸函數。為了將上述兩個圖形畫在同一個坐標系中,可以調整代碼如下:
initgraph(630,730);
for (int i=0; i<=5; i++)
{
setcolor(YELLOW);
line(i*100,factorial(i),(i+1)*100,factorial(i+1));
setcolor(RED);
line(i*100,fibonaci(i+9),(i+1)*100,fibonaci(i+1+9));
Sleep(85);
}
Sleep(50);
此處的factorial()函數和fibonaci()函數為自己編程實現的C語言函數代碼。根據重新調整后的代碼,可以獲得如圖6所示。其中黃色的線為數列函數畫出來的,紅色的線是斐波那契函數畫出來的。
圖6 階乘函數和斐波那契數列圖形
Fig.6 Factorial functions and Fibonacci sequence graphics
為了增加學生學習編程的興趣,我們接下來準備探討笛卡爾函數的可視化實現。
3.3? ?笛卡爾心形曲線
笛卡爾是大家都熟悉的著名數學家。他是法國著名的哲學家、物理學家、數學家、神學家。他對現代數學的發展做出了重要貢獻。他因為將幾何坐標體系公式化而被認為是解析幾何之父。在他眾多的數學理論中,笛卡爾心形曲線尤為著名,也被稱為“學霸的表白”,很多同學對這種心形曲線十分感興趣。
笛卡爾用運動的觀點把曲線看成點的運動的軌跡。笛卡爾函數即笛卡爾心形曲線。心形線即一個圓上固定一點在它繞著與其相切且半徑相同的另外一個圓周滾動時所形成的軌跡。它的極坐標表達式可以寫成:水平方向r=a(1-cosθ)或r=(1+cosθ)(a>0);或垂直方向r=a(1-sinθ)或r=a(1+sinθ)(a>0)。它的平面直角坐標表達式分別為:x^2+y^2+a*x=a*sqrt(x^2+y^2)和x^2+y^2-a*x=a*sqrt(x^2+y^20)。為了畫出動態圖形,需要先根據平面直角坐標的表達式求解出x、y的值,然后進行easyX畫圖。根據平面直角坐標表達式,獲得x、y參數方程為:y=a*(2*cos(t)–cos(2*t)),x=a*(2*sin(t)–sin(2*t)),(0<=t<=2*pi)。根據t的范圍,做出對應(x,y)點,然后將所有的點與原點(0,0)直接相連,合理地設置sleep時間,就可以看到動態效果。為了更好地適應easyX畫圖的窗口大小,這里我們選取了t的范圍為[0,720],x和y同時擴大30倍。具體的程序代碼如下。
initgraph(720,730);
setorigin(360,300);
setbkcolor(BLUE);
for (int t=0; t<=720; t++)
{
int a=4;
double x=a*(2*sin(t)+sin(2*t));
double y=a*(2*cos(t)+cos(2*t));
line(0,0,x*30,y*30);
sleep(20);
}
這段代碼的功能是動態地畫出笛卡爾心形圖形,每間隔20秒畫一條線,獲得的不同時間點的截圖如圖7和圖8所示。注意,這里截取了不同顏色的圖形。圖7藍色的圖形是中間過程中的一個瞬間,圖8綠色的圖形是完整的笛卡爾心形圖案。用動態圖可以讓學生更好地理解算法的過程,增強學習語言及算法的趣味性。
圖7 中間過程的瞬間圖形
Fig.7 Transient graphics of intermediate process
圖8 完整的笛卡爾圖形
Fig.8 Complete Cartesian graphics
用不同顏色的曲線繪制心形圖可以獲得不同的效果。如圖9和圖10所用的顏色分別為:
setcolor(RGB(t/3,t/3,t/3)); #圖9
setcolor(RGB(t/3,t/3*60,t/3*100)); #圖10
根據不同的setcolor,設置畫出的圖形如圖9和圖10所示。
圖9 RGB(t/3,t/3,t/3)畫出的完整圖形
Fig.9 Complete graphics drawn by RGB(t/3,t/3,t/3)