1 #include <stdio.h> 2 #include <stdlib.h>
3 /* 4 具體思路如下: 5 1.定義一個二維數組chessboard[8][8],用於保存黑白雙方棋子的位置。如果數組元素為0,表示該單元格未落子;如果是-1,表示該單元格是黑子;如果是1,則表示該單元格是白子。 6 2.當一方下棋時,先檢查是否有位置可下,如果有則己方下棋,如果沒有就讓對手下棋。 7 3.若玩家下,需要等待玩家輸入棋子坐標,然后執行翻轉對手棋子操作。 8 4.若計算機下,程序需對棋盤所有可以落子的位置進行判斷,找出最佳的落子位置,然后執行翻轉對手棋子操作。
9 5.重復步驟2~4,直到棋盤已滿或雙方都不能下子時結束。
10 */ 11 12 void Output(char chessboard[][8]); //顯示棋盤中的下子情況 13 int Check(char chessboard[][8],int moves[][8],char player);//檢查一方是否有位置下子 14 void PlayStep(char chessboard[][8],int row,int col,char player);//在指定位置下棋 15 void AutoPlayStep(char chessboard[][8],int moves[][8],char player);//計算機思考下子 16 int GetMaxScore(char chessboard[][8],char player);//獲取分數 17 int BestPlay(char chessboard[][8],int moves[][8],char player);//最優下子位置 18 19 20 int main(){ 21 char chessboard[8][8];//保存棋盤中各單元格下子的狀態 22 int isDown[8][8] = {0};//保存棋盤中的各個位置是否可以下子,可以下的位置為1,其余為0 23 int row,col,x,y; 24 int iCount = 0;//以下子的數量 25 int player = 0;//下棋方 26 int SkipPlay = 0;//重置下子的次數為0,若為2,則表示雙方都不能下子 27 int Score[2];//保存計算機和玩家的得分 28 29 char select,ch; 30 31 printf("黑白棋\n\n"); 32 printf("玩家執黑子先行,計算機執白,按Enter開始\n"); 33 34 35 scanf("%c",&select); 36 37 do{ 38 39 if(player==0){ 40 player = 1; 41 }else{ 42 player = 0; 43 } 44 45 for(row=0;row<8;row++){ 46 for(col=0;col<8;col++){ 47 chessboard[row][col]=0; 48 } 49 } 50 51 iCount = 4;//游戲開始的四顆棋子 52 chessboard[3][3] = chessboard[4][4] = 1; 53 chessboard[3][4] = chessboard[4][3] = -1; 54 55 printf("\n棋盤初始狀態:\n"); 56 Output(chessboard); 57 58 //雙方下棋 59 do{ 60 if(player==1){//玩家下棋(黑) 61 player = 0; 62 if(Check(chessboard,isDown,2)){ 63 while(1){ 64 fflush(stdin); 65 printf("輸入下子的位置(行,列):"); 66 scanf("%d%c",&x,&ch); 67 x--;//因為數組是從0開始存的 68 if(ch>='a'){ 69 y = ch - 'a' + 1; 70 } else{ 71 y = ch - 'A' + 1; 72 } 73 y--; 74 //判斷是否越界、是否已有棋子 75 if(x>=0&&x<8&&y>=0&&y<8&&isDown[x][y]){ 76 PlayStep(chessboard,x,y,2); 77 iCount++; 78 break; 79 }else{ 80 printf("坐標輸入有誤,請重新輸入。\n\n"); 81 } 82 } 83 84 printf("\n你下子之后的狀態:\n"); 85 Output(chessboard); 86 system("pause");
87
88 }else if(++SkipPlay < 2){//無效下子的次數小於2 89 fflush(stdin); 90 printf("你沒位置可下,按Enter讓計算機下子"); 91 scanf("%c",&select); 92 } else{ 93 printf("雙方都沒位置下子,游戲結束!\n"); 94 } 95 }else{//計算機下棋(白) 96 97 player = 1; 98 if(Check(chessboard,isDown,1)) { 99 SkipPlay = 0;//清除無效下子次數 100 AutoPlayStep(chessboard,isDown,1); //下子 101 iCount++; 102 printf("\n計算機下子后的狀態:\n"); 103 Output(chessboard); 104 }else if(++SkipPlay < 2){//無效下子的次數小於2 105 fflush(stdin); 106 printf("我沒位置可下,你走\n"); 107 scanf("%c",&select); 108 } else{ 109 printf("雙方都沒位置下子,游戲結束!\n"); 110 } 111 112 113 114 } 115 116 117 }while(iCount<64&&SkipPlay<2); 118 119 Output(chessboard); 120 Score[0] = Score[1] = 0;//清空幾份變量 121 122 for(row=0;row<8;row++){ 123 for(col=0;col<8;col++){ 124 if(chessboard[row][col]==-1){ 125 Score[0]++;//統計黑子數量 126 } 127 if(chessboard[row][col]==1){ 128 Score[1]++;//統計白子數量 129 } 130 } 131 } 132 printf("最終成績:\n"); 133 printf("玩家:%d\n計算機:%d\n",Score[0],Score[1]); 134 fflush(stdin); 135 printf("繼續下一局(y/n)?\n"); 136 scanf("%c",&select); 137 138 }while(select=='y'||select=='Y'); 139 printf("游戲結束!"); 140 system("pause"); 141 return 0; 142 143 } 144 145 146 //顯示棋盤中的下子情況 147 void Output(char chessboard[][8]){ 148 int row, col; 149 printf("\n "); 150 for (col = 0; col < 8; col++) //輸出列標號 151 printf(" %c", 'A' + col); 152 printf("\n"); 153 printf(" ┌"); //輸出頂部橫線 154 for (col = 0; col < 7; col++) //輸出一行 155 printf("—┬"); 156 printf("—┐\n"); 157 for (row = 0; row < 8; row++) 158 { 159 printf("%2d|", row + 1); //輸出行號 160 for (col = 0; col < 8; col++) //輸出棋盤各單元格中棋子的狀態 161 { 162 if (chessboard[row][col] == 1) //白棋 163 printf("○|"); 164 else if (chessboard[row][col] == -1) //黑棋 165 printf("●|"); 166 else //未下子處 167 printf(" |"); 168 } 169 printf("\n"); 170 if (row < 8-1) 171 { 172 printf(" ├"); //輸出交叉線 173 for (col = 0; col < 8-1; col++) //輸出一行 174 printf("—┼"); 175 printf("—┤\n"); 176 } 177 } 178 printf(" └"); 179 for (col = 0; col < 8-1; col++) //最后一行的橫線 180 printf("—┴"); 181 printf("—┘\n"); 182 } 183 184 //檢查一方是否有位置下子 185 int Check(char chessboard[][8], int isDown[][8], char player) 186 { 187 int rowdelta, coldelta, row, col, x, y = 0; 188 int iStep = 0;//可下的位置數量 189 char opponent = (player == 1) ? -1 : 1; //對方棋子 190 char myplayer = -1 *opponent;//我方棋子 191 for (row = 0; row < 8; row++) //將isDown數組全部清0 192 for (col = 0; col < 8; col++) 193 isDown[row][col] = 0; 194 for (row = 0; row < 8; row++) //循環判斷棋盤中的哪些單元格可以下子 195 { 196 for (col = 0; col < 8; col++) 197 { 198 if (chessboard[row][col] != 0) //若棋盤上的對應位置不為空(表示已經有子) 199 continue; //繼續處理下一個單元格 200 for (rowdelta = -1; rowdelta <= 1; rowdelta++) //循環檢查上下行 201 { 202 for (coldelta = -1; coldelta <= 1; coldelta++) //循環檢查左右列 203 { 204 if (row + rowdelta < 0 || row + rowdelta >= 8 || col + coldelta < 0 || col + coldelta >= 8|| (rowdelta == 0 && coldelta == 0))//若坐標超過棋盤或為當前單元格 205 continue; //繼續循環 206 if (chessboard[row + rowdelta][col + coldelta] == opponent)//若(row,col)四周有對手下的子 207 { 208 x = row + rowdelta; //以對手的下子位置為坐標 209 y = col + coldelta; 210 while(1)//以對手的下子為起始點,沿着該方向查找自己方的棋子,以攻擊對方棋子 211 { 212 x += rowdelta; //對手下子的四周坐標 213 y += coldelta; 214 if (x < 0 || x >= 8 || y < 0 || y >= 8) //超過棋盤 215 break; //退出循環 216 if (chessboard[x][y] == 0) //若對應位置為空 217 break; 218 if (chessboard[x][y] == myplayer) //若對應位置下的子是當前棋手的 219 { 220 //設置移動數組中對應位置為1 (該位置可下子,形成向對手進攻的棋形) 221 isDown[row][col] = 1; 222 iStep++; //加可下子的位置數量 223 break; 224 } 225 } 226 } 227 } 228 } 229 } 230 } 231 return iStep; //返回可下的位置數量(若返回值為0,表示沒地方可下) 232 } 233 234 235 //在指定位置下子 236 void PlayStep(char chessboard[][8], int row, int col, char player) 237 { 238 int rowdelta = 0; 239 int coldelta = 0; 240 int x = 0; 241 int y = 0; 242 char opponent = (player == 1) ? -1 : 1; //對方棋子 243 char myplayer = -1 * opponent;//我方棋子 244 chessboard[row][col] = myplayer; //保存所下的棋子 245 for (rowdelta = -1; rowdelta <= 1; rowdelta++)//檢查所下子四周的棋子 246 { 247 for (coldelta = -1; coldelta <= 1; coldelta++) 248 { 249 if (row + rowdelta < 0 || row + rowdelta >= 8 || col + coldelta < 0 || col + coldelta >= 8 || (rowdelta == 0 && coldelta == 0)) 250 //若坐標超過棋盤界限 251 continue; //繼續下一位置 252 //若該位置是對手的棋子 253 if (chessboard[row + rowdelta][col + coldelta] == opponent) 254 { 255 x = row + rowdelta; //以對手的棋子作為坐標 256 y = col + coldelta; 257 while(1) //在對手棋子的四周尋找我方棋子 258 { 259 x += rowdelta; 260 y += coldelta; 261 if (x < 0 || x >= 8 || y < 0 || y >= 8) //若坐標超過棋盤 262 break; //退出循環 263 if (chessboard[x][y] == 0)//若對應位置為空 264 break; //退出循環 265 if (chessboard[x][y] == myplayer) //若對應位置是我方棋子 266 { 267 //循環處理 268 while (chessboard[x -= rowdelta][y -= coldelta] == opponent) 269 chessboard[x][y] = myplayer; //將中間的棋子都變成我方棋子 270 break; //退出循環 271 } 272 } 273 } 274 } 275 } 276 } 277 278 //計算機自動下子 279 void AutoPlayStep(char chessboard[][8], int isDown[][8], char player) 280 { 281 int row, col, row1, col1, i, j; 282 int Score = 0, MinScore = 100;//對方可下子得到的分數和最小分數 283 char chessboard1[8][8]; //臨時數組,保存棋盤的下子位置 284 int isDown1[8][8]; //臨時數組,保存可下子的位置 285 char opponent = (player == 1) ? -1 : 1; //對手下的棋子 286 for (row = 0; row < 8; row++) //循環檢查棋盤的每個單元格 287 { 288 for (col = 0; col < 8; col++) 289 { 290 if (isDown[row][col] == 0) //若不可下子 291 continue; //繼續下一個位置 292 for (i = 0; i < 8; i++)//將棋盤原來的棋子復制到臨時數組中 293 for (j = 0; j < 8; j++) 294 chessboard1[i][j] = chessboard[i][j]; 295 PlayStep(chessboard1, row, col, player); 296 //試着在臨時棋盤中的一個位置下子 297 Check(chessboard1, isDown1, opponent); //檢查對手是否有地方可下子 298 Score = BestPlay(chessboard1, isDown1, opponent); 299 //獲得臨時棋盤中對方下子的得分情況 300 if (Score < MinScore) //保存對方得分最低的下法 301 { 302 MinScore = Score; 303 row1 = row; 304 col1 = col; 305 } 306 } 307 } 308 PlayStep(chessboard, row1, col1, player); //計算機按最優下法下子 309 } 310 311 //獲取分數 312 int GetMaxScore(char chessboard[][8], char player) 313 { 314 int Score, row, col; 315 char opponent = (player == 1) ? -1 : 1; //對方棋子 316 char myplayer=-1*opponent; 317 for (row = 0; row < 8; row++) //循環 318 { 319 for (col = 0; col < 8; col++) 320 { 321 //如果棋盤對應位置是對手下的棋子,從總分中減1分 322 Score -= chessboard[row][col] == opponent; 323 //如果棋盤對應位置是我方的棋子,在總分中加1分 324 Score += chessboard[row][col] == myplayer; 325 } 326 } 327 return Score; //返回分數 328 } 329 330 //最優下子位置 331 int BestPlay(char chessboard[][8], int isDown[][8], char player) 332 { 333 int row, col, i, j; 334 char chessboard1[8][8] = { 0 }; //定義一個臨時數組 335 int MaxScore = 0; //保存最高分 336 int Score = 0; 337 char opponent = (player == 1) ? -1 : 1;//對手下的棋子 338 for (row = 0; row < 8; row++) //循環檢查每個單元格 339 { 340 for (col = 0; col < 8; col++) 341 { 342 if (!isDown[row][col]) //如果該位置不可下子 343 continue; //繼續檢查 344 for (i = 0; i < 8; i++) //復制棋盤各單元格下子的狀態到臨時數組 345 for (j = 0; j < 8; j++) 346 chessboard1[i][j] = chessboard[i][j]; 347 PlayStep(chessboard1, row, col, player); //在臨時數組中的指定行列下子 348 Score = GetMaxScore(chessboard1, player); //獲取下子后可得到的分數 349 if (MaxScore < Score) //若原方案得到的分數小於本次下子的分數 350 MaxScore = Score; //保存最高分 351 } 352 } 353 return MaxScore; //返回得到的最高分 354 }
stdio
如果有就讓玩家或計算機下