//bat3.c -- @CopyLeft by tsaiwn@csie.nctu.edu.tw //BATtle of NUMbers ; 接近完成版, 目前沒有防呆, 電腦也不一定會贏 #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; // assume user win if(userFirst) userTurn( ); 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 you 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; 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); fgets(buf, sizeof(buf), stdin); nTake = (int)atol(buf); // check if the nTake is legale ? // .. 若不符規定則要求 USER 重新輸入 // .. 也可寫成若輸入負數表示 give up, 就結束此 game :-( nStone -= 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 == 0) nTake = 1; // at least have to take one if(nTake > nStone) nTake = nStone; // 沒那麼多! 只剩 nStone 個 nStone -= nTake; // 阿就拿走 nTake 個啊 printf(" I take %d stone", nTake); if(nTake > 1) printf("s"); // 複數 printf(" this time."); if(nStone == 0) printf(" I just took the last stone.\n"); else printf(" Now %d stone(s) left.\n", nStone); } // computerTurn