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++;
}

猜你喜欢

转载自blog.csdn.net/weixin_43374723/article/details/83547189