算法習題---4-3黑白棋(UVa220)

一:題目

系統提示當前旗手W/B(白/黑)下子,例如W下子,那麼W下的位置必須是夾住黑色棋子的位置才能夠。

夾住方式:橫向、豎向、斜向

注意落子後將夾住的黑棋吞噬變爲白棋

 (一)題目詳解

1.棋盤以數組表示,「W」表示白子,「B」表示黑子,「-」表示空格
2.棋盤大小8行8列

(二)樣例輸入

2            //第一行是遊戲局數
--------        //開始輸入棋盤
--------
--------
---WB---
---BW---
--------
--------
--------
W            //棋盤後,直接輸入當前旗手
L            //L是提示命令,若是當前有位置能夠下子,則提示(3,5) (4,6) (5,3) (6,4) <前面是能夠走的座標>,若是沒有位置能夠走,提示No legal move. 則輪到對方黑棋下子。
M35           //M是下子命令,35表示落子在3行5列,落子後顯示當前棋盤剩餘棋子數 Black - 1 White - 4
L
Q            //Q是退出命令,退出時將當前棋盤數據打印
WWWWB---
WWWB----
WWB-----
WB------
--------
--------
--------
--------
B
L
M25
L
Q

(三)樣例輸出

(3,5) (4,6) (5,3) (6,4)  //對於L提示命令
Black - 1 White - 4  //對於M35落子命令,提示棋盤當前棋子數
(3,4) (3,6) (5,6)    //對於L提示命令 --------          //對於Q退出命令,打印棋盤
--------
----W---
---WW---
---BW---
--------
--------
--------
No legal move.
Black - 3 White - 12
(3,5)
WWWWB---
WWWWW---
WWB-----
WB------
--------
--------
--------
--------

二:代碼實現

(一)初版本:400+行,可是解析詳細

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define N 8

char QP[N+1][N+1];    //棋盤信息
char player;    //旗手信息
char OP;    //對手信息

bool Oper[90];    //獲取操做數據

信息獲取和展現

//獲取棋盤信息、旗手信息
void getQPInfo()
{
    //獲取棋盤信息
    for (int i = 1; i <= N; i++)
    {
        for (int j = 1; j <= N; j++)
            scanf("%c", &QP[i][j]);
        getchar();
    }
    //獲取旗手信息、對手信息
    scanf("%c", &player);
    while (player=='\n')
        scanf("%c", &player);

    player == 'W' ? OP = 'B' : OP = 'W';
    getchar();
}

//打印棋盤信息
void showQPInfo()
{
    for (int i = 1; i <= N; i++)
    {
        for (int j = 1; j <= N; j++)
            printf("%c", QP[i][j]);
        printf("\n");
    }
}

//打印能夠走的步數
void printDataOper()
{
    for (int i = 11; i <= 88; i++)
        if (Oper[i])
            printf("(%d,%d) ", i / 10, i % 10);
    printf("\n");
}

//打印棋子數目
void printNumber()
{
    int w = 0, b = 0;
    for (int i = 1; i <= N; i++)
        for (int j = 1; j <= N; j++)
            if (QP[i][j] == 'W')
                w++;
            else if (QP[i][j] == 'B')
                b++;

    printf("Black - %d White - %d\n", b, w);
}

//交換旗手位置
void ExchangePlayer()
{
    if (player == 'W')
    {
        player = 'B';
        OP = 'W';
    }
    else
    {
        player = 'W';
        OP = 'B';
    }
}

如果落子後,將夾住的對方棋子同化《版本二簡化》

