摘要:以圖形輸出為例,利用for循環和print方法、tab函數、spc函數等的巧妙配合,演變從易到難的編程過程,闡述了Visual Basic的編程技巧,體會編程的快樂。
關鍵詞:切入點、單一符號組成的圖形、有規律的數字圖形
中圖分類號:TP311文獻標識碼:A文章編號:1009-3044(2008)36-3064-04
1 引言
Visual Basic是一種面向對象的可視化的程序設計語言,特別適合初學者學習。與它的前身Basic相比,Visual Basic在很多方面有著無可比擬的優勢,比如,用戶不需要編寫代碼來設計用戶界面,僅此這一點,就使得Visual Basic入門更加容易了,也更有趣了。
但是設計用戶界面僅僅是設計程序最初的一步,為了實現程序功能,最終還是要編寫代碼,而編寫代碼是程序設計的一大門坎,很多人徘徊于此,難以進步。“萬事開頭難”,找準突破口,對想深入學習編程的人來說至關重要。
圖形輸出就是一個很好的切入點,圖形很直觀、很形象,使編程者不會感到枯燥,而且圖形的變化很多,比如,將兩種或幾種最基本的圖形進行不同的組合、拼接就會生成很多不同的復雜圖形,如果在最基本的圖形代碼上稍加修改就又會生成另外不同形狀的圖形,感覺好像在“變魔術”。下面,我們就從最簡單的圖形開始,做一回“魔術師”,去體會編程的魅力。
2 單一符號組成的圖形
顧名思義,這種圖形中是只有一種符號構成的。這種簡單圖形有很多種:正方形、長方形、平行四邊形、直角三角形、等腰三角形、等腰直角三角形等等,這里列出了一些,見表1、表2。
長方形(或正方形)是最基礎的圖形,其他圖形如平行四邊形、三角形均可以在長方形(或正方形)代碼的基礎上稍加修改而得到。
圖1是一個4行5列的長方形,代碼如下:
1 For i=1 to 4
2 For j=1 to 5
3 Print \"*\";
4 Next j
5 Print
6 Next i
圖形是通過雙重for循環得到的,外循環用來控制圖形的行數,內循環用來控制每行的個數。因為是一個4行5列的長方形,所以外循環變量i的終值是4,而內循環變量j的終值是5。如果要輸出一個4行4列的正方形,則只要將內循環變量的終值改成4即可。第5語句行print的作用是換行,使得每次內循環結束后就換行;如果沒有這語句,則輸出的所有“*”都處于同一行。
圖2是一個4行5列的平行四邊形,與圖1相比,它每一行的起始位置是不同的,第1行從第1個位置開始輸出,第2行從第2個位置開始輸出,……。要想得到圖2,只要在圖1代碼的第1行和第2行之間,加一條Print tab(i);語句即可,tab函數的功能是給print方法的輸出項定位。圖2的代碼如下:
1 For i=1 to 4
2 Print tab(i); '用來確定每一行的起始位置
3 For j=1 to 4
4 Print \"*\";
5 Next j
6 Print
7 Next i
圖3也是一個4行5列的平行四邊形,與圖2所不同的是:它的第1行從第4個位置、第2行從第3個位置、第3行從第2個位置,第4行從第1個位置開始輸出。所以要想得到圖3圖形,只要將圖2代碼的第2語句行換成Print tab(5-i);語句即可。
表2的圖形都是三角形,與平行四邊形相比:平行四邊形每一行的字符個數是固定的,而三角形每一行的字符個數不等。表3列舉了圖5、圖7、圖8的代碼。
由表3的代碼可知,三角形的代碼與平行四邊形的代碼很相似,它們也都可以由雙重for循環得到,如果每一行的起始位置不一樣,則用tab函數來定位。但由于三角形每一行的“*”個數不同,所以三角形內循環的循環變量終值是變化的,而且是與外循環變量i相關的。以圖7代碼為例,當i=1,內循環變量的終值為7;當i=2,內循環變量的終值為5;當i=3,內循環變量的終值為3;當i=4,內循環變量的終值為1。
以上均屬簡單圖形,像一些比較復雜的對稱圖形,可以由上述簡單圖形拼接而成。比如圖10這樣一個菱形:
圖10
我們可以把菱形看成是由一個3行的正等腰三角形和一個4行倒等腰三角形拼接而成;也可以看成是一個4行的正等腰三角形和一個3行倒等腰三角形拼接而成;只要按順序將兩段代碼連接起來即可。
那么像圖11這樣的圖形如何得到呢?
圖11
通過觀察可以發現:每一行都有兩個“*”,但兩個“*”之間的距離不一樣,隨著行數的增加有減少的趨勢。可以用三種方法來實現,代碼如下。
代碼1:
1) 方法一
For i = 1 To 4
Print Tab(i);
For j = 1 To 2
Print \"*\"; Spc(8 - 2 * i);
Next j
Next i
2) 方法二
X1=1:x2=8
For i=1 to 4
Print tab(x1);\"*\";tab(x2);\"*\"
X1=x1+1
X2=x2-1
Next i
3) 方法三
For i=1 to 4
Print tab(i); \"*\";spc(8-2*i);\"*\"
Next i
方法一采用的是雙重for循環。基本思想就是:外循環控制行數,內循環控制每行個數。因為是4行,所以外循環變量從1變到4;因為每一行都是兩個“*”,所以內循環變量從1變到2。在print方法中采用spc函數來控制每一行兩個“*”之間的空格。
方法二:沒有使用雙重for循環,它只用了一層循環。在print方法中用兩個TAB函數對處于同一行的兩個“*”分別進行定位,注意TAB函數的參數x1、x2的值是變化的,x1的值逐漸增大而x2的值逐漸減少。
方法三:也只用了一層循環,在print方法中用spc 函數產生空格來將處于一行的兩個“*”分開,每一行產生的空格是隨著i的變化而變化的。
可發現,使用單層循環輸出這個圖形比使用雙重循環要簡單些。這個圖形之所以可以用單層循環來實現,是因為它每一行的字符個數是相等的。平行四邊形也可以用單層循環來得到。代碼如下:
For i=1 to 4
Print tab(i); \"*****\";
Next i
圖12是由兩個圖11左右拼接而成,同樣可以用單層循環來實現。代碼如下:
代碼2:
1) 方法一
X1=1:x2=x1+7: x3=x2+1: x4=x3+7
For i=1 to 4
Print tab(x1);”*”;tab(x2);”*”;
Print tab(x3);”*”;tab(x4);”*”;
X1=x1+1:X2=x2-1
X3=x3+1:X4=x4-1
Next i
2) 方法二
For i=1 to 4
Print tab(i); \"*\" ;spc(8-2*i); \"*\";
Print spc(2*i-2); \"*\";spc(8-2*i); \"*\";
Next i
第一種方法通過4個TAB函數用x1、x2、x3、x4四個變量來控制每一個“*”的位置,弄清這四個變量之間的關系及各自的變化趨勢是關鍵所在。而第二種方法,只用一個TAB函數來控制每行第一個字符的位置,用3個SPC函數控制每行“*”之間的空格數,計算好每個SPC函數的參數是關鍵。以上兩段代碼都是在代碼1的基礎上稍作修改而得到。
3 有規律的數字圖形
這類圖形不是由單一符號組成的,它是由不同的阿拉伯數字按照一定規律排列而成。表5列出了一些簡單的有規律的數字圖形。如果一個圖形既有一位數又有兩位數,那么為了使圖形中的數字能夠對齊,通常要在print方法中使用format函數,用“@”格式符來指定每個數字所占的列數。表5列出了三種最簡單的數字圖形。
注意,代碼中tab函數的參數與format函數的格式字符串是相關的,例如,將圖13代碼中format(i,”@@”)改成format(i,\" @@@\"),則tab函數的參數也要作相應的調整,否則數字對不齊。
圖16
圖16是由1~10十個阿拉伯數字組成,注意這些數字的排列順序:第1列從上到下為:1、2、3、4,第2列從上到下為:5、6、7……
代碼3:
1) 方法一
Dim a(1 to 4,1 to 4)
K=1
For i=1 to 4
For j=1 to 5-i
A(j,i)=k
K=k+1
Next j
Next i
For i=1 to 4
For j=1 to 5-i
Print a(i,j);
Next j
Next i
2) 方法二
1 For i=1 to 4
2 K=i
3 For j=1 to 5-i
4 Print format(k,”@@@”);
5 K=k+(5-j)
6 Next j
7 Print
8 Next i
圖16可以用兩種方法來實現,見代碼3。第一種方法使用數組,第二種方法使用簡單變量。我們先來看看第一種方法:代碼包含兩個雙重for循環,第1個for循環的作用是給數組a賦值,第2個for循環的作用是將a數組元素輸出。給數組a賦值是代碼的關鍵。方法一是按這樣的順序給數字賦值的,見圖17。
第2種方法的第2語句行和第5語句行是關鍵。由k=i得到每行第1列數字,當i=1時,k=1;i=2時,k=2;i=3時,k=3;i=4時,k=4。將第1列數字輸出后,再由內循環體的k=k+(5-j)得到其他列的數字。以第一行為例,第1行有4個數字,1、5、8、10,很顯然,它們是逐漸增加的,而且它們之間的增加額隨著j的增大是逐漸減少的(5比1大4,8比5大3,10比8大2)。見圖18。
圖19與圖16很相似,也可以用兩種方法來實現。如代碼4:
代碼4:
1) 方法一
Dim a(1 to 4,1 to 4)
K=1
For i=1 to 4
For j=i to 4
A(j,i)=k
K=k+1
Next j
Next i
For i=1 to 4
For j=1 to i
Print a(i,j);
Next j
Next i
2) 方法二
For i=1 to 4
K=i
For j=1 to i
Print format(k,”@@@”);
K=k+(4-j)
Next j
Next i
圖20也是由1~10十個阿拉伯數字組成,與圖16、圖19所不同的是,數字是沿著對角線方向按順序分布的:A(1,1)=1,a(2,2)=2,a(3,3)=3,a(4,4)=4,a(2,1)=5,a(3,2)=6,a(4,3)=7,……
圖20也可以用兩種方法來實現。見代碼5:
代碼5:
1) 方法一
Dim a(1 to 4,1 to 4)
i=1:j=1
For x=1 to 10
A(i,j)=x
If i=4 then
i=6-j
j=1
Else
i=i+1
j=j+1
End if
Next x
For i=1 to 4
For j=1 to i
Print a(i,j);
Next j
Next i
2) 方法二
a = 1
For i = 1 To 4
k = a
For j = 1 To i
Print k;
k = k - (j + 4 - i)
Next j
a = a + (5 – i)
Next i(下轉第3070頁)
(上接第3067頁)
第1種方法依然使用數組,代碼中有一個單層for循環和一個雙重for循環。單層for循環用來給數組a賦值,雙重for循環的作用是將賦過值的數組元素輸出出來。單層for循環內有一條if語句,整個賦值流程就是這個if語句控制的。
循環變量x的值從1變到10,i和j的初值均為1,首先從a(1,1)開始賦值,a(1,1)=1,只要i的值不為4,則就執行i=i+1:j=j+1,a(2,2)=2→a(3,3)=3→a(4,4)=4;此時i的值為4,if語句的條件滿足,則要執行i=6-j:j=1,使得賦值轉向a(2,1)=5。由圖25可知整個賦值的先后順序。
第2種方法,設了兩個變量a和k。變量a用來存放每行第1列數字,每一行的其他列數字由變量k得到。
由圖22可看出:第1列4個數字1、5、8、10,是逐漸增大的,但增加額卻是隨著i的增加而逐漸減少的。所以,每行第1列數字由a = a + (5-i)語句得到。
橫向來看,每一行的數字是逐漸減少的,減少額不僅是隨著內循環變量j的增加而增加,而且隨著外循環變量i的增加而減少,所以除了第1列以外,其他列數字都可由k = k - (j + 4 - i)得到。
以上圖形代碼基本上都是由for循環語句和print方法、tab函數、spc函數等相配合而得到,各個圖形代碼之間的區別并不大,往往只是一點點,然而正是這一點點體現了編程魔術般的魅力。像這樣漂亮而有趣的圖形還有很多,限于篇幅,這里只列舉了一些;如果有興趣,大家自己可以進行嘗試,應該會有很多收獲。
4 結束語
圖形輸出只是學習編程的一個切入點,它不是目的而是手段。通過它,可以幫助那些想深入學習編程的人體會到編程帶來的快樂,幫助他們充分了解編程技巧,熟悉常用的編程方法。有了這樣一個旅程,他們對編程應該不會感到恐懼了。
參考文獻:
[1] 朱馴.青少年信息學奧林匹克競賽培訓教材[M]. 南京:南京大學出版社,2002.
[2] 潘地林.Visual Basic程序設計[M]. 北京:高等教育出版社,2006.
[3] 譚浩強. Visual Basic程序設計[M]. 北京:清華大學出版社,2000.
注:“本文中所涉及到的圖表、注解、公式等內容請以PDF格式閱讀原文。”