//bat2.c -- @CopyLeft by tsaiwn@csie.nctu.edu.tw //BATtle of NUMbers; ==> try this: TCC -DDEBUG bat2.c #define repeat do { #define until(x) } while(! (x) ) #define bool int #define TRUE (38==38) // good idea, works even in Java Language #define FALSE (38==49) // C 不認識 true / false #include #include #include #define MAX_STONE 31 #define MIN_STONE 15 #define MAX_TAKE 9 // define some global variables for the Game int nStone; // number of Stone int maxTake; // max stone to take for some game bool lastToWin; // Win or Lose if took last one stone? bool userFirst, playAgain; /// enum player {USER, COMPUTER}; // 這樣寫後面可以用USER/COMPUTER enum player who; // who's turn? who is taking the stone? 輪到誰? void hello( ), prepareGame( ), playGame( ); bool askUserFirst( ), askPlayAgain( ); void userTurn( ), computerTurn( ); int main( ) { hello( ); srand(time(0)); // randomize; make it TRUE random repeat prepareGame( ); userFirst = askUserFirst( ); playGame( ); playAgain = askPlayAgain( ); until( ! playAgain ); printf("Thank you for your play.\n"); return 0; } void hello( ) { } void prepareGame( ) { char msg[ ][88]={"Lose the game.", "win the game."}; nStone = MIN_STONE + rand( ) % (MAX_STONE-MIN_STONE+1); maxTake = 3 + rand( ) % (MAX_TAKE -3 +1); // 3.. lastToWin = (rand( )%2 == 1); // half chance 一半的機會 printf("\nThere are %d stones.\n", nStone); printf("At least take 1, at most %d stones.\n", maxTake); printf("The one who take the last one will "); printf("%s\n", msg[lastToWin]); // 拿最後一個輸還是贏? #ifdef DEBUG printf("lastToWin=%d\n", lastToWin); #endif } // prepareGame bool askUserFirst( ) { static char buf[99]; fprintf(stderr, "Do you want to go first(Y, N)? "); fgets(buf, sizeof(buf), stdin); if(buf[0]=='N' || buf[0]=='n') return FALSE; //no if(buf[0]==0) return FALSE; // no! C不認識 true/false return TRUE; // Yes otherwise } bool askPlayAgain( ) { static char buf[99]; fprintf(stderr, " Play again(Y, N)? "); fgets(buf, sizeof(buf), stdin); if(buf[0]=='N' || buf[0]=='n') return FALSE; //no if(feof(stdin)) return FALSE; // EOF encounted return TRUE; // Yes } // askPlayAgain void playGame( ) { int userWin=1; // Local variable is enough here if(userFirst) userTurn( ); // userFirst 是 global variable else printf(" OK. I go first.\n"); while(nStone > 0 ) { computerTurn( ); if(nStone <= 0) break; // gameOver userTurn( ); } // game Over when leave the while Loop userWin = 1; // assume USER win if(lastToWin && (who == COMPUTER) ) userWin = 0; // 這樣 USER 輸! if( (!lastToWin) && (who == USER) ) userWin = 0; // USER 也是輸 if(userWin) printf(" Congratulations! You win!\n"); else printf(" Sorry, I won! Ha ha!\n"); } // playGame void userTurn( ) { int nTake, canTake; // canTake 是要算出這次可拿幾個? static char buf[99]; who = USER; // now USER 's turn 記住輪到 USER canTake = maxTake; // 照規定最多只能拿取 maxTake if(nStone < maxTake) canTake = nStone; // 沒那麼多了 printf(" How many you want to take(1..%d)? ", canTake); //讀取 USER 要拿幾個, then check if the nTake is leagle ? // .. 若不符規定則要求 USER 重新輸入, 直到 nTake 合乎規定 // .. 也可寫成若輸入負數表示 USER give up, 就結束此 game :-( nStone -= nTake; // 阿就拿走 nTake 個啊 if(nStone == 0) printf(" You just took the last stone.\n"); else printf(" %d stone(s) left.\n", nStone); return; } // userTurn void computerTurn( ) { int nTake = 1; who = COMPUTER; // now is COMPUTER 's turn 記住輪到 COMPUTER nTake = 1 + nStone % maxTake; // 隨便拿 if(nTake > nStone) nTake = nStone; // 沒那麼多! 只剩 nStone 個 // 請改為可以贏就要贏 // 必贏的策略? 須考慮拿最後一個贏還是輸 /// 這策略很簡單! 先令 nTake = nStone; /// 然後若拿最後一個是輸則令 nTake = nTake - 1; 表留一個給對手拿 /// 再來, 令 nTake = nTake % (1+maxTake); 這樣拿就會贏 /// 若是算出 nTake 為 0 則表示必輸的, 就先拿一個等對手出錯! /// /// nStone -= nTake; // 阿就拿走 nTake 個啊 // print out some message return; } // computerTurn