void dealAllOP(int n, int m)
{
    //判斷四周是否有對手棋子
    int x, y;

    //先判斷左上
    x = n-1, y = m-1;
    if (x >= 1 && y >= 1 && QP[x][y] == OP)
    {
        //夾住對手
        while (QP[x][y] == OP&&x >= 1 && y >= 1)
        {
            x--;
            y--;
        }
        if (x >= 1 && y >= 1 && QP[x][y] == player)    //對面也是本身棋子,成功夾住,能夠吞噬
        {
            x = n - 1, y = m - 1;
            while (x >= 1 && y >= 1&&QP[x][y]!='-')
            {
                QP[x][y] = player;
                x--;
                y--;
            }
        }
    }

    //再判斷上方
    x = n-1, y = m;
    if (x >= 1 && QP[x][y] == OP)
    {
        //夾住對手
        while (QP[x][y] == OP&&x >= 1)
        {
            x--;
        }
        if (x >= 1 && QP[x][y] == player)    //對面也是本身棋子,成功夾住,能夠吞噬
        {
            x = n - 1, y = m;
            while (x >= 1 && QP[x][y] != '-')
            {
                QP[x][y] = player;
                x--;
            }
        }
    }

    //再判斷右上
    x = n - 1, y = m + 1;
    if (x >= 1 && y<= 8 && QP[x][y] == OP)
    {
        //夾住對手
        while (QP[x][y] == OP&&x >= 1 && y <= 8)
        {
            x--;
            y++;
        }
        if (x >= 1 && y <= 8 && QP[x][y] == player)    //對面也是本身棋子,成功夾住,能夠吞噬
        {
            x = n - 1, y = m + 1;
            while (x >= 1 && y <= 8 && QP[x][y] != '-')
            {
                QP[x][y] = player;
                x--;
                y++;
            }
        }
    }

    //再判斷左
    y = m - 1,x=n;
    if (y >= 1 && QP[x][y] == OP)
    {
        //夾住對手
        while (QP[x][y] == OP&&y >= 1)
        {
            y--;
        }
        if (y>=1 && QP[x][y] == player)    //對面也是本身棋子,成功夾住,能夠吞噬
        {
            y = m - 1, x = n;
            while (y >= 1 && QP[x][y] != '-')
            {
                QP[x][y] = player;
                y--;
            }
        }
    }

    //再判斷右
    x = n, y = m+1;
    if (y <=8 && QP[x][y] == OP)
    {
        //夾住對手
        while (QP[x][y] == OP&&y <= 8)
        {
            y++;
        }
        if (y <= 8 && QP[x][y] == player)    //對面也是本身棋子,成功夾住,能夠吞噬
        {
            x = n, y = m + 1;
            while (y <= 8 && QP[x][y] != '-')
            {
                QP[x][y] = player;
                y++;
            }
        }
    }

    //再判斷左下
    x = n + 1, y = m - 1;
    if (x <= 8 && y >= 1 && QP[x][y] == OP)
    {
        //夾住對手
        while (QP[x][y] == OP&&x <= 8 && y >= 1)
        {
            x++;
            y--;
        }
        if (x <= 8 && y >= 1 && QP[x][y] == player)    //對面也是本身棋子,成功夾住,能夠吞噬
        {
            x = n + 1, y = m - 1;
            while (x <= 8 && y >= 1 && QP[x][y] != '-')
            {
                QP[x][y] = player;
                x++;
                y--;
            }
        }
    }

    //再判斷下
    x = n + 1, y = m;
    if (x <= 8 && QP[x][y] == OP)
    {
        //夾住對手
        while (QP[x][y] == OP&&x <= 8)
        {
            x++;
        }
        if (x <= 8 && QP[x][y] == player)    //對面也是本身棋子,成功夾住,能夠吞噬
        {
            x = n + 1, y = m;
            while (x <= 8 && QP[x][y] != '-')
            {
                QP[x][y] = player;
                x++;
            }
        }
    }

    //再判斷右下
    x = n + 1, y = m + 1;
    if (x <= 8 && y <= 8 && QP[x][y] == OP)
    {
        //夾住對手
        while (QP[x][y] == OP&&x <= 8 && y <= 8)
        {
            x++;
            y++;
        }
        if (x <= 8 && y <= 8 && QP[x][y] == player)    //對面也是本身棋子,成功夾住,能夠吞噬
        {
            x = n + 1, y = m + 1;
            while (x <= 8 && y <= 8 && QP[x][y] != '-')
            {
                QP[x][y] = player;
                x++;
                y++;
            }
        }
    }
}

判斷對方棋子四周8個方向是否能夠落子《版本二簡化》

