習題4-1 Xiangqi UVA
阿新 • • 發佈:2018-12-11
這題真繁瑣,昨晚上我寫到了兩點,以為把炮的、將的模組都寫對了,只剩下馬和車的了,但是今天下午頭腦清醒了,才發現這倆模組都寫錯了,於是我相當於全重寫的,最後輸入輸出也改了。但是基本的架構還是沒改。
演算法是這樣的:開一個二維字元陣列,存放對應棋子到座標上,記錄兩個將的位置。最開始先判定“飛將”,如果飛將,就輸出“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; }