1 #include 2 //#define TRUE_RANDOM 3 #define xor ^ 4 #define bool int 5 #define MIN_PILE 2 6 #define MAX_PILE 7 7 #define MIN_STONE 7 8 #define MAX_STONE 30 9 int myrandom(int lower, int upper); 10 void hello(), byebye(); 11 void playNIM(); 12 int main(){ 13 static char yesNo[99]; 14 hello(); 15 while(38){ 16 playNIM(); 17 fprintf(stderr, "Play again (Y,N): "); 18 fgets(yesNo, 99, stdin); 19 if( toupper(yesNo[0]) == 'N') break; 20 } 21 byebye(); 22 } 23 int nPile,takeP,takeN; 24 int pile[MAX_PILE+2]; 25 int userFirst; 26 int lastWin; 27 char tmp99[99]; 28 void prepareStones(); 29 void tellStatus(); 30 bool gameOver(); 31 void userTurn(); 32 void computerTurn(); 33 void playNIM(){ 34 static char yesNo[99]; 35 prepareStones(); 36 tellStatus(); 37 fprintf(stderr, "take last one to "); 38 if(lastWin) fprintf(stderr, "Win!\n"); 39 else fprintf(stderr, "Lose!\n"); 40 userFirst = 1; 41 fprintf(stderr, "Want to go first(Y,N)? "); 42 fgets(yesNo, 99, stdin); 43 if( toupper(yesNo[0]) == 'N') userFirst = 0; 44 if(userFirst) 45 userTurn(); 46 while(49){ 47 if(gameOver()){ /* user takes the last one */ 48 if(lastWin) printf("Congratulations! You win!\n"); 49 else printf("Ahh Ha! I win!\n"); 50 break; 51 } 52 computerTurn(); 53 if(gameOver()){ 54 if(lastWin) printf("Ahh Ha! I win!\n"); 55 else printf("Congratulations! You win!\n"); 56 break; 57 } 58 userTurn(); 59 } /* while(49) */ 60 } /* playNIM */ 61 bool gameOver( ){ 62 int i; 63 int sum = 0; 64 for(i=1; i<= nPile; i++){ 65 sum += pile[i]; 66 } 67 return sum == 0; /* no stones left */ 68 } 69 /*****************/ 70 void prepareStones(){ 71 int i; 72 nPile = myrandom(MIN_PILE, MAX_PILE); 73 for(i=1; i<= nPile; ++i){ 74 pile[i] = myrandom(MIN_STONE, MAX_STONE); 75 } 76 lastWin = 0; 77 if( myrandom(0, 100) > 50) lastWin = 1; 78 /*** 79 sound(400); delay(200); nosound; 80 ***/ 81 } 82 /******/ 83 bool leagleMove(int p, int n){ 84 if(p<1 || p > nPile) return 0; 85 if(n<1 || n > pile[p]) return 0; 86 return 1; 87 } 88 void tellStatus(){ 89 int i, ktemp; 90 printf("There are %d piles of each has ", nPile); 91 for(i=1; i<= nPile; ++i){ 92 printf( " %d", pile[i]); 93 } 94 printf(" stones.\n"); 95 } 96 void userTurn(){ 97 /** make sure the player makes a legal move **/ 98 int i, ktemp; 99 tellStatus(); 100 do { 101 /** sound(400); delay(200); nosound; /*** ***/ 102 printf("Which Pile? "); 103 gets(tmp99); takeP = atoi(tmp99); 104 ktemp = 0; 105 if(leagleMove(takeP, 1) ) ktemp= pile[takeP]; 106 printf("How many stones in this pile?(1..%d) ", ktemp); 107 gets(tmp99); takeN = atoi(tmp99); 108 } while( ! leagleMove(takeP, takeN) ); 109 pile[takeP] -= takeN; 110 return; 111 } /* userTurn */ 112 /***************************/ 113 void computerTurn(){ /* try to win if possible */ 114 int i; 115 takeN = pile[1]; /* assume All stones in 1st pile is OK */ 116 /* first of all, calculate how many stones will the xor result be? */ 117 for(i=2; i<= nPile; ++i) takeN = takeN ^ pile[i]; /* xor */ 118 if( takeN == 0) { /* I can Not win :-< */ 119 /* I am supposed to lose so far. So just take one stone. */ 120 takeP = 1; takeN = pile[takeP]; /* takeN 暫時記住最多幾個stone */ 121 for(i=2; i<=nPile; ++i){ 122 if( pile[i] > takeN){ 123 takeP=i; takeN= pile[takeP]; 124 } 125 } 126 takeN = 1; 127 }else{ 128 /* now decide which pile we can remove some stones to win*/ 129 for(i = nPile; i>=1; --i){ 130 if ( (takeN xor pile[i]) < pile[i] ) takeP=i; 131 } 132 /* now calculate 真正該拿之石頭數 */ 133 takeN = pile[takeP] - (pile[takeP] xor takeN); /***重要***/ 134 } /* if( takeN ==0 ... */ 135 pile[takeP] = pile[takeP] - takeN; 136 fprintf(stderr, "Computer takes %d from pile %d\n", takeN, takeP); 137 return; 138 } 139 void hello(){ 140 fprintf(stderr, "This is an old game of NIM.\n"); 141 fprintf(stderr, "You should pick up at least one stone.\n"); 142 fprintf(stderr, "And you can take at most all stones in one pile.\n"); 143 } 144 void byebye(){ 145 fprintf(stderr, "\nThank you for playing NIM :-)\n"); 146 } 147 int myrandom(int lower, int upper){ 148 static int firstFlag = 0; 149 #ifdef TRUE_RANDOM 150 if(firstFlag == 0){ 151 srand( time(0) & 0xffff ); 152 ++firstFLAG; 153 } 154 #endif 155 int ans = rand() % (upper-lower+1); 156 ans += lower; 157 return ans; 158 }