bool judgePlayAtSite(int n,int m)
{
    bool flag = false;
    int x, y;

    //先判斷左上
    x = n, y = m;
    if ((x - 1) >= 1 && (y - 1) >= 1 && QP[x - 1][y - 1] == '-')
    {
        //能夠落子,判斷是否合理
        while (QP[x][y]==OP&&x<=8&&y<=8)
        {
            x++;
            y++;
        }
        if (x <= 8 && y <= 8&&QP[x][y] == player)    //位置合理 落子合理
        {
            Oper[(n-1) * 10 + m-1] = true;
            flag = true;
        }
    }

    //再判斷上方
    x = n, y = m;
    if ((x - 1) >= 1&& QP[x - 1][y] == '-')
    {
        //能夠落子,判斷是否合理
        while (QP[x][y] == OP&&x <= 8)
            x++;
        if (x <= 8 && QP[x][y] == player)    //位置合理 落子合理
        {
            Oper[(n - 1) * 10 + m] = true;
            flag = true;
        }
    }

    //再判斷右上
    x = n, y = m;
    if ((x - 1) >= 1 && (y + 1) <= 8 && QP[x - 1][y + 1] == '-')
    {
        //能夠落子,判斷是否合理
        while (QP[x][y] == OP&&x <= 8 && y >= 1)
        {
            x++;
            y--;
        }
        if (x <= 8 && y >= 1 && QP[x][y] == player)    //位置合理 落子合理
        {
            Oper[(n-1) * 10 + m+1] = true;
            flag = true;
        }
    }

    //再判斷左
    x = n, y = m;
    if ((y - 1) >= 1 && QP[x][y - 1] == '-')
    {
        //能夠落子,判斷是否合理
        while (QP[x][y] == OP && y <= 8)
        {
            y++;
        }
        if (y <= 8 && QP[x][y] == player)    //位置合理 落子合理
        {
            Oper[n * 10 + m-1] = true;
            flag = true;
        }
    }

    //再判斷右
    x = n, y = m;
    if ((y + 1) <=8 && QP[x][y + 1] == '-')
    {
        //能夠落子,判斷是否合理
        while (QP[x][y] == OP && y >= 1)
        {
            y--;
        }
        if (y >= 1 && QP[x][y] == player)    //位置合理 落子合理
        {
            Oper[n * 10 + m+1] = true;
            flag = true;
        }
    }

    //再判斷左下
    x = n, y = m;
    if ((x + 1) <= 8 && (y - 1) >= 1 && QP[x + 1][y - 1] == '-')
    {
        //能夠落子,判斷是否合理
        while (QP[x][y] == OP&&x >= 1 && y <= 8)
        {
            x--;
            y++;
        }
        if (x >= 1 && y <= 8 && QP[x][y] == player)    //位置合理 落子合理
        {
            Oper[(n+1) * 10 + m-1] = true;
            flag = true;
        }
    }

    //再判斷下
    x = n, y = m;
    if ((x + 1) <= 8 && QP[x + 1][y] == '-')
    {
        //能夠落子,判斷是否合理
        while (QP[x][y] == OP&&x >= 1)
        {
            x--;
        }
        if (x >= 1 && QP[x][y] == player)    //位置合理 落子合理
        {
            Oper[(n+1) * 10 + m] = true;
            flag = true;
        }
    }

    //再判斷右下
    x = n, y = m;
    if ((x + 1) <= 8 && (y + 1) <=8 && QP[x + 1][y + 1] == '-')
    {
        //能夠落子,判斷是否合理
        while (QP[x][y] == OP&&x >=1 && y >= 1)
        {
            x--;
            y--;
        }
        if (x >= 1 && y >= 1 && QP[x][y] == player)    //位置合理 落子合理
        {
            Oper[(n+1) * 10 + m+1] = true;
            flag = true;
        }
    }

    return flag;
}

判斷是否當前旗手是否能夠落子

