上次在用函式來傳達你的心意> 0 <中我們把while迴圈內在做什麼用函式名稱詮釋出來,看起來像是在閱讀一篇文章一樣,這次讓我帶你看main裡面還有什麼可以改進的部分,讓整個main更直覺好懂。
第一眼我看見的是seats[10]這個陣列宣告長度的數值,10在很多地方用到而且這個數字是在這個範例內永遠是固定值,所以我們可以用一個叫做size來取代他,也方便我們之後長度修改,再來看到宣告變數i, j的地方,由於我們之前把函式切割出去了,這兩個變數就不需要存在。
int main()
{
int seats[10] = {99, 0, 10, 31, 0, 42, 70, 67, 0, 0};
int i, j, seat, number;
showSeats(seats, 10);
getUserInput(seat, number);
while(number != 0){
if(seats [seat - 1] == 0){
seats[seat - 1] = number;
showSeats(seats, 10);
getUserInput(seat, number);
}
else{
printf("Sorry, seat is taken.\n");
scanf("%d %d", &seat, &number);
}
}
bubble_sort(seats, 10);
showSeats(seats, 10);
printf("\n");
printf("***************\n");
return 0;
}
變數宣告這個區塊我感覺上是差不多了,你有其他想法也歡迎提出來跟我討論^ ^,再來我想往提示使用者輸入這整個區塊來做個修改,讓我幫你切割出我說的地方。
int main()
{
const int size = 10;
int seats[size] = {99, 0, 10, 31, 0, 42, 70, 67, 0, 0};
int seat, number;
showSeats(seats, size);
getUserInput(seat, number);
while(number != 0){
if(seats [seat - 1] == 0){
seats[seat - 1] = number;
showSeats(seats, size);
getUserInput(seat, number);
}
else{
printf("Sorry, seat is taken.\n");
scanf("%d %d", &seat, &number);
}
}
bubble_sort(seats, size);
showSeats(seats, size);
printf("\n");
printf("***************\n");
return 0;
}
提示使用者輸入這整個區塊的流程可以分成幾點:
- 顯示所有位置資訊
- 輸入位置索引和號碼
- 判斷位置是否合法然後塞值
- 判斷是否繼續輸入(使用者輸入數字不等於0)
首先第1點和第2點我們已經有了分別是showSeats和getUserInput,3和4我想再加兩個新函式,分別式isSeatValid跟isContinueInput,我們可以用這幾個函式來重新組織看看。
showSeats(seats, size);
getUserInput(seat, number);
while(number != 0){
if(seats [seat - 1] == 0){
seats[seat - 1] = number;
showSeats(seats, size);
getUserInput(seat, number);
}
else{
printf("Sorry, seat is taken.\n");
scanf("%d %d", &seat, &number);
}
}
太棒了!!看看我們修改後的成果,整個區塊越來越精簡了,而且閱讀性增加更多,試著一行一行過去就像看文章一樣,他要做的事情就跟你想得差不多,這是讓人覺得最舒服的程式碼。
原本的while迴圈我更換成do...while,因為使用者是先輸入才判斷之後要做的事,do...while會更符合整個流程概念,讓我們把整個修改結果整個合併一下。
do{
showSeats(seats, size);
getUserInput(seat, number);
if(isSeatValid(seats, size, seat)){
seats[seat - 1] = number;
}
}while(isContinueInput(number));
void showSeats(int seats[], int size)
{
printf("*seating*\n");
for(int i = 0; i < size; ++i){
printf("%d ", seats[i]);
}
}
void getUserInput(int& seat, int& number){
printf("\n");
printf("***************\n");
printf("Please input the seat (0~9) and number(-1 to end game)\n");
scanf("%d %d", &seat, &number);
}
bool isSeatValid(int seats[], int size, int seat){
if(seat - 1 < 0 || seat - 1 >= size){
printf("Sorry, seat is invalid.\n");
return false;
}
if(seats[seat - 1] != 0){
printf("Sorry, seat is taken.\n");
return false;
}
return true;
}
bool isContinueInput(int number){
return number != 0;
}
int main()
{
const int size = 10;
int seats[size] = {99, 0, 10, 31, 0, 42, 70, 67, 0, 0};
int seat, number;
do{
showSeats(seats, size);
getUserInput(seat, number);
if(isSeatValid(seats, size, seat)){
seats[seat - 1] = number;
}
}while(isContinueInput(number));
bubble_sort(seats, size);
showSeats(seats, size);
printf("\n");
printf("***************\n");
return 0;
}
到這邊你可能會對isContinueInput有個疑問,這個函式裡面只有一行有需要為了這一行新增一個函式嗎?沒錯很多人會覺得沒有必要,對我自己來說number != 0這行沒辦法直接說明他到底想做什麼,我必須切換我的思維才能了解這是根據使用者輸入數字來決定要不要繼續,思維上的轉換會導致分心,在看main的時候我只想專注在抽象的想法上,而不是實作細節,這會幫助我減少理解程式碼所花的時間,相信也可以幫助其他看程式碼的人,要記住你一定會跟別人一起合作寫程式碼,能夠為別人多做一點都是值得的。
整個重新架構的部分就先到這裡,你可以回頭看這篇變數命名的善意來比較看看閱讀性上的差異,相信你會感受很深,很感謝你這麼有耐心看到最後,過程中可能有些講解上不太明確的部分都歡迎留言告訴我,或是你有任何想法也都歡迎!之後還有其他可以重新修正的程式碼範例我也會繼續分享給你,讓我們繼續往更美好程式碼邁進,我們下次見 ^ ^