1. 程式人生 > >習題4-1 Xiangqi UVA

習題4-1 Xiangqi UVA

這題真繁瑣,昨晚上我寫到了兩點,以為把炮的、將的模組都寫對了,只剩下馬和車的了,但是今天下午頭腦清醒了,才發現這倆模組都寫錯了,於是我相當於全重寫的,最後輸入輸出也改了。但是基本的架構還是沒改。

演算法是這樣的:開一個二維字元陣列,存放對應棋子到座標上,記錄兩個將的位置。最開始先判定“飛將”,如果飛將,就輸出“No”,continue。沒有飛將,則從遍歷整個棋盤,對每個紅方棋子,按照它的遊戲規則,標記它造成的黑將不能到達的位置(到達就輸了)。全部標記完後,判斷黑將身邊能夠走到的那幾個位置,看看是否可以走,如果由於紅方棋子的標記,都不能走了,就輸了。只要存在一個位置可以走,就贏了。

邏輯如此簡單的一個程式,但是我寫了這麼長時間,因為太繁瑣了,程式碼160多行。我踩過的坑有以下幾個:

1.最不好寫的馬還一次寫對了,但是看似簡單的炮卻調了半天才發現bug,就是漏了幾個break

2.該不該把黑將作為空字元格來處理。我剛開始沒意識到這個問題,後來發現了,但是程式架構已經寫的差不多了,所以改又花了很多時間。

3.“飛將”是個什麼鬼?我玩的時候都是禁止兩將對頭的,所以寫的時候沒加這條,所以最後除錯又出問題了。後來加了這個規則,但是其中一個變數又打錯了一個字母,導致了函數出錯了,我又加列印語句才發現了這個錯誤,改了,提交上,對了。前後花了5-6個小時,一刻不停的那種。

下面上程式碼。

#include <bits/stdc++.h>
using namespace std;
const int N=15;
char cb[N][N];
bool ok,fobd[N][N];
void oph(int i,int j);
void opc(int i,int j);
void opg(int i,int j);
void opr(int i,int j);
void check(int i,int j);
bool fg();
int n=1,xb=1,yb=1,tx,ty,xr,yr;
int main()  {
    char pe;
    while (n&&xb&&yb)   {
        cin>>n>>xb>>yb;
        if (!n||!xb||!yb)   break;
        for (int i=0;i<n;i++)   {
            cin>>pe>>tx>>ty;
            cb[tx][ty]=pe;
            if (pe=='G')    xr=tx,yr=ty;
        }
//        cout<<"xb="<<xb<<'\t'<<"yb="<<yb<<endl;
//        cout<<"xr="<<xr<<'\t'<<"yr="<<yr<<endl;
        if (fg())   {
            cout<<"No"<<endl;
            continue;
        }
//        for (int i=1;i<=10;i++) {
//            for (int j=1;j<=9;j++)
//                cout<<' '<<cb[i][j];
//            cout<<endl;
//        }
        for (int i=1;i<=10;i++) {
            for (int j=1;j<=9;j++) {
                switch(cb[i][j])    {
                    case 'G': opg(i,j);break;
                    case 'H': oph(i,j);break;
                    case 'C': opc(i,j);break;
                    case 'R': opr(i,j);break;
                }
//                if (cb[i][j])  {
//                    cout<<"time"<<endl;
//                    for (int i=1;i<=10;i++) {
//                        for (int j=1;j<=9;j++)
//                            cout<<' '<<fobd[i][j];
//                        cout<<endl;
//                    }
//                }
            }
        }
        check(xb,yb);
        if (ok) cout<<"NO"<<endl;
        else    cout<<"YES"<<endl;
        fill(cb[0],cb[0]+N*N,'\0');
        fill(fobd[0],fobd[0]+N*N,false);
        ok=false;
    }
    return 0;
}