bool judgeRunPlayer()
{
    //初始化步操做
    bool flag = false;
    memset(Oper, false, sizeof(Oper));

    //循環棋盤,找到對方棋子,判斷對方棋子四周是否能夠落子
    for (int i = 1; i <= N; i++)
    {
        for (int j = 1; j <= N; j++)
        {
            if (QP[i][j] == OP) //判斷四周是否能夠落子
                if (judgePlayAtSite(i, j))
                    flag = true;
        }
    }

    //若是步數無效,則調換對手
    if (flag == false)
        ExchangePlayer();
    return flag;
}

處理命令

void dealCommand()
{
    char comm;
    int x, y, temp;
    while (1)
    {
        scanf("%c", &comm);
        switch (comm)
        {
        case 'M':    //落子
            scanf("%d", &temp);
            x = temp / 10;
            y = temp % 10;
            //開始處理棋盤信息
            QP[x][y] = player;
            dealAllOP(x, y);
            ExchangePlayer();
            printNumber();    //輸出棋盤棋子數
            break;
        case 'L':    //提示信息
            //先判斷當前旗手是否能夠落子
            if (judgeRunPlayer())    //打印數據
                printDataOper();
            else
                printf("No legal move.\n");
            break;
        case 'Q':    //退出遊戲、打印棋盤
            showQPInfo();
            printf("\n");
            getchar();
            return;
        }
        getchar();
    }
}

主函數

int main()
{
    FILE* fp = freopen("data3.in", "r", stdin);
    freopen("data3.out", "w", stdout);
    int num;

    scanf("%d", &num);
    getchar();

    while (num--)
    {
        getQPInfo();
        dealCommand();
    }

    freopen("CON", "r", stdin);
    freopen("CON", "w", stdout);
    return 0;
}

(二)第二版本:200+行,對兩處函數進行了修改,含空行和註釋

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define N 8

char QP[N+1][N+1];    //棋盤信息
char player;    //旗手信息
char OP;    //對手信息

bool Oper[90];    //獲取操做數據

//8個方向 左上、上、右上、左、右、左下、下、右下
int x_dir[8] = { -1, -1, -1, 0, 0, 1, 1, 1 };    
int y_dir[8] = { -1, 0, 1, -1, 1, -1, 0, 1 };    

