题解 CF3C 【Tic-tac-toe】

Bill_liu2020

2020-02-04 15:04:47

Solution

[$\color{purple}\texttt{来这里不能获得更好的阅读体验}$](https://www.luogu.com.cn/blog/CodeGarden/solution-cf3c) [$\color{blue}\texttt{来这里也不能获得更好的阅读体验}$](https://www.cnblogs.com/Code-Garden/p/12259547.html) 这道题目坑点非常多,我提交了3次才做对。 刚才看了一下题解,发现很多人都是用 $\text{DFS}$ 做的,一开始,我也想用 $\text{DFS}$ ,可是一看到这是井字棋的题目,我有了不一样的打算。。。 # $\huge\color{red}\texttt{暴力出奇迹!}$ 玩过井字棋的人都知道,井字棋的胜利条件是有限的,只需要判断横竖斜行中是否有三个棋子一样的情况就行了。 刚才的文字比较抽象,大家可以根据下文的图示来理解: ![](https://cdn.luogu.com.cn/upload/image_hosting/f1cqg6rl.png) ![](https://cdn.luogu.com.cn/upload/image_hosting/1u363q89.png) ![](https://cdn.luogu.com.cn/upload/image_hosting/n0u0tmh9.png) (黄线代表一种胜利情况) 通过图示我们可以了解到胜利情况共有3+3+2=8种 因为只有这几种情况,所以我干脆用一大坨判断水过去,一开始,我的思路是这样子的: * 首先,边输入边判断这个棋盘填满了没有 * 然后,判断非法情况(A比B多下了两颗棋及以上) * 接着,如果棋盘填满了,判断AB两人的胜负 * 反之,判断下一个应该到谁下棋 Code: ```cpp #include<bits/stdc++.h> using namespace std; char mp[4][4]; int pa,pb; int main() { bool flag=1; for(int i=1;i<=3;i++) { for(int j=1;j<=3;j++) { cin>>mp[i][j]; if(mp[i][j] == '.') { flag=0; } if(mp[i][j] == 'X') { pa++; } if(mp[i][j] == '0') { pb++; } } } if(pa-pb >= 2 || pb > pa) { cout<<"illegal"<<endl; return 0; } if(flag) { if((mp[1][1] == mp[1][2] && mp[1][1] == mp[1][3] && mp[1][1] == 'X') || (mp[1][1] == mp[2][1] && mp[1][1] == mp[3][1] && mp[1][1] == 'X') || (mp[2][1] == mp[2][2] && mp[2][1] == mp[2][3] && mp[2][1] == 'X') || (mp[3][1] == mp[3][2] && mp[3][1] == mp[3][3] && mp[3][1] == 'X') || (mp[1][2] == mp[2][2] && mp[1][2] == mp[3][2] && mp[1][2] == 'X') || (mp[1][3] == mp[2][3] && mp[1][3] == mp[3][3] && mp[1][3] == 'X') || (mp[1][1] == mp[2][2] && mp[1][1] == mp[3][3] && mp[1][1] == 'X') || (mp[1][3] == mp[2][2] && mp[1][3] == mp[3][1] && mp[1][3] == 'X'))//判断 { cout<<"the first player won"<<endl; } else if((mp[1][1] == mp[1][2] && mp[1][1] == mp[1][3] && mp[1][1] == '0') || (mp[1][1] == mp[2][1] && mp[1][1] == mp[3][1] && mp[1][1] == '0') || (mp[2][1] == mp[2][2] && mp[2][1] == mp[2][3] && mp[2][1] == '0') || (mp[3][1] == mp[3][2] && mp[3][1] == mp[3][3] && mp[3][1] == '0') || (mp[1][2] == mp[2][2] && mp[1][2] == mp[3][2] && mp[1][2] == '0') || (mp[1][3] == mp[2][3] && mp[1][3] == mp[3][3] && mp[1][3] == '0') || (mp[1][1] == mp[2][2] && mp[1][1] == mp[3][3] && mp[1][1] == '0') || (mp[1][3] == mp[2][2] && mp[1][3] == mp[3][1] && mp[1][3] == '0'))//判断 { cout<<"the second player won"<<endl; } else { cout<<"draw"<<endl; } } else { if(pa > pb) { cout<<"second"<<endl; } else { cout<<"first"<<endl; } } return 0; } ``` 如果推敲一下我的思路,就会发现几个很严重的错误!!! 1. 非法情况应该再多加两个:当有人胜利了但是对方又下了一枚棋子和两人都赢 2. 并不是一定要把棋盘填满才会决出胜负!!! 所以,我去除了判断flag的语句,将他们放在一起判断,但要注意及时return 0; 正确代码 ```cpp #include<bits/stdc++.h> using namespace std; char mp[4][4]; int pa,pb; int main() { bool flag=1; for(int i=1;i<=3;i++) { for(int j=1;j<=3;j++) { cin>>mp[i][j]; if(mp[i][j] == '.') { flag=0; } if(mp[i][j] == 'X') { pa++; } if(mp[i][j] == '0') { pb++; } } } if(pa-pb >= 2 || pb > pa) { cout<<"illegal"<<endl; return 0; } bool f1=0,f2=0; if((mp[1][1] == mp[1][2] && mp[1][1] == mp[1][3] && mp[1][1] == 'X') || (mp[1][1] == mp[2][1] && mp[1][1] == mp[3][1] && mp[1][1] == 'X') || (mp[2][1] == mp[2][2] && mp[2][1] == mp[2][3] && mp[2][1] == 'X') || (mp[3][1] == mp[3][2] && mp[3][1] == mp[3][3] && mp[3][1] == 'X') || (mp[1][2] == mp[2][2] && mp[1][2] == mp[3][2] && mp[1][2] == 'X') || (mp[1][3] == mp[2][3] && mp[1][3] == mp[3][3] && mp[1][3] == 'X') || (mp[1][1] == mp[2][2] && mp[1][1] == mp[3][3] && mp[1][1] == 'X') || (mp[1][3] == mp[2][2] && mp[1][3] == mp[3][1] && mp[1][3] == 'X')) { f1=1; } if((mp[1][1] == mp[1][2] && mp[1][1] == mp[1][3] && mp[1][1] == '0') || (mp[1][1] == mp[2][1] && mp[1][1] == mp[3][1] && mp[1][1] == '0') || (mp[2][1] == mp[2][2] && mp[2][1] == mp[2][3] && mp[2][1] == '0') || (mp[3][1] == mp[3][2] && mp[3][1] == mp[3][3] && mp[3][1] == '0') || (mp[1][2] == mp[2][2] && mp[1][2] == mp[3][2] && mp[1][2] == '0') || (mp[1][3] == mp[2][3] && mp[1][3] == mp[3][3] && mp[1][3] == '0') || (mp[1][1] == mp[2][2] && mp[1][1] == mp[3][3] && mp[1][1] == '0') || (mp[1][3] == mp[2][2] && mp[1][3] == mp[3][1] && mp[1][3] == '0')) { f2=1; } if(!f1 && !f2) { if(flag) cout<<"draw"<<endl; else { if(pa > pb) { cout<<"second"<<endl; } else { cout<<"first"<<endl; } } return 0; } if(f1 && f2) { cout<<"illegal"<<endl; return 0; } if(f1) { if(pa == pb) { cout<<"illegal"<<endl; return 0; } cout<<"the first player won"<<endl; return 0; } if(f2) { if(pa > pb) { cout<<"illegal"<<endl; return 0; } cout<<"the second player won"<<endl; return 0; } return 0; } ``` # 完结撒花 ~~不点个赞再走吗?~~