//bullcow2.c -- Bullcow.c, version 2, by tsaiwn@csie.nctu.edu.tw /****** 注意這種一版改進一版的做法叫做 Step refinement 逐步改進! "想方法" --> "寫出" 程式! 、、、 Task: 練習 寫一個 公牛母牛遊戲 (又叫 幾 A 幾 B 遊戲), 電腦想給人猜 ! Purpose: to understand: (a)何謂Pseudo Random Number Generator(PRNG;亂數產生器)及其用法用途? (b)如何連續使用 rand( ) 生出四位不同的數字(或更多 digit)? (c)如何用兩層 Loop 交叉比對兩個 array 間相同元素? Hints: 請自己用 http://gogle.com 打入 "bulls and cows" 查詢 註: 關於"亂數"可用 http://gogle.com 打入 "PRNG wiki" 查詢 ******=====================================================******/ #include #include #define repeat do{ #define until(x) }while(!(x)) char yourGuess[5]; // Global variable, 故意的 ! void think(char*), getAnswer( ), checkAnswer(char*, char*, int*, int*); void hello( ) { printf("這是公牛母牛遊戲,請輸入 4位不同數字猜我想的數。\r\n"); printf("我將告訴你幾隻公牛(?A) 和 幾隻母牛(?B)\r\n"); printf("公牛 means 數字對位置也對; "); printf("母牛 means 數字對但位置不對。\r\n"); } int getYN( ) { } // 問 user YES/NO 後傳回 1 代表 "yes" or 0=="no" int main( ) { /** Pseudo code: **/ char myNum[5]; // 故意把 myNum[ ] 弄成 auto variable (自動變數) int nBull, nCow; // 幾 A (Bull)? 幾 B (Cow) ? int yyn; // yyn 為 要不要繼續玩? 0 不要 hello( ); // welcome message and information .. repeat printf("Let me ..讓我想好四位數字...OK.\r\n"); think(myNum); // 填入 myNum[ ] while (38== 38 ) { // true, for(;;){ // Loop forever printf(" Your guess:"); getAnswer( ); // read into yourGuess[ ] //if(輸入 -1){ 告訴他答案 並 break; } // 離開 目前的 loop checkAnswer(myNum, yourGuess, &nBull, &nCow); //address if(nBull == 4){ //印出恭喜猜對了 break; // do NOT forget break; } // 印出 nBull 幾隻公牛, 幾隻母牛 nCow } // while printf(" 繼續玩(y, n)? "); yyn = getYN( ); //讀取回答, 然後 yes 回傳 1, 否則回傳 0 until( yyn == 0 ); // repeat ... until(x); 等於 do{...}while(!(x)); printf("\r\nBye\n"); return 0; // C 規定 main 要回傳一個整數 }//main( void think(char x[ ]) { // 想一想, why 用 5 char 不是 4 char 就好? // 函數 think( ) 用來想一個四位不重複的數字! // 如何讓四位不同? 這比較難一點點 (也很簡單啦 :-) // 可先寫一假的: (以後再用rand()或random( )生出亂數, see "man rand") x[0] = '5'; x[1] = '3'; x[2] = '8'; x[3] = '0'; // 聽說 5380 代表 "我想抱您" :-) x[4] = 0; // 剛好代表字串結束 ! 如此 x[ ] 可當字串用, printf 用 %s // 可先都用 = '0' + rand( ) % 10; 但先不檢查是否重複看看會怎樣? }// think( void getAnswer( ) { // 不傳參數, 用 Global variable; 你的就是我的 :-) /** 函數 getAnswer( ) 用來讀入一個四位不重複的數字, 放 yourGuess[] 中 不傳參數, 直接用 yourGuess (global 變數); 你要用像 think(myNum) 那樣有參數的寫法也可以啦! ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^******/ fgets(yourGuess, sizeof(yourGuess) ,stdin); //注意 yourGuess是Global } void checkAnswer(char myn[5], char ygs[5], int*nb, int*nc) { /** 函數 checkAnswer(char *, char *, int*nb, int*nc) 也很簡單! 用 loop 比比看到底 前兩參數 myn[5] 和 ygs[5] (都是 char array) 中 有幾位數字同且位置同(公牛)? 用 *nb 記住並傳回去; 又有幾位是數字同但是位置不同(母牛)? 用 *nc 記住並傳回去! (P.S. 這招 &arg 傳給參數 *para 又稱 call by address to pointer) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^==========================******/ int i,k; // for Loop *nb = *nc =0; // C 語言強調怎麼宣告就怎麼用! *nb 與 *nc 都是 int for(i=0; i<=3; i++){ // 算出公牛放 *nb , 數字對且位置也對 if(myn[i] == ygs[i]) *nb = *nb +1; // *nb 是一個 int //內部另一 for Loop算母牛數放 *nc, 這留給你算囉:-) } } /** 更進一步練習題: 上面說的是人猜電腦想的, 如過你覺得太也簡單, 那就, 寫一個電腦會猜人想的 公牛母牛遊戲 你每次在電腦猜完後告訴它是 幾隻公牛 幾隻母牛 *** 再來, 若還不過癮, 可以寫成 由人和電腦輪流對猜 !!! *****************************************************************/