//獲取棋盤信息、旗手信息
void getQPInfo()
{
    //獲取棋盤信息
    for (int i = 1; i <= N; i++)
    {
        for (int j = 1; j <= N; j++)
            scanf("%c", &QP[i][j]);
        getchar();
    }
    //獲取旗手信息、對手信息
    scanf("%c", &player);
    while (player=='\n')
        scanf("%c", &player);

    player == 'W' ? OP = 'B' : OP = 'W';
    getchar();
}
//打印棋盤信息
void showQPInfo()
{
    for (int i = 1; i <= N; i++)
    {
        for (int j = 1; j <= N; j++)
            printf("%c", QP[i][j]);
        printf("\n");
    }
}
//打印能夠走的步數
void printDataOper()
{
    for (int i = 11; i <= 88; i++)
        if (Oper[i])
            printf("(%d,%d) ", i / 10, i % 10);
    printf("\n");
}
//打印棋子數目
void printNumber()
{
    int w = 0, b = 0;
    for (int i = 1; i <= N; i++)
        for (int j = 1; j <= N; j++)
            if (QP[i][j] == 'W')
                w++;
            else if (QP[i][j] == 'B')
                b++;

    printf("Black - %d White - %d\n", b, w);
}
//交換旗手位置
void ExchangePlayer()
{
    if (player == 'W')
    {
        player = 'B';
        OP = 'W';
    }
    else
    {
        player = 'W';
        OP = 'B';
    }
}
//判斷對方四周是否能夠落子
bool judgePlayAtSite(int n, int m)
{
    bool flag = false;
    int x, y;

    for (int i = 0; i < 8; i++)    //循環8個方向
    {
        x = n, y = m;
        if ((x + x_dir[i]) >= 1 && (x + x_dir[i]) <= 8 && (y + y_dir[i]) >= 1 && (y + y_dir[i]) <= 8 && QP[x + x_dir[i]][y + y_dir[i]] == '-')
        {
            //能夠落子,判斷是否合理
            while (QP[x][y] == OP&&x <= 8 && x >= 1 && y <= 8 && y >= 1)
            {
                x -= x_dir[i];
                y -= y_dir[i];
            }
            if (x <= 8 && x >= 1 && y <= 8 && y >= 1 && QP[x][y] == player)    //位置合理 落子合理
            {
                Oper[(n + x_dir[i]) * 10 + m + y_dir[i]] = true;
                flag = true;
            }
        }
    }

    return flag;
}
//將當前落子後的棋子夾住的棋子吞噬
void dealAllOP(int n, int m)
{
    //判斷四周是否有對手棋子
    int x, y;

    for (int i = 0; i < 8; i++)
    {
        x = n + x_dir[i], y = m + y_dir[i];
        if (x >= 1 && x <= 8 && y >= 1 && y <= 8 && QP[x][y] == OP)
        {
            //夾住對手
            while (QP[x][y] == OP&&x >= 1 && x <= 8 && y >= 1 && y <= 8)
            {
                x += x_dir[i];
                y += y_dir[i];
            }
            if (x >= 1 && x <= 8 && y >= 1 && y <= 8 && QP[x][y] == player)    //對面也是本身棋子,成功夾住,能夠吞噬
            {
                x = n + x_dir[i], y = m + y_dir[i];
                while (x >= 1 && x <= 8 && y >= 1 && y <= 8 && QP[x][y] != '-')
                {
                    QP[x][y] = player;
                    x += x_dir[i];
                    y += y_dir[i];
                }
            }
        }
    }
}
//判斷是否當前旗手是否能夠落子
bool judgeRunPlayer()
{
    //初始化步操做
    bool flag = false;
    memset(Oper, false, sizeof(Oper));

    //循環棋盤,找到對方棋子,判斷對方棋子四周是否能夠落子
    for (int i = 1; i <= N; i++)
    {
        for (int j = 1; j <= N; j++)
        {
            if (QP[i][j] == OP) //判斷四周是否能夠落子
                if (judgePlayAtSite(i, j))
                    flag = true;
        }
    }

    //若是步數無效,則調換對手
    if (flag == false)
        ExchangePlayer();
    return flag;
}
//處理命令
void dealCommand()
{
    char comm;
    int x, y, temp;
    while (1)
    {
        scanf("%c", &comm);
        switch (comm)
        {
        case 'M':    //落子
            scanf("%d", &temp);
            x = temp / 10;
            y = temp % 10;
            //開始處理棋盤信息
            QP[x][y] = player;
            dealAllOP(x, y);
            ExchangePlayer();
            printNumber();    //輸出棋盤棋子數
            break;
        case 'L':    //提示信息
            //先判斷當前旗手是否能夠落子
            if (judgeRunPlayer())    //打印數據
                printDataOper();
            else
                printf("No legal move.\n");
            break;
        case 'Q':    //退出遊戲、打印棋盤
            showQPInfo();
            printf("\n");
            getchar();
            return;
        }
        getchar();
    }
}
//主函數
void main()
{
    FILE* fp = freopen("data3.in", "r", stdin);
    freopen("data3.out", "w", stdout);
    int num;
    scanf("%d", &num);
    getchar();

    while (num--)
    {
        getQPInfo();
        dealCommand();
    }

    freopen("CON", "r", stdin);
    freopen("CON", "w", stdout);
}

