当前位置:   article > 正文

c语言数组矩阵求交叉线,C语言-黑白棋(人机对战)

黑白格子影像找交叉线程式

1 #include

2 #include

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 intmain(){21 char chessboard[8][8];//保存棋盘中各单元格下子的状态

22 int isDown[8][8] = {0};//保存棋盘中的各个位置是否可以下子,可以下的位置为1,其余为0

23 introw,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 printf("按任意键计算机下子\n");87 getch();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 getch();141 return 0;142

143 }144

145

146 //显示棋盘中的下子情况

147 void Output(char chessboard[][8]){148 introw, 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], charplayer)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, charplayer)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], charplayer)280 {281 introw, 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], charplayer)313 {314 intScore, 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], charplayer)332 {333 introw, 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 }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/135283
推荐阅读
相关标签
  

闽ICP备14008679号