設計軟體亦如是,大型程式該怎麼做控制權的移轉,常常也會讓開發者傷透腦筋。程式執行其實可以分成許多情況,就以猜數字遊戲來看,程式最後有五種情況,就是猜對數字、猜大超過 5 、猜大小於 5 、猜小超過 5 、 猜小小於 5 。
因此遊戲到最後的五種情況,也就是處於五種不同的狀態中。我們打算以狀態作為顯示最後結果的依據,這是說,猜數字遊戲會分成兩部份,首先是狀態設定,依三層巢狀的 if-else 陳述設定狀態,再來是依狀態顯示最後遊戲的訊息。
利用狀態操作程式的控制移轉是一種技巧,這個效果在我們目前的猜數字可能並不明顯,對我們往後繼續開發程式卻有莫大的助益。
我們提供利用狀態改寫的版本如下
#include <stdio.h>
#include <time.h>
#include <math.h>
enum STATE {RIGHT = 1, BIG_FOUR, BIG_FIVE, SMALL_FOUR, SMALL_FIVE};
int main(void)
{
int answer = time(NULL);
int guess;
int diff;
int state = 0;
answer %= 25;
if (answer == 0) {
answer = 25;
}
printf("請猜一個數字 1 到 25: ");
scanf("%d", &guess);
diff = guess - answer;
diff = (int) fabs(diff);
if (guess == answer) {
state = RIGHT;
}
else {
if (guess > answer) {
if (diff > 5) {
state = BIG_FIVE;
}
else {
state = BIG_FOUR;
}
}
else {
if (diff > 5) {
state = SMALL_FIVE;
}
else {
state = SMALL_FOUR;
}
}
}
if (state == RIGHT) {
printf("猜對囉!\n");
}
else if (state == BIG_FIVE) {
printf("猜的數字比答案大....還很遠,再加把勁!\n");
}
else if (state == BIG_FOUR) {
printf("猜的數字比答案大....不錯喔!很接近了\n");
}
else if (state == SMALL_FIVE) {
printf("猜的數字比答案小....還很遠,再加把勁!\n");
}
else if (state == SMALL_FOUR) {
printf("猜的數字比答案小....不錯喔!很接近了\n");
}
else {
printf("猜錯囉!\n");
}
return 0;
}
/* 《程式語言教學誌》的範例程式
http://pydoing.blogspot.com/
檔名:gn4.c
功能:簡單的猜數字遊戲
作者:張凱慶
時間:西元2010年7月 */第 5 行,我們利用了 C 語言設計一連串整數常數的關鍵字 enum ,來標示狀態
enum STATE {RIGHT = 1, BIG_FOUR, BIG_FIVE, SMALL_FOUR, SMALL_FIVE};利用 enum 宣告出的特別的列舉型態,其為有名稱的列舉數,實際上是整數常數。這是說,列舉數中如果用等號設定初值,隨後的值都會逐項遞增 1 ,如果沒有用等號設定初值,第一項列舉數會被設成 0 ,隨後的值也都會逐項遞增 1 。
注意,列舉數的宣告不需要等號,首先是 enum ,然後空格,接上列舉型態的名稱,然後是用大括弧圍起來的列舉數。通常宣告列舉型態會放到引入標頭檔之下,也就是所有函數之外,這樣一來所有函數都可以使用。
所以五種狀態,我們用列舉數分別是 RIGHT 、 BIG_FOUR 、 BIG_FIVE 、 SMALL_FOUR 、 SMALL_FIVE ,程式的第 24 行到第 44 行為設定狀態,第 46 行到第 63 行則是依狀態顯示遊戲結果的訊息。
第 46 行到第 63 行,我們用了種不一樣的寫法
if (state == RIGHT) {
printf("猜對囉!\n");
}
else if (state == BIG_FIVE) {
printf("猜的數字比答案大....還很遠,再加把勁!\n");
}
else if (state == BIG_FOUR) {
printf("猜的數字比答案大....不錯喔!很接近了\n");
}
else if (state == SMALL_FIVE) {
printf("猜的數字比答案小....還很遠,再加把勁!\n");
}
else if (state == SMALL_FOUR) {
printf("猜的數字比答案小....不錯喔!很接近了\n");
}
else {
printf("猜錯囉!\n");
}因為對不同條件判斷很常用到,所以 else 後面可以直接加另一個 if 陳述,最後的 else 則是可有可無,加的話程式就會執行以上皆非的情況,不加的話,以上皆非就會直接跳過,程式會繼續執行最後 else 底下大括弧的陳述。
來編譯執行看看吧!

問題與討論
- 為什麼要用狀態控制程式?
- 列舉數還可以有哪些應用?
- C 語言有哪些方式可以做多重選擇?
- 連續的 else if 最後若接 else ,這跟 switch-case 的 default 有什麼相似之處?
沒有留言:
張貼留言