(三)第三版本:100+行,同網上其餘形式,去掉註釋,進行空行縮減,語句簡寫

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 8
char QP[N+1][N+1];    //棋盤信息
char player;    //旗手信息
char OP;    //對手信息
bool Oper[90];    //獲取操做數據
int x_dir[8] = { -1, -1, -1, 0, 0, 1, 1, 1 };    
int y_dir[8] = { -1, 0, 1, -1, 1, -1, 0, 1 };    
void getQPInfo()
{
    for (int i = 1; i <= N; i++)
    {
        for (int j = 1; j <= N; j++)
            scanf("%c", &QP[i][j]);
        getchar();
    }
    scanf("%c", &player);
    while (player == '\n') scanf("%c", &player);
    player == 'W' ? OP = 'B' : OP = 'W';
    getchar();
}
void showQPInfo()
{
    for (int i = 1; i <= N; i++)
    {
        for (int j = 1; j <= N; j++)
            printf("%c", QP[i][j]);
        printf("\n");
    }
}
void printDataOper()
{
    for (int i = 11; i <= 88; i++)
        if (Oper[i]) printf("(%d,%d) ", i / 10, i % 10);
    printf("\n");
}
void printNumber()
{
    int w = 0, b = 0;
    for (int i = 1; i <= N; i++)
        for (int j = 1; j <= N; j++)
            if (QP[i][j] == 'W') w++;
            else if (QP[i][j] == 'B') b++;
    printf("Black - %d White - %d\n", b, w);
}
void ExchangePlayer()
{
    if (player == 'W') player = 'B', OP = 'W';
    else player = 'W', OP = 'B';
}
bool judgePlayAtSite(int n, int m)
{
    bool flag = false;
    int x, y;
    for (int i = 0; i < 8; i++)    //循環8個方向
    {
        x = n, y = m;
        if ((x + x_dir[i]) >= 1 && (x + x_dir[i]) <= 8 && (y + y_dir[i]) >= 1 && (y + y_dir[i]) <= 8 && QP[x + x_dir[i]][y + y_dir[i]] == '-')
        {
            while (QP[x][y] == OP&&x <= 8 && x >= 1 && y <= 8 && y >= 1)
                x -= x_dir[i],y -= y_dir[i];
            if (x <= 8 && x >= 1 && y <= 8 && y >= 1 && QP[x][y] == player)    //位置合理 落子合理
                Oper[(n + x_dir[i]) * 10 + m + y_dir[i]] = true,flag = true;
        }
    }
    return flag;
}
void dealAllOP(int n, int m)
{
    int x, y;
    for (int i = 0; i < 8; i++)
    {
        x = n + x_dir[i], y = m + y_dir[i];
        if (x >= 1 && x <= 8 && y >= 1 && y <= 8 && QP[x][y] == OP)
        {
            while (QP[x][y] == OP&&x >= 1 && x <= 8 && y >= 1 && y <= 8)
                x += x_dir[i],y += y_dir[i];
            if (x >= 1 && x <= 8 && y >= 1 && y <= 8 && QP[x][y] == player)    //對面也是本身棋子,成功夾住,能夠吞噬
            {
                x = n + x_dir[i], y = m + y_dir[i];
                while (x >= 1 && x <= 8 && y >= 1 && y <= 8 && QP[x][y] != '-')
                    QP[x][y] = player,x += x_dir[i],y += y_dir[i];
            }
        }
    }
}
bool judgeRunPlayer()
{
    bool flag = false;
    memset(Oper, false, sizeof(Oper));
    for (int i = 1; i <= N; i++)
    {
        for (int j = 1; j <= N; j++)
            if (QP[i][j] == OP) //判斷四周是否能夠落子
                if (judgePlayAtSite(i, j)) flag = true;
    }
    if (flag == false) ExchangePlayer();
    return flag;
}
void dealCommand()
{
    char comm;
    int x, y, temp;
    while (1)
    {
        scanf("%c", &comm);
        switch (comm)
        {
        case 'M':    //落子
            scanf("%d", &temp);
            x = temp / 10, y = temp % 10;
            QP[x][y] = player;
            dealAllOP(x, y);
            ExchangePlayer();
            printNumber();    //輸出棋盤棋子數
            break;
        case 'L':    //提示信息
            if (judgeRunPlayer())    printDataOper();//打印數據
            else printf("No legal move.\n");
            break;
        case 'Q':    //退出遊戲、打印棋盤
            showQPInfo();
            printf("\n");
            getchar();
            return;
        }
        getchar();
    }
}
void main()
{
    FILE* fp = freopen("data3.in", "r", stdin);
    freopen("data3.out", "w", stdout);
    int num;
    scanf("%d", &num);
    getchar();
    while (num--)
    {
        getQPInfo();
        dealCommand();
    }
    freopen("CON", "r", stdin);
    freopen("CON", "w", stdout);
}
不必看
相關文章
相關標籤/搜索