Othello UVA - 220
问题
代码
// 算法竞赛入门经典习题与解答 P28
// 算法竞赛入门经典第2版 P96
/*
Dreams never shine!
It's you that shine while chasing your dreams :)
JAYO!!
*/
#include <iostream>
#include <vector>
#include <cassert>
#include <cstring>
#include <iomanip>
using namespace std;
bool inRange(int x, int left, int right) {
if(left > right) return inRange(x, right, left);
return left <= x && x <= right;
}
struct Point {
int x, y;
Point(int x = 0, int y = 0) : x(x), y(y) {}
};
ostream & operator << (ostream &os, const Point &p) { return os << "(" << p.x << "," << p.y << ")"; }
template<typename T>
ostream & operator << (ostream &os, const vector<T> &v) {
for(int i = 0; i < v.size(); i++) {
if(i) os << ' ';
os << v[i];
}
return os;
}
typedef Point Vector;
Vector operator + (const Vector &A, const Vector &B) { return Vector(A.x + B.x, A.y + B.y); }
Vector operator - (const Vector &A, const Vector &B) { return Vector(A.x - B.x, A.y - B.y); }
Vector operator * (const Vector &A, int p) { return Vector(A.x * p, A.y * p); }
bool operator == (const Vector &A, const Vector &B) { return A.x == B.x && A.y == B.y; }
bool operator < (const Vector &A, const Vector &B) { return A.x < B.x || (A.x == B.x && A.y < B.y); }
const int N = 8, White = 'W', Black = 'B', Empty = '-';
Vector DIRS[N];
inline bool valid(const Point &p) { return inRange(p.x, 1, N) && inRange(p.y, 1, N); }
char Board[N + 1][N + 1], Player;
char playerChange(char c) {
if(c == White) return Black;
assert(c == Black);
return White;
}
void print_board() {
for(int i = 1; i <= N; i++) {
for(int j = 1; j <= N; j++)
cout << Board[i][j];
cout << endl;
}
}
bool canMove(const Point &p, const Vector &dir) { // 先判断这一条线上有么有可以杀掉的棋子
Point pn = p + dir;
char c, pc = playerChange(Player);
int sz = 0;
while(valid(pn)) {
c = Board[pn.x][pn.y];
if(c == pc) {
sz++;
pn = pn + dir;
}
else break;
}
if(!sz) return false;
if(!valid(pn)) return false;
return c == Player;
}
void move(const Point &p, const Vector & dv) { // 执行杀棋操作(要先判断canMove)
Board[p.x][p.y] = Player;
Point pn = p + dv;
char pc = playerChange(Player);
assert(Board[pn.x][pn.y] == pc);
while(Board[pn.x][pn.y] == pc) {
Board[pn.x][pn.y] = Player;
pn = pn + dv;
}
assert(Board[pn.x][pn.y] == Player);
}
void move(int r, int c) { // 放棋子的点
Point p(r, c);
bool m = false;
for(int d = 0; d < N; d++) {
const Vector &dv = DIRS[d];
if(canMove(p, dv)) { // 杀棋的判断操作(能杀的都杀)(检测落子处的杀棋范围)
m = true;
move(p, dv); // 判断后进行杀棋
}
}
Player = playerChange(Player); // (提前交换棋手)
if(m) return; // 如果杀不了对方的,就只能被杀(交换棋手)
for(int d = 0; d < N; d++) {
const Vector &dv = DIRS[d];
if(canMove(p, dv)) move(p, dv);
}
Player = playerChange(Player);
}
void listAllMoves() {
vector<Point> moves;
for(int i = 1; i <= N; i++) {
for(int j = 1; j <= N; j++) {
Point p(i, j);
if(Board[i][j] != Empty) continue; // 找出合法的空格‘-’(并且可以至少夹住一个对方棋子), 计算legal moves
for(int d = 0; d < N; d++)
if(canMove(p, DIRS[d])) {
moves.push_back(p);
break;
}
}
}
if(moves.empty()) cout << "No legal move." << endl;
else cout << moves << endl;
}
int main() {
int T;
cin >> T;
DIRS[0].x = 1; DIRS[0].y = 0;
DIRS[1].x = 1; DIRS[1].y = 1;
DIRS[2].x = 0; DIRS[2].y = 1;
DIRS[3].x = -1; DIRS[3].y = 1;
DIRS[4].x = -1; DIRS[4].y = 0;
DIRS[5].x = -1; DIRS[5].y = -1;
DIRS[6].x = 0; DIRS[6].y = -1;
DIRS[7].x = 1; DIRS[7].y = -1;
bool first = true;
while(T--) {
if(first) first = false; else cout << endl;
string line;
memset(Board, 0, sizeof(Board));
for(int i = 1; i <= N; i++) {
cin >> line;
for(int j = 1; j <= N; j++)
Board[i][j] = line[j - 1];
}
cin >> Player;
while(true) {
cin >> line;
if(line == "Q") {
print_board();
break;
}
if(line == "L") {
listAllMoves();
} else {
assert(line.size() == 3 && line[0] == 'M');
move(line[1] - '0', line[2] - '0');
int w = 0, b = 0;
for(int i = 1; i <= N; i++) {
for(int j = 1; j <= N; j++) {
char c = Board[i][j];
if(c == White) w++;
else if(c == Black) b++;
}
}
cout << "Black - " << setw(2) << b << " White - " << setw(2) << w << endl;
}
}
}
return 0;
}
知识点
setw(n)
C++ setw() 函数用于设置字段的宽度,语法格式如下:
setw(n)
n 表示宽度,用数字表示。
setw() 函数只对紧接着的输出产生作用。
当后面紧跟着的输出字段长度小于 n 的时候,
在该字段前面用空格补齐,当输出字段长度大于 n 时,全部整体输出。
总结
耐心,解析。带动自己的大脑积极思考。
读懂题目,读懂要求,知道代码实在干嘛?
就是按照题目要求执行一系列被指定的操作!!!
注意自己的心态!你遇到的困难别人也遇到了,但是那些志在登顶的人,绝不会半途而废,绝不放弃,前进,朝着目标前进!!!