UVA

来源:互联网 发布:初识seo ppt 编辑:程序博客网 时间:2024/06/05 20:54
/*  这题实在是让人不由感慨一下,好的思路有多么重要!~  起因:因为自己实在想不出来,于是百度题解。然而搜到的题解,要不看得艰难,要不一看就是200行以上的,就可能是畏难吧,于是我甚至看题解,看别人的代码都看不下去了...    但是我又实在不想放弃,接着搜搜搜,居然在百度的比较靠后的页里,找到了一份对我而言,最简洁易懂的代码,马上就理解了,于是自己借用思路手敲了一次    BTW,这个博主写的真心是好,毫无冗余,并且条理逻辑十分清晰,虽然注释不多,但还是让人一眼就看懂了,真的强烈推荐大家去瞻仰一下  http://blog.csdn.net/fzl1941572592/article/details/75208834    但是值得一提的是,如果用这种写法,对格式的控制必须十分精细,不得有丝毫错漏,否则很容易WA,建议先把所有输入数据赋值到一个txt里,观察格式,末尾有无空格,还是只是换行?合理运用getchar(),必要时可以用 cout / printf 输出来检验自己的输入格式,是否真的控制好了。    还要说一下,如果选手在0和1间不断变换,可以用异或符号 ^=    0826更新--  今天我自己按照博主的思路敲了一次,才发现这题,黑白棋连子的判断和替换,选手的替换,这两个最大的难点,博主都用了十分简洁清晰的思路写出来了,真是十分佩服,要是我自己写,肯定得写得很长很长很麻烦*/


#include <iostream>#include <cstring>#include <cstdio>using namespace std;char chess[10][10];typedef pair<int, int > p;p store[50]; int dxy[8][2] = { {1, 0}, {-1, 0}, {0, 1}, {0, -1}, {-1, -1}, {-1, 1}, {1, -1}, {1, 1} };//#define debugvoid count(){int s1 = 0, s2 = 0;for (int i = 1; i <= 8; i++)for (int j = 1; j <= 8; j++){switch (chess[i][j]){case 'B': s1++; break;case 'W': s2++; break;}}printf("Black - %2d White - %2d\n", s1, s2);}int is_legal(char c){int res = 0;memset(store, 0, sizeof (store));for (int i = 1; i <= 8; i++){for (int j = 1; j <= 8; j++){bool flag = false;if (chess[i][j] == '-') //在此放己方棋子作为起点{for (int k = 0; k < 8; k++){int xx = i + dxy[k][0], yy = j + dxy[k][1]; if (xx >= 1&& xx <= 8 && yy >= 1 && yy <= 8 && chess[xx][yy] != c && chess[xx][yy] != '-') //只要该方向上距离 chess[i][j]最近的位置满足这个严苛的条件,就可以一直往这个方向循环,直到越界,或者因为不满足特定条件而break出来 {while (xx >= 1&& xx <= 8 && yy >= 1 && yy <= 8) //在此方向不断延伸,直到碰到己方棋子,或空位,{xx += dxy[k][0]; yy += dxy[k][1];if (chess[xx][yy] == '-') break; // 夹住对方棋子的条件:两端都是己方棋子,不能是空位if (chess[xx][yy] != c) continue; // 如果是对方棋子,继续循环flag = true; break; //如果是己方棋子,标记一下这个起点(i,j)可以放置,于是就可以退出了,将这个位置赋值pair数组}}}}if (flag){res++;store[res].first = i; store[res].second = j;}}}return res;}void change (int x, int y, char c){chess[x][y] = c;for (int i = 0; i < 8; i++){int xx = x + dxy[i][0], yy = y + dxy[i][1];bool flag = false;if (xx >= 1 && xx <= 8 && yy >= 1 && yy <= 8 && chess[xx][yy] != c && chess[xx][yy] != '-') //注意,有2个x的变量,有2个y的变量,不要写漏为1个了,我在这个地方WA了几次,找了很久,真的很难发现 {while (xx >= 1&& xx <= 8 && yy >= 1 && yy <= 8){xx += dxy[i][0]; yy += dxy[i][1];if (chess[xx][yy] == '-') break;if (chess[xx][yy] != c) continue;flag = true; break; //确认当前方向的确可以替换己方棋子}}if (flag){xx = x + dxy[i][0]; yy = y + dxy[i][1];while (xx >= 1&& xx <= 8 && yy >= 1 && yy <= 8){chess[xx][yy] = c;xx += dxy[i][0]; yy += dxy[i][1];if (chess[xx][yy] == c) break; // 等到遇到己方棋子,该方向的替换也就结束了}}}}void showchess(){for (int i = 1; i <= 8; i++){for (int j = 1; j <= 8; j++) cout << chess[i][j];cout << endl;}}int main(){#ifdef debugfreopen("E:\\in.txt", "r", stdin);freopen("E:\\out.txt", "w", stdout);#endifint t, kase = 0, s; //s表示当前棋局从谁开始下 char player[2] = { 'W', 'B' };char start, order; //起始选手,指令 cin >> t;getchar(); //处理末尾的回车符 while (t--){if (kase++) cout << endl;for (int i = 1; i <= 8; i++){for (int j = 1; j <= 8; j++)cin >> chess[i][j];getchar(); //处理末尾的回车符 }cin >> start; getchar(); //处理回车if (start == 'W')s = 0; else s = 1;while (cin >> order){if (order == 'Q'){showchess();getchar();break;}else if (order == 'M'){int r, c, rc; // row, colunmcin >> rc;r = rc / 10;c = rc % 10;if (is_legal(player[s]))change(r, c, player[s]);else{s ^= 1;change(r, c, player[s]);}s ^= 1; //别忘了为M时,是真正的两人下棋的情况,一定要记得一人下完以后,更换选手了!!! count();}else{int ans = is_legal(player[s]);if (!ans) cout << "No legal move." << endl;else{printf("(%d,%d)", store[1].first, store[1].second);for (int i = 2; i <= ans; i++)printf(" (%d,%d)", store[i].first, store[i].second);cout << endl;}}getchar();}}#ifdef debugfclose(stdin);fclose(stdout);#endifreturn 0;}



原创粉丝点击