UVa220 - Othello(黑白棋)

题目

这条题输入格式要求非常多...很多坑,笔者就在输出格式这搞了很久最终通过网站https://cn.vjudge.net debug才发现哪里不对,先提一下。
L输出的每个坐标间要有空格,但是整行首末都不能有空格;题目与题目之间有空行,且最后一题在输出棋盘后也有一个空行;M命令输出的棋数统计的数字占两格(%2d)。

输入

输入包括三部分
第一部分只有一个数字 n,表示下面一共有 n 个题目。

第二部分有 9 行,代表当前棋盘状态。前八行是 8*8 的棋盘,'-'代表空,'B'代表黑棋,'W'代表白棋。第九行是 'B' 或者 'W' 代表当前玩家。

第三部分是操作命令,有三种:
'L': 输出当前玩家可放棋的所有位置。column优先升序再到row升序。
'Mij': 当前玩家在 (i,j)下棋子,如果当前玩家没有可放棋的位置则直接变为对手下这一步棋。下棋之后转换当前玩家。
'Q': 退出这题。

处理

当放下一个棋子后,若该棋子的水平、垂直 或 对角线方向(共八个方向)满足有相同颜色的棋子且两棋子间都是相反颜色的棋子,则把中间的棋子全部变为己方的棋子。要求每次下棋至少有一个棋子被转换。

解读

题目主要需要处理的功能有两个:列出可走的位置 和 下棋。下面进行解析。

列出可走的位置只需传递一个参数 player(当前玩家),然后遍历棋盘所有空格,并判断该位置能否下棋,能则输出。所以这里右需要一个函数(check1)。
check1函数需要三个参数:player,x,y。但是判断一个位置又分八个方向,所以再加一个函数(check2)。遍历八个方向,有一个方向为真就返回1。
check2函数需要五个参数:player,x,y,dx,dy。其中 dx 和 dy 表示方向,取值 -1,0,1。遍历该方向,若符合则返回长度。

下棋则需要三个参数,player,x,y。遍历八个方向,用 check2 返回的长度对该方向遍历,进行转换。

代码

#define maxn 10
#include <stdio.h>
#include <string.h>
char broad[maxn][maxn];

void print() {
    for (int i = 1; i <= 8; i++) 
        printf("%s\n", &broad[i][1]);
}
char readdisk() {
    char ch;
    while (ch = getchar()) 
        if (ch == '-' || ch == 'W' || ch == 'B') return ch;
}
int list(char &player);
int check(char &player, int x, int y);
int check(char &player, int x, int y, int dx, int dy);
void place(char &player, int x, int y);
void sum();

int main() {
#ifdef TEST
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif // TEST

    int n, kase = 0;
    scanf("%d", &n);
    while (n--) {
        if (kase++) putchar('\n');
        memset(broad, '\0', sizeof(broad));
        for (int i = 1; i <= 8; i++) {
            broad[i][1] = readdisk();
            for (int j = 2; j <= 8; j++) {
                broad[i][j] = getchar();
            }
        }
        char player[2];
        scanf("%s", player);
        char cmd[5];
        while(scanf("%s", cmd) != EOF && cmd[0] != 'Q') {
            if (cmd[0] == 'L') list(player[0]);
            else if (cmd[0] == 'M') place(player[0], cmd[1] - '0', cmd[2] - '0'); 
        }
        print();
    }

    return 0;
}

int list(char &player) {
    int sum = 0, kase = 0;
    for (int x = 1; x <= 8; x++) for (int y = 1; y <= 8; y++) {
        if (broad[x][y] != '-') continue;
        if (check(player, x, y)) {
            if (kase++) putchar(' ');
            printf("(%d,%d)", x, y), sum++;
        }
    }
    if (sum == 0) printf("No legal move.");
    printf("\n");
    return sum;
}

int check(char &player, int x, int y) {
    for (int dx = -1; dx <= 1; dx++) for (int dy = -1; dy <= 1; dy++) {
        //不遍历(0,0)方向
        if (dx == 0 && dy == 0) continue;
        if (check(player, x, y, dx, dy)) return 1;
    }
    return 0;
}

int check(char &player, int x, int y, int dx, int dy){
    int len, flag = 0;
    x += dx; y += dy;
    //len统计该方向两棋间长度
    for (len = 1; x <= 8 && x >= 1 && y <= 8 && y >= 1; len++) {
        if (broad[x][y] == '-') break;
        if (broad[x][y] == player) { flag = 1; break; }
        x += dx; y += dy;
    }
    if (len == 1 || flag == 0)  return 0;
    return len;
}

void place(char &player, int x, int y) {
    if (check(player, x, y) == 0) player = (player == 'W' ? 'B' : 'W');
    broad[x][y] = player;
    for (int dx = -1; dx <= 1; dx++) for (int dy = -1; dy <= 1; dy++) {
        //不遍历(0,0)方向
        if (dx == 0 && dy == 0) continue;
        int len = check(player, x, y, dx, dy);
        //遍历两棋间
        for (int i = 1; i < len; i++)  broad[x + i * dx][y + i * dy] = player;
    }
    player = (player == 'W' ? 'B' : 'W');
    sum();
}

void sum() {
    int sumb = 0, sumw = 0;
    for (int x = 1; x <= 8; x++) for (int y = 1; y <= 8; y++) {
        if (broad[x][y] == 'W') sumw++;
        else if (broad[x][y] == 'B') sumb++;
    }
    printf("Black - %2d White - %2d\n", sumb, sumw);
}

原题

UVa220
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,137评论 6 511
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,824评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,465评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,131评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,140评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,895评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,535评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,435评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,952评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,081评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,210评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,896评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,552评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,089评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,198评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,531评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,209评论 2 357