Codeforces Round#3 C : Tic-tac-toe

Bではまって残り時間10分になってしまったCのPractice.
Bより簡単じゃないかorz

問題概要

3x3の盤で行われる先手が×の「○×ゲーム」(ルールは通常と同じ)において、盤面の状態が次のうちどれであるか判定せよ。

  • 先手勝ち
  • 後手勝ち
  • 先手番
  • 後手番
  • 引き分け
  • 不正

解法

適切に場合分けする。
良い実装&デバッグケース作りの練習。


以下の順で判定すればOK.

  • ○と×の個数がおかしかったり、両方が勝っていたら「不正」
  • 今○×どっちかのターンで、前のターンの人が揃えていたら前のターンの人の勝ち
  • どっちかが勝ってるけどターン的におかしかったら「不正」
  • 全マスが埋まっていたら引き分け
  • 手番を返す
bool doesWin(char board[3][3],char c)
{
	//row
	rep(i,3)
	{
		bool ok=1;
		rep(j,3)if(board[i][j]!=c)ok=0;
		if(ok)return 1;
	}
	//col
	rep(j,3)
	{
		bool ok=1;
		rep(i,3)if(board[i][j]!=c)ok=0;
		if(ok)return 1;
	}
	//dia1
	{
		bool ok=1;
		rep(i,3)if(board[i][i]!=c)ok=0;
		if(ok)return 1;
	}
	//dia2
	{
		bool ok=1;
		rep(i,3)if(board[i][2-i]!=c)ok=0;
		if(ok)return 1;
	}
	
	return 0;
}

int main()
{
	char board[3][3];
	int x=0,o=0,dot=0;
	rep(i,3)
	{
		cin>>board[i];
		rep(j,3)
		{
			if(board[i][j]=='X')x++;
			if(board[i][j]=='0')o++;
			if(board[i][j]=='.')dot++;
		}
	}
	bool xwin=doesWin(board,'X'),owin=doesWin(board,'0');
	
	//dbg(x);dbg(o);
	
	if(x-o>1||x<o||xwin&&owin)
	{
		cout<<"illegal"<<endl;
		goto END;
	}
	if(xwin&&x==o+1)
	{
		cout<<"the first player won"<<endl;
		goto END;
	}
	if(x==o&&owin)
	{
		cout<<"the second player won"<<endl;
		goto END;
	}
	if(xwin||owin)
	{
		cout<<"illegal"<<endl;
		goto END;
	}
	if(dot==0&&x==5&&o==4)
	{
		cout<<"draw"<<endl;
		goto END;
	}
	
	cout<<(x==o?"first":"second")<<endl;
	
	END:return 0;
}

(ヘッダ・マクロは省略)
冗長かも?もっと効率的な実装ができた方は是非教えてください;;