這裡只有印出 BATNUM.txt(bat.htm), bat0.c, bat2.c, 
 以及完整版的 bat6ok.c, 和 Java 版的 bat6ok.java
 其他的請自行看  目錄內 各個 file 

Purpose:  
       也是練習使用亂數,與了解策略遊戲(Strategy game) 
  (1)透過這個練習,你將更了解程式庫 rand( ) 和 srand( ) 的用途與用法, 
     以及更熟悉 PRNG (Pseudo Random Number Generator;亂數產生器)與
     程式庫 time(0) 用途(會傳回一個整數, 從1970/01/01 0:0:0算至今秒數);
  (2)了解策略遊戲(Strategy game)與如何在可以贏的時候做出贏的策略!
     或說如何才能 "儘可能贏" ? 請上網查"策略遊戲"大略看看!
  (3)這BATNUM 只要用到取餘數 %, 比 NIM 遊戲用 xor 運算的應用簡單。

Description:
   BATNUM game (數字大戰) 是一個古老但簡單的策略遊戲(Strategy game);
是兩人從一堆石頭輪流拿的遊戲, 
每次最少要拿一個,最多可以拿幾個石頭要先規定好! (用亂數決定)
(可改成輪流從 1 喊數字,每次可以喊幾個要先規定好)
當然也要先約定好拿到後一個的贏或是輸! (用亂數決定)
這個遊戲其實當各項初始值都說好之後, 
先拿的會贏還是後拿的會贏就已經定案!
所以要由誰先拿呢?
若電腦程式要耍賴, 先拿會贏就自己先拿, 先拿會輸則讓 User 先拿:-)
但這樣 User 會抗議, 所以誰先拿就讓  User 自己決定!! 
不太會寫的同學請依序看並測試這些範例: 
   bat.htm  題目說明
   bat0.c   可以拿這版本去修改
   bat2.c   也是未完成版
   bat3.c  接近完成版, 目前沒有防呆, 電腦也不一定會贏
   bat5.c  沒有防呆, 但電腦會想辦法贏
   bat6ok.c  完成版, 有防呆 !  且電腦會想辦法贏!!
   bat6ok.java   從 bat6ok.c 改寫的 Java 版

   另一個 Java 檔案 bat7.java 須用到 c2java.java, 也是 Java版的 BATNUM

/// 寫程式的秘訣: 
//     大事化小, 小事化無!       上司管下司, 鋤頭管畚箕 !
//     ^^^^^^^^^^^^^^^^^^       ^^^^^^^^^^^^^^^^^^^^^^^
//  再次提醒,  把握 "大哥叫小弟做事" 的原則, 或是立委包工程分包出去的作法!
// 就是..
//  把工作作切開, 分給一個個的小弟(函數;function, 函式), 然後組織起來就完成了!
//


   01 //BATNUM.txt  --  BATtle of NUMbers   數字大戰
   02 
   03    int nStone, maxTake;  // 總石頭數, 最多可拿幾個?
   04    boolean lastToWin = true; // 拿最後一個贏還是輸?
   05 int main( ) {
   06    //BATtle of NUMbers
   07    hello( ); // welcome message
   08    playAgain = true;
   09    while(playAgain) {
   10       prepareGame( );
   11       userFirst = askUserFirst( );
   12       playGame( );
   13       playAgain = askPlayAgain( );
   14    }
   15    print("Bye bye\n"); return 0;
   16 } // main
   17 //======================
   18 void hello( ) {
   19    // welcome message and/or game rules
   20 }
   21 void prepareGame( ) {
   22     // 用亂數 生出 遊戲所需的各個 Global variables
   23     //nStone = 用亂數取得 15 .. 31;
   24     //maxTake = 用亂數取得 3..7 ;
   25     //用亂數決定 lastToWin 是 true 還是 false
   26 
   27 }
   28 boolean askUserFirst( ) {
   29    // 若 USER 要先拿, 就傳回 1 
   30    return (38==38);  // YES / TRUE
   31 }
   32 boolean askPlayAgain( ) {
   33    // 問user 並讀入答案, 若 USER 要繼續玩, 就傳回 true 
   34    return false;  // NO / FALSE 表示不完了 :-) 
   35 }
   36 void userTurn( ) {
   37    // nTake = 問 USER 要拿幾個;
   38    // 檢查 nTake 是否合乎規定? 若不符合則要求 user 重新輸入 
   39    // 然後當然要從 nStone 減去 nTake
   40 }
   41 void computerTurn( ) {
   42   // 先寫隨便拿但要合乎規定, 就是取 1..min(maxTake, nStone) 的亂數 
   43   // 再想出可贏就會贏的策略 (很簡單 :-)
   44   // Hint: 拿 max(1, (nStone - xxx) % (1+maxTake) ) 就會贏
   45   //    其中 xxx 是  0  if lastToWin is true
   46   ///        xxx 是  1  if lastToWin == false
   47 }
   48 void playGame( ) {
   49   // user and the computer take Turn until no more stones left
   50   // if(userFirst) userTurn( );
   51   // Loop until no more stone
   52   //   computerTurn( ); 
   53   //   if no more stone then leave the Loop;
   54   //   userTurn( );
   55   // end Loop
   56   // Judge the game result and print some message..
   57   // 如何判斷誰輸誰贏? 須知道誰拿走最後一個! 
   58   // 注意拿最後一個是輸還是贏? 
   59   //   (lastToWin == true 表示拿到最後一個的贏 )
   60 } // playGame


 

