1. 程式人生 > >4.黑白棋(UVA220)

4.黑白棋(UVA220)

黑白棋(UVA220)

題目簡單分析

題目的詳細內容可以在這個網站上看到,下面簡單說明一下題目要求。
[題意]
本題主要任務是模擬黑白棋的過程,黑白棋的規則是一方用自己的棋子夾住對方的棋子,然後就可以把夾住的棋子“吃掉”,從而變為自己的棋子,最終棋子數多的獲勝。分析下棋的規則可知,程式的主要任務為下面兩點:
①計算棋局中可落子的位置。
②計算落子後棋盤中的棋子的變化。

上圖可以看出,白色方在(7,3)位置落子之後,將黑色方(6,3)和(6,4)位置兩枚棋子“吃掉”了。
[輸入輸出]
樣例輸入輸出如下:

輸入的格式如圖,其中,第一行的2表示測試用例的數量為2;接下來的8行為棋盤,B代筆黑色棋子,W代表白色棋子,-代表該處無子;其他命令的意義如下:
W

:表示指定當前執子方為白色方,
L:列出可落子的位置,
M35:指定落子在(3,5)處並在落子之後打印出雙方棋子數,
Q:表示列印棋盤並結束。
輸出的格式如圖所示,注意各例之間用空行隔開。
[分析]
分析黑白棋的規則可知,玩家可以從8個方向“吃掉”對方的棋子,故搜尋可落子時需要考慮八個方向的情況,分別是上、下、左、右、左上、右上、左下、右下。

程式碼

完整程式碼如下,用C語言實現,VS2017的工程在github。程式碼如有bug,敬請指出。

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
typedef struct { int x, y; int dir[8]; }Move; Move move[64]; int Nmove = 0; //上、下、左、右、左上、右上、左下、右下 int dx[8] = { -1,1,0,0,-1,-1,1,1 }, dy[8] = { 0,0,-1,1,-1,1,-1,1 }; int nWhite, nBlack;//黑白棋子數 char board[9 + 1][9 + 1];//多1行/列,防止溢位 char cmd[4], player;//指令最長為3個字元 void exec_cmd();//執行命令 void make_a_move();//下棋 int main
() { int n; //freopen("data.txt", "r", stdin); memset(board, 0, sizeof(board)); scanf("%d", &n); while (n--) { memset(move, 0, sizeof(move)); if (cmd[0]) printf("\n");//除了第一局之前都加上\n for (int i = 1; i <= 8; ++i) scanf("%s", &board[i][1]); do { scanf("%s", cmd);//讀取命令 exec_cmd();//執行命令 } while (cmd[0] != 'Q'); } //fclose(stdin); return 0; } void find_legal_move();//查詢合法位置 void list_legal_move();//列出合法位置 void print_board();//列印棋局 void exec_cmd() { if (cmd[0] == 'W') player = 1; else if (cmd[0] == 'B') player = 0; else if (cmd[0] == 'M') make_a_move(); else if (cmd[0] == 'L') list_legal_move(); else if (cmd[0] == 'Q') print_board(); } void find_legal_move() { char mine,rival, flag = 0; Nmove = 0;//合法點計數 memset(move, 0, sizeof(move)); if (player) mine = 'W',rival='B'; else mine = 'B',rival='W'; for(int i=1;i<=8;++i)//遍歷所有位置 for (int j = 1; j <= 8; ++j) { if (board[i][j] != '-') continue; flag = 0; for (int k = 0; k < 8; ++k)//八個方向 if (board[i + dx[k]][j + dy[k]] == rival) for (int m = i + dx[k], n = j + dy[k]; m > 0 && n > 0 && m < 9 && n < 9; m += dx[k], n += dy[k]) { if (board[m][n] == '-') break; if (board[m][n] == mine) { move[Nmove].dir[k] = 1; flag = 1; } } if (flag) {move[Nmove].x = i; move[Nmove].y = j; Nmove++;} } } void list_legal_move() { find_legal_move(); if (Nmove == 0) { printf("No legal move.\n"); return; } int i = 0; for (; i < Nmove-1; ++i) { printf("(%d,%d) ", move[i].x, move[i].y); } printf("(%d,%d)\n", move[i].x, move[i].y); } void count(); void make_a_move() { char mine,rival;//自己-對手 int tempx, tempy; find_legal_move(); if (Nmove == 0) { player = 1 - player; find_legal_move(); } if (player) mine = 'W', rival = 'B'; else mine = 'B', rival = 'W'; for (int i = 0; i < Nmove; ++i) if (move[i].x == cmd[1]-'0' && move[i].y == cmd[2]-'0') { tempx = move[i].x; tempy = move[i].y; board[tempx][tempy] = mine; for (int k = 0; k < 8; ++k) if(move[i].dir[k]) for(int m=tempx+dx[k],n=tempy+dy[k]; m > 0 && n > 0 && m < 9 && n < 9; m += dx[k], n += dy[k]) if (board[m][n] == mine) break; else board[m][n] = mine; } count(); printf("Black -%3d White -%3d\n", nBlack, nWhite);//坑爹的3d player = 1 - player; } void print_board(){ for (int i = 1; i <= 8; ++i) printf("%s\n", &board[i][1]); } void count() { nWhite=0, nBlack=0; for (int i = 1; i <= 8; ++i) for (int j = 1; j <= 8; ++j) if (board[i][j] == 'W') nWhite++; else if(board[i][j] == 'B') nBlack++; }