4.黑白棋(UVA220)
阿新 • • 發佈:2018-11-12
黑白棋(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++;
}