D:\> linenum < bat0.c
   01 //bat0.c  -- prototype by tsaiwn@csie.nctu.edu.tw
   02 //BATtle of NUMbers
   03 // === 以下是要 讓 do{...}while(x); 可寫成repeat...until(!(x));
   04 #define repeat  do {
   05 #define until(x)   } while(! (x) )
   06 #define bool  int
   07 //^^^^^^^^^^^^^^^^^^ 因為 C 不認識 bool, 用 int 代替;也可用enum 
   08 #include <stdio.h>
   09 #include <stdlib.h>
   10 #include <time.h>
   11 //
   12 // define some global variables for the Game
   13 int nStone; // number of Stone
   14 int maxTake; // max stone to take
   15 bool userFirst, playAgain;   // 是否 USER 先拿?  是否要繼續玩?
   16 // more variable needed? 想到再補上來
   17 //
   18 // 先把用到的各小弟 (function; 函數; 函式) 宣告在這 ..
   19 void hello( ), prepareGame( ), playGame( );  // 看名稱就知道意思
   20 bool askUserFirst( ), askPlayAgain( );
   21 void userTurn(void), computerTurn(void);  // take turn to play
   22 //
   23 int main( ) {   // 把工作都儘量分給 function, 讓 main 看起來很乾爽!
   24    hello( );
   25    // 必要時可做 srand(time(0));  //用時間做亂數種子, 就是 randomize
   26    repeat
   27       prepareGame( );
   28       userFirst = askUserFirst( );
   29       playGame( );
   30       playAgain = askPlayAgain( );
   31    until( ! playAgain );
   32    printf("Thank you for your play.\n");
   33    return 0;
   34 } // main
   35 
   36 void hello( ) {
   37    // welcome message and/or game rules
   38 }
   39 void prepareGame( ) {
   40    // 用亂數 rand( )生出 遊戲所需的各個 Global variables
   41 }
   42 bool askUserFirst( ) {
   43    // 若 USER 要先拿, 就傳回 1 
   44    return (38==38);  // YES / TRUE; 因為 C 不認識 true/false
   45 }
   46 bool askPlayAgain( ) {
   47    // 若 USER 要繼續玩, 就傳回 1 
   48    return (38==49);  // NO / FALSE; 因為 C 不認識 true/false
   49 }
   50 void userTurn( ) {
   51    // 問 USER 要拿幾個存入 nTake, 但要 check 是否合乎規定!
   52    // 然後當然要從 nStone 減去 nTake
   53 }
   54 void computerTurn( ) {
   55   // 先寫隨便拿但要合乎規定, 再想出可贏就會贏的策略 (很簡單 :-)
   56 }
   57 void playGame( ) {
   58   // user and the computer take Turn until no more stones left
   59   // if(userFirst) userTurn( );
   60   // Loop until no more stone
   61   //   computerTurn( ); 
   62   //   if no more stone then leave the Loop;
   63   //   userTurn( );
   64   // end Loop
   65   // Judge the game result and print some message..
   66   // 如何判斷誰輸誰贏? 須知道誰拿走最後一個! 拿最後一個是輸還是贏?
   67 } // playGame


 
