//bullcow4.c -- by tsaiwn@csie.nctu.edu.tw /* 這是 BULL& COW 程式 -- 電腦想四位數, 給人來猜 -- 接近完成版! gcc -DHINT bullcow4.c 自己寫不下出的才看...其實只是把之前給大家的範例程式整合: ***** 重點: How to generate a random number in 0..9 ? How to generate four "different" digits? How to find out ?A ?B ***************************************************/ #include #include #include #define repeat do { #define until(x) } while(!(x)) char myMind[6], yourGuess[6]; int yyn=1; // 1 == yes, no == 0 int nBull, nCow; void think(char[ ]); // 這要傳參數 void getAnswer( ); // 這不傳, 用 global 變數 yourGuess[ ] void checkAnswer(char[ ], char* , int *nb, int* nc); int isError(char*), askPlayAgain( ); void hello( ); int main( ) { hello( ); repeat printf("Let me think 讓我想好四位數字...OK.\n"); think(myMind); // 填入 char myMind[ ] #ifdef HINT printf("我想好的是 My Secret : %s\n", myMind); //因myMind[4]是 0 #endif while(38==38) { // true printf(" Your guess:"); getAnswer( ); // read into yourGuess if( feof(stdin) || (yourGuess[0] == '-' ) ){ printf("答案是 ...The answer is %s\n", myMind); clearerr(stdin); // reset the input buffer break; } //if checkAnswer(myMind, yourGuess, &nBull, &nCow); if(nBull == 4 ) { printf("Contratulations!恭喜猜對了\n"); break; } // if printf("%d Bull 隻公牛, %d Cow隻母牛\n", nBull, nCow); } // while yyn = askPlayAgain( ); // 交給小弟去問 然後回報 until( yyn == 0); // 直到不玩了 ! printf("\nBye\n"); return 0; } // main /********* END of Main Program *************/ /****** ** 函數 think( ) 用來想一個四位不重複的數字 ** 用 rand( ) 或 random() 生出亂數, see "man rand", "man random" ** 函數 getAnswer( ) 用來讀入一個四位不重複的數字, 放 yourGuess[] 中 不傳參數, 直接用 yourGuess (global 變數) 你要用像 think(myMind) 那樣有參數的寫法也可以啦 ** 函數 checkAnswer( ) 也很簡單: 用 loop 比比看到底 前兩參數 (都是 char array) 中有幾位數字同且位置同? 又有幾位數的數字同但是位置不同? (? B 或說 ? Cow 母牛) 更進一步練習題: 寫一個電腦會猜人想的 公牛母牛遊戲 **** 再來, 寫成人和電腦輪流對猜 *******************************************************************/ void getAnswer( ) { int ok = 1; // assume OK do { // 有防呆 ! fgets(yourGuess, sizeof(yourGuess),stdin); // yourGuess 是外變數 // fgets(buf, k, ...) will reads k-1 char at most into buf[ ] // 注意若是參數傳入的 array parVar[ ] 則不可用 sizeof(parVar) ! // 這是因為 array 有幾個元素並不會傳入 function (array會變 pointer) if(feof(stdin)) yourGuess[0] = '-'; // give up if(yourGuess[0] == '-') return; // 不檢查 "-" 開頭的 if(yourGuess[0] == 'q') return; // 不檢查, 因可能 "quit" :-) ok = 1; // assume OK if(isError(yourGuess) != 0) ok = 0; // error if(ok==0) { fprintf(stderr, " Error, re-type your Guess: "); } }while(ok == 0); // 直到輸入的沒有錯 ! return; // 想一想若要用參數呢? }// getAnswer( /////////////////////////////////////////////////////////// void checkAnswer(char x[ ], char*y , int *nb, int*nc) { // dummy array 寫成 char x[ ] 或 char*x 都一樣意思 int i,k; *nb = *nc =0; for(i=0; i<=3; i++){ // 算出公牛 if(x[i] == y[i]) *nb = *nb +1; /* 再來算母牛 */ for(k=0; k<=3; k++) if(x[i]==y[k]) *nc += 1; } *nc -= *nb; /* 扣掉多算的 !! */ }// checkAnswer( ///////////////////////////////////////////////////////// int myRandom( ); // declare ONLY, I need this function, 其定義在後面寫 void think(char *myMind) { int k, x, seed; myMind[4] = 0; // 0 is same as '\0' 代表字串結束! /***** 去掉這列再 run 看看 ==> 會變成 true random 而不是 pseudo random seed = (int) time(0) & 0xffff; srand( seed ); /*** set seed, see "man srand", "man 3 time" ***/ /*** time( ) returns the time since 00:00:00 GMT, Jan. 1, 1970, measured in seconds. **************************/ #ifdef DEBUG printf("seed=%d===\n", seed); // gcc -DDEBUG bullcow4.c #endif myMind[0] = myRandom( ); // myRandom( ) 會傳回 0..9 之一 repeat x= myRandom( ); until (x != myMind[0]); myMind[1] = x; x= myRandom( ); while( x== myMind[0] || x == myMind[1]) // 注意條件 x= myRandom( ); myMind[2] = x; repeat x= myRandom( ); until ( (x != myMind[0]) && x!= myMind[1] && x!= myMind[2]); myMind[3] = x; // 其實以上可以用 for Loop 把程式寫得更短而不要看起來土土的 :-) for(k=0; k<=3; k++) myMind[k] += '0'; // convert to ASCII /// 轉為 ASCII 文字並在尾巴放 '\0' 這樣可做為字串用 %s 印出! }// think( int myRandom( ) { int ans= rand( ); // C 的標準 function 宣告在 return ans % 10; // 0..9 ; 若要 15..31 呢 ? } int askPlayAgain( ) { // 注意與之前版本 getYN( ) 略有不同 static char tmp[99]; printf(" 繼續玩 Play again?"); fgets(tmp, sizeof(tmp), stdin); // 讀取回答進 tmp if(feof(stdin)) return 0; // EOF encounted (CTRL_Z) if( (tmp[0] == 'n') || (tmp[0]=='N') ) return 0; // NO return 1; // 其他都當作 Yes }// askPlayAgain( void hello( ) { printf("Bulls&Cows game這是公牛母牛遊戲, 請輸入 4位不同數字猜我想的數\n"); printf("\r我將告訴你幾隻公牛 幾隻母牛\r\n"); printf("公牛Bull means 數字對位置也對\r\n"); printf("母牛Cow means 數字對但位置不對\r\n"); printf("Negative number will give up輸入負數表示放棄, 不玩了!\r\n"); }//hello( int isError(char* y) { // 看輸入有沒非數字或是有沒相同數字 // 若有錯則回傳 1, 無錯回傳 0 if(y[0] == '-') return 0; // "-" 開頭不檢查 :-) why? if(y[0] == 'x') return 1; // 測試用 :-) // 其他留給你寫 :-) return 0; // assume no error }//isError(char*