习题4-3 黑白棋 UVa220

1.题目描述:点击打开链接

2.解题思路:本题是一道模拟题,要求模拟黑白棋的三种操作。对于这类题,肯定是分情况编写相应的函数处理。不过本题的难点在于如何方便地寻找到合法位置。思考了一会儿,可以枚举每一个空位置,同时利用一个向量数组方便来后续讨论,由于实现的细节较多,详细过程见代码注释。本题还有一个细节:在执行M命令时记得要更换当前的游戏者,题目中说了是两个人轮流下棋。

3.代码:

#define _CRT_SECURE_NO_WARNINGS 
#include<iostream>
#include<algorithm>
#include<string>
#include<sstream>
#include<set>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<functional>
using namespace std;

typedef pair<int, int> P;
#define N 8
char g[N][N];
vector<P>pos;
char player;//当前玩家,设为全局变量,便于后续讨论
int dx[] = { -1, 1, 0, 0, -1, 1, -1, 1 };//利用向量数组,方便处理各种情况
int dy[] = { 0, 0, -1, 1, -1, 1, 1, -1 };
bool inside(int x, int y)
{
	if (x<0 || x>7 || y<0 || y>7)return false;
	return true;
}
bool find(int d,int x,int y, char c)//沿着路径dx[d],dy[d]寻找目标棋子
{
	int w = dx[d], v = dy[d], i = x, j = y;
	while (inside(i, j) && g[i][j] == 'W' + 'B' - c){ i += w; j += v; }
	if (inside(i, j) && g[i][j] == c)return true; 
	return false;
}
bool is_valid(char c, int x, int y)//判断该位置是否为合法放置位置
{
	if (c == 'W')
	{
		for (int d = 0; d < 8; d++)
		if (inside(x + dx[d], y + dy[d]) && g[x + dx[d]][y + dy[d]]=='B')
		{
			int i = x + dx[d], j = y + dy[d];
			if (find(d, i, j, 'W'))return true;
		}
		return false;
	}
	else
	{
		for (int d = 0; d < 8; d++)
		if (inside(x + dx[d], y + dy[d]) && g[x + dx[d]][y + dy[d]] == 'W')
		{
			int i = x + dx[d], j = y + dy[d];
			if (find(d, i, j, 'B'))return true;
		}
		return false;
	}
}
bool find_pos()//寻找合法放置位置
{
	pos.clear();
	for (int i = 0; i < 8; i++)
	for (int j = 0; j < 8; j++)
	if (g[i][j] == '-'&&is_valid(player, i, j))//枚举每一个位置
		pos.push_back(P(i + 1, j + 1));
	int len = pos.size();
	if (len>0)return true;
	else return false;
}
void place(int x, int y)//放置棋子
{
	if (player == 'W')
	{
		g[x][y] = 'W';
		for (int d = 0; d < 8;d++)
		if (inside(x + dx[d], y + dy[d]) && g[x + dx[d]][y + dy[d]] == 'B')
		{
			int i = x + dx[d], j = y + dy[d];
			if (find(d, i, j, 'W'))
			{
				int w = dx[d], v = dy[d];
				while (g[i][j] != 'W'){ g[i][j] = 'W'; i += w; j += v; }
			}
		}
	}
	else
	{
		g[x][y] = 'B';
		for (int d = 0; d < 8; d++)
		if (inside(x + dx[d], y + dy[d]) && g[x + dx[d]][y + dy[d]] == 'W')
		{
			int i = x + dx[d], j = y + dy[d];
			if (find(d, i, j, 'B'))
			{
				int w = dx[d], v = dy[d];
				while (g[i][j] != 'B'){ g[i][j] = 'B'; i += w; j += v; }
			}
		}
	}
}
void print_num()//打印黑白棋的个数
{
	int n1, n2;
	n1 = n2 = 0;
	for (int i = 0; i < 8;i++)
	for (int j = 0; j < 8;j++)
	if (g[i][j] == 'W')n1++;
	else if (g[i][j]=='B')n2++;
	printf("Black - %2d White - %2d\n", n2, n1);
}
void print_board()//打印当前棋盘
{
	for (int i = 0; i < 8; i++)
	for (int j = 0; j < 8; j++)
		printf("%c%s", g[i][j], j == 7 ? "\n":"");
}
int main()
{
	//freopen("t.txt", "r", stdin);
	int T;
	cin >> T;
	int rnd = 0;
	while (T--)
	{
		memset(g, '\0', sizeof(g));
		for (int i = 0; i < 8; i++)
			scanf("%s", g[i]);
		cin >> player;
		char cmd;
		if (rnd++)cout << endl;
		while (cin >> cmd)
		{
			if (cmd == 'L')
			{
				if (find_pos())
				{
					int len = pos.size();
					for (int i = 0; i < len; i++)
						printf("(%d,%d)%c", pos[i].first, pos[i].second, i == len - 1 ? '\n' : ' ');
				}
				else puts("No legal move.");
			}
			if (cmd == 'M')
			{
				char str[10];
				scanf("%s", str);
				int r, c;
				r = str[0] - '0' - 1, c = str[1] - '0' - 1;
				if (g[r][c]=='-'&&!is_valid(player, r, c)){ player = 'W' + 'B' - player;  }
				place(r, c);
				print_num();
				player = 'W' + 'B' - player;
			}
			if (cmd == 'Q')
			{
				print_board();
				break;
			}
		}
	}
	return 0;
}

你可能感兴趣的:(模拟)