D:\> linenum < bat2.c
   01 //bat2.c  -- @CopyLeft by tsaiwn@csie.nctu.edu.tw
   02 //BATtle of NUMbers;   ==> try this:  TCC -DDEBUG bat2.c
   03 #define repeat  do {
   04 #define until(x)   } while(! (x) )
   05 #define bool  int
   06 #define TRUE (38==38)   // good idea, works even in Java Language
   07 #define FALSE (38==49)   // C 不認識 true / false
   08 
   09 #include <stdio.h>
   10 #include <stdlib.h>
   11 #include <time.h>
   12 
   13 #define MAX_STONE 31
   14 #define MIN_STONE 15
   15 #define MAX_TAKE 9
   16 
   17 // define some global variables for the Game
   18 int nStone; // number of Stone
   19 int maxTake; // max stone to take for some game
   20 bool lastToWin;  // Win or Lose if took last one stone?
   21 bool userFirst, playAgain;
   22 ///
   23 enum player {USER, COMPUTER};  // 這樣寫後面可以用USER/COMPUTER
   24 enum player who; // who's turn? who is taking the stone? 輪到誰?
   25 
   26 void hello( ), prepareGame( ), playGame( );
   27 bool askUserFirst( ), askPlayAgain( );
   28 void userTurn( ), computerTurn( );
   29 
   30 int main( ) {
   31    hello( ); 
   32    srand(time(0));   // randomize; make it TRUE random
   33    repeat
   34       prepareGame( );
   35       userFirst = askUserFirst( );
   36       playGame( );
   37       playAgain = askPlayAgain( );
   38    until( ! playAgain );
   39    printf("Thank you for your play.\n");
   40    return 0;
   41 }
   42 void hello( ) {  
   43 }
   44 void prepareGame( ) {
   45    char msg[ ][88]={"Lose the game.", "win the game."};
   46    nStone = MIN_STONE + rand( ) % (MAX_STONE-MIN_STONE+1);
   47    maxTake = 3 + rand( ) % (MAX_TAKE -3 +1);  // 3..
   48    lastToWin = (rand( )%2 == 1);  // half chance 一半的機會
   49    printf("\nThere are %d stones.\n", nStone);
   50    printf("At least take 1, at most %d stones.\n", maxTake);
   51    printf("The one who take the last one will ");
   52    printf("%s\n", msg[lastToWin]); // 拿最後一個輸還是贏?
   53 #ifdef DEBUG
   54    printf("lastToWin=%d\n", lastToWin);
   55 #endif
   56 } // prepareGame
   57 bool askUserFirst( ) {
   58    static char buf[99];
   59    fprintf(stderr, "Do you want to go first(Y, N)? ");
   60    fgets(buf, sizeof(buf), stdin);
   61    if(buf[0]=='N' || buf[0]=='n') return FALSE; //no
   62    if(buf[0]==0) return FALSE;  // no!  C不認識 true/false
   63    return TRUE;  //  Yes otherwise
   64 }



   65 bool askPlayAgain( ) {
   66    static char buf[99];
   67    fprintf(stderr, " Play again(Y, N)? ");
   68    fgets(buf, sizeof(buf), stdin);
   69    if(buf[0]=='N' || buf[0]=='n') return FALSE; //no
   70    if(feof(stdin)) return FALSE;  // EOF encounted
   71    return TRUE;  // Yes
   72 } // askPlayAgain
   73 void playGame( ) {
   74    int userWin=1; // Local variable is enough here
   75    if(userFirst) userTurn( );   // userFirst 是 global variable
   76    else printf(" OK. I go first.\n");
   77    while(nStone > 0 ) {
   78       computerTurn( );
   79       if(nStone <= 0) break; // gameOver
   80       userTurn( );
   81    } // game Over when leave the while Loop
   82    userWin = 1; // assume USER win
   83    if(lastToWin && (who == COMPUTER) ) userWin = 0; // 這樣 USER 輸!
   84    if( (!lastToWin) && (who == USER) ) userWin = 0; // USER 也是輸
   85    if(userWin) printf(" Congratulations! You win!\n");
   86    else printf(" Sorry, I won! Ha ha!\n");
   87 } // playGame
   88 void userTurn( ) { 
   89    int nTake, canTake;  // canTake 是要算出這次可拿幾個?
   90    static char buf[99];
   91    who = USER;  // now USER 's turn  記住輪到 USER
   92    canTake = maxTake;  // 照規定最多只能拿取 maxTake
   93    if(nStone < maxTake) canTake = nStone;  // 沒那麼多了
   94    printf(" How many you want to take(1..%d)? ", canTake);
   95    //讀取 USER 要拿幾個, then check if the nTake is leagle ?
   96    // .. 若不符規定則要求 USER 重新輸入, 直到 nTake 合乎規定
   97    // .. 也可寫成若輸入負數表示 USER give up, 就結束此 game :-(
   98    nStone -= nTake;   // 阿就拿走 nTake 個啊
   99    if(nStone == 0) printf(" You just took the last stone.\n");
  100    else printf(" %d stone(s) left.\n", nStone);
  101    return;
  102 } // userTurn
  103 void computerTurn( ) {
  104    int nTake = 1;
  105    who = COMPUTER;  // now is COMPUTER 's turn 記住輪到 COMPUTER
  106    nTake = 1 + nStone % maxTake;   // 隨便拿
  107    if(nTake > nStone) nTake = nStone; // 沒那麼多! 只剩 nStone 個
  108    // 請改為可以贏就要贏
  109    // 必贏的策略?  須考慮拿最後一個贏還是輸
  110    /// 這策略很簡單! 先令 nTake = nStone;
  111    ///  然後若拿最後一個是輸則令 nTake = nTake - 1; 表留一個給對手拿
  112    ///   再來, 令 nTake = nTake % (1+maxTake); 這樣拿就會贏
  113    ///   若是算出 nTake 為 0 則表示必輸的, 就先拿一個等對手出錯!
  114    /// ///
  115    nStone -= nTake;   // 阿就拿走 nTake 個啊
  116    // print out some message
  117    return;
  118 } // computerTurn



 