void oph(int i,int j)   {
    int s=i-1,x=i+1,z=j-1,y=j+1;
    if (s>=1)   {
        if (!cb[s][j]&&s-1>=1)  {
            if (j-1>=1) fobd[s-1][j-1]=1;
            if (j+1<=9)    fobd[s-1][j+1]=1;
        }
    }
    if (x<=10)  {
        if (!cb[x][j]&&x+1<=10) {
            if (j-1>=1) fobd[x+1][j-1]=1;
            if (j+1<=9)    fobd[x+1][j+1]=1;
        }
    }
    if (z>=1)   {
        if (!cb[i][z]&&z-1>=1)  {
            if (i-1>=1) fobd[i-1][z-1]=1;
            if (i+1<=10)    fobd[i+1][z-1]=1;
        }
    }
    if (y<=9)   {
        if (!cb[i][y]&&y+1<=9)  {
            if (i-1>=1) fobd[i-1][y+1]=1;
            if (i+1<=10)    fobd[i+1][y+1]=1;
        }
    }
}

void opc(int i,int j)   {
    for (int q=j-1;q>0;q--)    {
        if (cb[i][q])   {
            int p=q-1;
            while (p>0&&(!cb[i][p]||(xb==i&&yb==p)))  p--;
            for (int b=p+1;b<=q-1;b++)
                fobd[i][b]=1;
            break;
        }
    }
    for (int q=j+1;q<=9;q++)    {
        if (cb[i][q])   {
            int p=q+1;
            while (p<=9&&(!cb[i][p]||(xb==i&&yb==p)))  p++;
            for (int b=q+1;b<=p-1;b++)
                fobd[i][b]=1;
            break;
        }
    }
    for (int p=i-1;p>0;p--) {
        if (cb[p][j])   {
            int r=p-1;
            while (r>0&&(!cb[r][j]||(xb==r&&yb==j)))  r--;
            for (int b=r+1;b<=p-1;b++)
                fobd[b][j]=1;
            break;
        }
    }
    for (int p=i+1;p<=10;p++) {
        if (cb[p][j])   {
            int r=p+1;
            while (r<=10&&(!cb[r][j]||(xb==r&&yb==j)))  r++;
            for (int b=p+1;b<=r-1;b++)
                fobd[b][j]=1;
            break;
        }
    }
}

void opg(int i,int j)   {
    int q=i-1;
    while (q>0) {
        if (cb[q][j])  break;
        q--;
    }
    if (q==0)   q++;
    for (int it=q;it<i;it++)    fobd[it][j]=1;
}

void opr(int i,int j)   {
    int a,b;
    for (a=i-1;a>=1&&(!cb[a][j]||(a==xb&&j==yb));a--) fobd[a][j]=1;
    if (cb[a][j]&&(a!=xb||j!=yb))   fobd[a][j]=1;
    for (a=i+1;a<=10&&(!cb[a][j]||(a==xb&&j==yb));a++) fobd[a][j]=1;
    if (cb[a][j]&&(a!=xb||j!=yb))   fobd[a][j]=1;
    for (b=j-1;b>=1&&(!cb[i][b]||(i==xb&&b==yb));b--) fobd[i][b]=1;
    if (cb[i][b]&&(i!=xb||b!=yb))   fobd[i][b]=1;
    for (b=j+1;b<=9&&(!cb[i][b]||(i==xb&&b==yb));b++) fobd[i][b]=1;
    if (cb[i][b]&&(i!=xb||b!=yb))   fobd[i][b]=1;
}

void check(int i,int j) {
    if (i+1<=3&&!fobd[i+1][j])  {ok=true;return;}
    if (i-1>=1&&!fobd[i-1][j])  {ok=true;return;}
    if (j+1<=6&&!fobd[i][j+1])  {ok=true;return;}
    if (j-1>=4&&!fobd[i][j-1])  {ok=true;return;}
}


bool fg()   {
    int i=0;
    if (yb!=yr) return false;
    for (i=xr-1;i>=xb;i--)
        if (cb[i][yb])  break;
    if (i<xb)   return true;
    else    return false;
}