D:\> linenum < bat6ok.c
   01 //bat6ok.c  -- @CopyLeft by tsaiwn@csie.nctu.edu.tw
   02 //BATtle of NUMbers
   03 //modified by __學號__  _姓_名_  and  __學號__  _姓_名_ 
   04 ///
   05 // 若用 Java 則須用 class 包起來; class名稱須與檔案名稱相同 !
   06 // 且 main 必須 public static void main(String xxx[ ]) {
   07 #define repeat  do {
   08 #define until(x)   } while(! (x) )
   09 
   10 #include <stdio.h>
   11 #include <stdlib.h>
   12 #include <time.h>
   13 
   14 #define MAX_STONE 31
   15 #define MIN_STONE 18
   16 #define MAX_TAKE 9
   17 //Java 內以上須用這樣 public final static int MAX_TAKE = 9;
   18 
   19 #ifndef __cplusplus
   20   typedef enum {false=0, true } bool; // C 不認識 這些
   21 #endif
   22 
   23 // define some global variables for the Game
   24 int nStone; // number of Stone
   25 int maxTake; // max stone to take for some game
   26 
   27 bool lastToWin;  // Win or Lose if took last one stone?
   28 bool userFirst, playAgain;
   29 /// 
   30 enum player {USER, COMPUTER};  // 這樣寫後面可以用USER/COMPUTER
   31 enum player who; // who is taking the stone? 輪到誰?
   32   // Java 的 enum 請看本檔案最後的補充 ! 
   33 void hello( ), prepareGame( ), playGame( );
   34 bool askUserFirst( ), askPlayAgain( );
   35 void userTurn( ), computerTurn( );
   36 void randomize( ) { srand(time(0));  } // 抓時間來當作亂數種子
   37 
   38 int main( ) {
   39    hello( ); 
   40    randomize( );  // randomize; make it true random
   41    repeat
   42       prepareGame( );
   43       userFirst = askUserFirst( );
   44       playGame( );
   45       playAgain = askPlayAgain( );
   46    until( ! playAgain );
   47    printf("Thank you for your play.\r\n");
   48    return 0;
   49 }
   50 
   51 void hello( ) {  
   52    printf("Welcome to the BATNUM game ...\r\n");
   53 }
   54 
   55 void prepareGame( ) {
   56    char msg[ ][88]={"Lose the game.", "win the game."};
   57    nStone = MIN_STONE + rand( ) % (MAX_STONE-MIN_STONE+1);
   58    maxTake = 3 + rand( ) % (MAX_TAKE -3 +1);  // 3..
   59    lastToWin = rand( )%2 == 1;  // half chance 一半的機會
   60    printf("\r\nThere are %d stones.\r\n", nStone);
   61    printf("At least take 1, at most %d stones.\r\n", maxTake);
   62    printf("The one who take the last stone will ");
   63    printf("%s\r\n", msg[lastToWin]); // 拿最後一個輸還是贏?
   64 #ifdef DEBUG
   65    printf("lastToWin=%d\n", lastToWin);
   66 #endif
   67 } // prepareGame
   68 

   69 bool askUserFirst( ) {
   70    static char buf[99];
   71    fprintf(stderr, "Do you want to go first(Y, N)? ");
   72    fgets(buf, sizeof(buf), stdin);
   73    if(buf[0]=='N' || buf[0]=='n') return false; //no
   74    if(buf[0]==0) return false;  // no!  C不認識 true/false
   75    return true;  //  Yes otherwise
   76 }
   77 
   78 bool askPlayAgain( ) {
   79    static char buf[99];
   80    fprintf(stderr, " Play again(Y, N)? ");
   81    fgets(buf, sizeof(buf), stdin);
   82    if(buf[0]=='N' || buf[0]=='n') return false; //no
   83    if(feof(stdin)) return false;  // EOF encounted
   84    return true;  // Yes
   85 } // askPlayAgain
   86 
   87 void playGame( ) {
   88    bool userWin=true; // assume user win
   89    if(userFirst) userTurn( );
   90    else printf(" OK. I go first.\r\n");
   91    while(nStone > 0 ) {
   92       computerTurn( );
   93       if(nStone <= 0) break; // gameOver
   94       userTurn( );
   95    } // game Over when leave the while Loop
   96    userWin = true; // assume you win
   97    if(lastToWin && (who == COMPUTER) ) userWin = false; // user 輸!
   98    if( (!lastToWin) && (who == USER) ) userWin = false; // user 也是輸
   99    if(userWin) printf(" Congratulations! You win!\r\n");
  100    else printf(" Sorry, I won! Ha ha!\n");
  101 } // playGame
  102 
  103 void userTurn( ) { 
  104    int nTake, canTake;
  105    static char buf[99];
  106    who = USER;  // now USER 's turn  記住輪到 USER
  107    canTake = maxTake;  // 照規定最多只能拿取 maxTake
  108    if(nStone < maxTake) canTake = nStone;  // 沒那麼多了
  109    printf(" How many you want to take(1..%d)? ", canTake);
  110    fgets(buf, sizeof(buf), stdin);
  111    nTake = (int)atol(buf);  
  112    // check if the nTake is legal ?
  113    // .. 若不符規定則要求 USER 重新輸入
  114    // .. 也可寫成若輸入負數表示 give up, 就結束此 game :-(
  115    while(nTake < 1 || nTake > canTake) { // illegal
  116       printf("  ?? Error, please re-type(1..%d)? ", canTake);
  117       fgets(buf, sizeof(buf), stdin);
  118       nTake = (int)atol(buf);  
  119    }
  120    nStone -= nTake;
  121    if(nStone == 0) printf(" You just took the last stone.\r\n");
  122    else printf(" %d stone(s) left.\r\n", nStone);
  123    return;
  124 } // userTurn
  125 
       // ( 下頁還有 )










  126 void computerTurn( ) {
  127    int nTake = 1;
  128    who = COMPUTER;  // now is COMPUTER 's turn 記住輪到 COMPUTER
  129    // 必贏的策略?  須考慮拿最後一個贏還是輸
  130    nTake = nStone;
  131    if(!lastToWin) nTake--;  // 拿最後一個是輸ㄝ, 留一個給對手
  132    nTake = nTake % (1+maxTake);
  133    if(nTake == 0) nTake = 1; // 電腦會輸, 先賴皮拿一個等對手拿錯:-)
  134    if(nTake > nStone) nTake = nStone; // 沒那麼多! (不可能發生)
  135   ///
  136    nStone -= nTake;  // 拿走啊
  137    printf(" I take %d stone", nTake);
  138    if(nTake > 1) printf("s");  // 複數
  139    printf(" this time.");
  140    if(nStone == 0) printf(" I just took the last stone.\r\n");
  141    else printf(" Now %d stone(s) left.\r\n", nStone);
  142 } // computerTurn
  143 ///   === === END of the program BATNUM === ===

  144 /*** 關於 Java 的 enum: 在 C/C++ 的 enum 其實是整數, 可 Java 不是!
  145   Java 的 enum 是會變成 class ! 請編譯完後看看目錄中多出的 class 檔!
  146   以下是個簡單範例, 可編譯並且執行:
  147   //gg.java  -- test enum in Java, by tsaiwn@csie.nctu.edu.tw
  148   //avac gg.java
  149   //java gg
  150   //javap gg$player
  151   class gg {
  152        enum player {USER, COMPUTER}; 
  153     public static void main(String xx[ ]) {
  154        player yy = player.USER;
  155        System.out.println("user="+yy);
  156        if(yy == player.USER) 
                  System.out.println("YES yy is player.USER");
  157        else System.out.println("NO hahaha!");
  158     }//main
  159   } // class gg
  160 *************************************************************/



 
   01 //bat6ok.java -- modified from bat6ok.c
   02 //javac bat6ok.java
   03 //java bat6ok
   04 ///////////////////////////////////////////////////
   05 //bat6ok.c  -- @CopyLeft by tsaiwn@csie.nctu.edu.tw
   06 //BATtle of NUMbers
   07 //modified by __學號__  _姓_名_  and  __學號__  _姓_名_ 
   08 ///
   09 // 若用 Java 則須用 class 包起來; class名稱須與檔案名稱相同 !
   10 // 且 main 必須 public static void main(String xxx[ ]) {
   11 import java.io.*;
   12 import java.util.*;
   13 
   14 class bat6ok {   //  filename should be the same as class name
   15 
   16  public final static int MAX_STONE = 31;
   17  public final static int MIN_STONE = 18;
   18  public final static int MAX_TAKE = 9;
   19 
   20  // define some global variables for the Game
   21   int nStone; // number of Stone
   22   int maxTake; // max stone to take for some game
   23 
   24   boolean lastToWin;  // Win or Lose if took last one stone?
   25   boolean userFirst, playAgain;
   26   /// 
   27 enum player {USER, COMPUTER};  // 這樣寫後面可以用USER/COMPUTER
   28  player who;  // who is taking the stone? 輪到誰? 注意 Java 寫法 !
   29 
   30 public static void main(String xxx[  ]) {
   31     bat6ok ggyy = new bat6ok( );
   32     ggyy.main( );
   33 }
   34 bat6ok( ) {   // constructor
   35      prepareIO( );
   36 }
   37 BufferedReader cin=null;
   38 PrintStream cout=null;
   39 
   40 void prepareIO( ) {
   41      try {
   42         cin =  new BufferedReader(
   43                      new InputStreamReader( System.in )  );
   44         cout = System.out;
   45      }catch(Exception e) {  }
   46 }
   47 
   48 int main( ) { // 原來的 main( ); Note that it has different prototype
   49    hello( ); 
   50    randomize( );  // randomize; make it true random
   51    do {
   52       prepareGame( );
   53       userFirst = askUserFirst( );
   54       playGame( );
   55       playAgain = askPlayAgain( );
   56    } while( playAgain );
   57    cout.printf("Thank you for your play.\r\n");
   58    return 0;
   59 }
   60 
   61 int rand( ) {
   62      return (int) (32767* Math.random( ) );
   63 }
   64 void srand(int seed) {
   65 } // not necessary :-)
   66 void randomize( ) {
   67      srand((int)System.currentTimeMillis( ) );
   68 }
   69 
   70 void hello( ) {  
   71    cout.printf("Welcome to the BATNUM game ...\r\n");
   72 }
   73 
   74 void prepareGame( ) {
   75    String msg[ ]={"Lose the game.", "win the game."};
   76    nStone = MIN_STONE + rand( ) % (MAX_STONE-MIN_STONE+1);
   77    maxTake = 3 + rand( ) % (MAX_TAKE -3 +1);  // 3..
   78    lastToWin = rand( )%2 == 1;  // half chance 一半的機會
   79    cout.printf("\r\nThere are %d stones.\r\n", nStone);
   80    cout.printf("At least take 1, at most %d stones.\r\n", maxTake);
   81    cout.printf("The one who take the last stone will ");
   82    int kkk;   kkk = 0;
   83    if(lastToWin) kkk = 1;
   84    cout.printf("%s\r\n", msg[kkk]); // 拿最後一個輸還是贏?
   85 } // prepareGame
   86 
   87 boolean askUserFirst( ) {
   88     cout.printf( "Do you want to go first(Y, N)? ");
   89     String buf = null;
   90     try {
   91           buf = cin.readLine( );
   92     } catch(Exception e) { }
   93     if(buf == null) return false;
   94     if(buf.length( )==0) buf = "n";
   95     if(buf.charAt(0)=='N' || buf.charAt(0)=='n') return false; //no
   96     if(buf.charAt(0)==0) return false;  // no! 
   97     return true;  //  Yes otherwise
   98 }
   99 
  100 boolean askPlayAgain( ) {
  101     cout.printf( "Do you want to go first(Y, N)? ");
  102     String buf = null;
  103     try {
  104           buf = cin.readLine( );
  105     } catch(Exception e) { }
  106     if(buf == null) return false;
  107     if(buf.length( )==0) buf = "n";
  108     if(buf.charAt(0)=='N' || buf.charAt(0)=='n') return false; //no
  109     if(buf.charAt(0)==0) return false;  // no! 
  110     return true;  // Yes
  111 } // askPlayAgain
  112 
  113 void playGame( ) {
  114    boolean userWin=true; // assume user win
  115    if(userFirst) userTurn( );
  116    else cout.printf(" OK. I go first.\r\n");
  117    while(nStone > 0 ) {
  118         computerTurn( );
  119         if(nStone <= 0) break; // gameOver
  120         userTurn( );
  121    } // game Over when leave the while Loop
  122    userWin = true; // assume you win
  123    if(lastToWin && (who == player.COMPUTER) ) userWin = false; // user 輸!
  124    if( (!lastToWin) && (who == player.USER) ) userWin = false; // user 也是輸
  125    if(userWin) cout.printf(" Congratulations! You win!\r\n");
  126    else cout.printf(" Sorry, I won! Ha ha!\n");
  127 } // playGame
  128 
  129 void userTurn( ) { 
  130    int nTake, canTake;
  131    String buf;
  132    who = player.USER;  // now USER 's turn  記住輪到 USER
  133    canTake = maxTake;  // 照規定最多只能拿取 maxTake
  134    if(nStone < maxTake) canTake = nStone;  // 沒那麼多了
  135    cout.printf(" How many you want to take(1..%d)? ", canTake);
  136    try {
  137         buf = cin.readLine( );
  138         if(buf==null) buf="0";
  139         nTake = Integer.parseInt(buf);
  140    }catch(Exception e) { nTake = 0;  }
  141    while(nTake < 1 || nTake > canTake) { // illegal
  142       cout.printf("  ?? Error, please re-type(1..%d)? ", canTake);
  143       try {
  144            buf = cin.readLine( );
  145            if(buf==null) buf="0";
  146            if(buf.length( )==0) buf = "0";
  147            nTake = Integer.parseInt(buf);
  148       }catch(Exception e) {  nTake = 0; }
  149    }
  150    nStone -= nTake;
  151    if(nStone == 0) cout.printf(" You just took the last stone.\r\n");
  152    else cout.printf(" %d stone(s) left.\r\n", nStone);
  153    return;
  154 } // userTurn
  155 
  156 void computerTurn( ) {
  157    int nTake = 1;
  158    who = player.COMPUTER;  // now is COMPUTER 's turn 記住輪到 COMPUTER
  159    // 必贏的策略?  須考慮拿最後一個贏還是輸
  160    nTake = nStone;
  161    if(!lastToWin) nTake--;  // 拿最後一個是輸ㄝ, 留一個給對手
  162    nTake = nTake % (1+maxTake);
  163    if(nTake == 0) nTake = 1; // 電腦會輸, 先賴皮拿一個等對手拿錯:-)
  164    if(nTake > nStone) nTake = nStone; // 沒那麼多! (不可能發生)
  165   ///
  166    nStone -= nTake;  // 拿走啊
  167    cout.printf(" I take %d stone", nTake);
  168    if(nTake > 1) cout.printf("s");  // 複數
  169    cout.printf(" this time.");
  170    if(nStone == 0) cout.printf(" I just took the last stone.\r\n");
  171    else cout.printf(" Now %d stone(s) left.\r\n", nStone);
  172 } // computerTurn
  173 
  174 } // class bat6ok
  175 ///   === === END of the program BATNUM === ===



*** 提醒要 Stepwise refinement 逐步改進 !