題目請參考 https://zerojudge.tw/ShowProblem?problemid=f790.
這題要判斷兩種活三,活四和死四再加上有水平,垂直和兩種斜向共四種方向, 還有斜向時的長度有可能是七子,六子或五子, 所以程式寫起來應該頗為複雜. 為了降低程式的複雜度,我設計一個可以適用各種方向的getn( ), 因為四種方向只是座標增減的方法不同而已. 所以如果有了起始點和方向後,第幾子的狀態都可以用下面的函式來取得.每子的先後順序是從左到右,從上到下.
char d[7][8]; //儲存測資的字串
int VH_TYPE;//0:水平, 1:垂直, 2:斜線(左下往右上), 3:倒斜線(左上往右下)
int start_y;
int start_x;
inline char getn(int index){
switch(VH_TYPE){
case 0:return d[start_y][start_x+index];
case 1:return d[start_y+index][start_x];
case 2:return d[start_y-index][start_x+index];
case 3:return d[start_y+index][start_x+index];
}
}
C++水平和垂直方向都是七子, 只有斜向時可能出現只有六子或五子. 少於五子不存在任何活三,活四和死四,所以不用考慮. 我把七子,六子和五子分三個函式來處理. 只有五子的情形下,只有一種連續的活三和兩種死四.
0 | 1 | 2 | 3 | 4 | |
活三 | X | O | O | O | X |
死四 | O | O | O | O | X |
死四 | X | O | O | O | O |
活三分成連續活三和不連續活三兩種只是為了除錯方便. 五子只有連續活三.
int L31=0;//活三第一種 xooox(全相連)
int L32=0;//活三第二種 xooxox(有斷開)
int L4=0;//活四xoooox
int D4=0;//死四xoooo
//5點斜線方向1種連續活三,2種死四
void Check5(int y, int x, int type){
start_y=y;
start_x=x;
VH_TYPE=type;
if(getn(2)=='o'){
if(getn(3)=='o'){
if(getn(4)=='o'){
if(getn(1)=='o'){
if(getn(0)=='x'){
D4++;
}
}
}else{
if(getn(1)=='o'){
if(getn(0)=='o'){
D4++;
}
else{
L31++;
}
}
}
}
}
}
C++只有五子的斜線只存在以下四種,依序檢查就好.
//檢查5點的斜線
Check5(4,0,2);
Check5(6,2,2);
//檢查5點的反斜線
Check5(0,2,3);
Check5(2,0,3);
C++再來就是處理六子, 六子有2種連續活三,2種不連續活三,1種活四,2種死四.
0 | 1 | 2 | 3 | 4 | 5 | |
連續活三 | X | O | O | O | X | |
連續活三 | X | O | O | O | X | |
不連續活三 | X | O | X | O | O | X |
不連續活三 | X | O | O | X | O | X |
活四 | X | O | O | O | O | X |
死四 | O | O | O | O | X | |
死四 | X | O | O | O | O |
以下程式搭配上面表格看就輕鬆了.
void Check6(int y, int x, int type){
start_y=y;
start_x=x;
VH_TYPE=type;
if(getn(3)=='o'){
if(getn(4)=='o'){
if(getn(5)=='o'){
if(getn(2)=='o'){
if(getn(1)=='x'){
D4++;
}
}
}else{
if(getn(2)=='o'){
if(getn(1)=='o'){
if(getn(0)=='x'){
L4++;
}
}else{
L31++;
}
}else{
if(getn(1)=='o'){
if(getn(0)=='x'){
L32++;
}
}
}
}
}else{
if(getn(2)=='o'){
if(getn(1)=='o'){
if(getn(0)=='o'){
D4++;
}else{
L31++;
}
}
}
}
}else{
if(getn(4)=='o' && getn(5)=='x'){
if(getn(2)=='o' && getn(1)=='o'){
if(getn(0)=='x'){
L32++;
}
}
}
}
}
C++六子的斜線也僅有四條要檢查.
//檢查6點的斜線
Check6(5,0,2);
Check6(6,1,2);
//檢查6點的反斜線
Check6(0,1,3);
Check6(1,0,3);
C++最後處理七子, 七子有3種連續活三,4種不連續活三,2種活四,2種死四.
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
連續活三 | X | O | O | O | X | ||
連續活三 | X | O | O | O | X | ||
連續活三 | X | O | O | O | X | ||
不連續活三 | X | O | X | O | O | X | |
不連續活三 | X | O | X | O | O | X | |
不連續活三 | X | O | O | X | O | X | |
不連續活三 | X | O | O | X | O | X | |
活四 | X | O | O | O | O | X | |
活四 | X | O | O | O | O | X | |
死四 | O | O | O | O | X | ||
死四 | X | O | O | O | O |
七子的程式Check7( )有點長,就自己看完整程式吧.
最後處理輸出. 要記得L31+L32才是活三的總數.
void PrintNumber(int n){
switch(n){
case 1:break;
case 2:printf("雙"); break;
case 3:printf("參"); break;
case 4:printf("肆"); break;
case 5:printf("伍"); break;
case 6:printf("陸"); break;
case 7:printf("柒"); break;
case 8:printf("捌"); break;
case 9:printf("玖"); break;
default:printf("拾"); break;
}
}
int main(){
...
if(D4>0){
PrintNumber(D4);
printf("死四");
}
if(L4>0){
PrintNumber(L4);
printf("活四");
}
int L3=L31+L32;
if(L3>0){
PrintNumber(L3);
printf("活三");
}
}
C++完整程式如下. AC時間2ms.
#include <iostream>
#include <stdio.h>
using namespace std;
//f790.
char d[7][8]; //儲存測資的字串
int VH_TYPE;//0:水平, 1:垂直, 2:斜線(左下往右上), 3:倒斜線(左上往右下)
int start_y;
int start_x;
inline char getn(int index){
switch(VH_TYPE){
case 0:return d[start_y][start_x+index];
case 1:return d[start_y+index][start_x];
case 2:return d[start_y-index][start_x+index];
case 3:return d[start_y+index][start_x+index];
}
}
int L31=0;//活三第一種 xooox(全相連)
int L32=0;//活三第二種 xooxox(有斷開)
int L4=0;//活四xoooox
int D4=0;//死四xoooo
//7點有3種連續活三,4種不連續活三,2種活四,2種死四
//0123456
//xooox 連續活三
// xooox 連續活三
// xooox 連續活三
//xoxoox 不連續活三
// xoxoox 不連續活三
//xooxox 不連續活三
// xooxox 不連續活三
//xoooox 活四
// xoooox 活四
//oooox 死四
// xoooo 死四
void Check7(int y, int x, int type){
start_y=y;
start_x=x;
VH_TYPE=type;
if(getn(3)=='o'){
if(getn(4)=='o'){
if(getn(5)=='o'){
if(getn(6)=='o'){
if(getn(2)=='x'){
D4++;
}
}else{
if(getn(2)=='o'){
if(getn(1)=='x'){
L4++;
}
}else{
L31++;
}
}
}else{
if(getn(2)=='o'){
if(getn(1)=='o'){
if(getn(0)=='x'){
L4++;
}
}else{
L31++;
}
}else{
if(getn(1)=='o'){
if(getn(0)=='x'){
L32++;
}
}
}
}
}else{
if(getn(2)=='o'){
if(getn(1)=='o'){
if(getn(0)=='o'){
D4++;
}else{
L31++;
}
}else{
if(getn(5)=='o'){
if(getn(6)=='x'){
L32++;
}
}
}
}
}
}else{
if(getn(4)=='o'){
if(getn(5)=='o'){
if(getn(6)=='x'){
if(getn(2)=='o'){
if(getn(1)=='x'){
L32++;
}
}
}
}else{
if(getn(2)=='o'){
if(getn(1)=='o'){
if(getn(0)=='x'){
L32++;
}
}
}
}
}
}
}
//6點有2種連續活三,2種不連續活三,1種活四,2種死四
//012345
//xooox 連續活三
// xooox 連續活三
//xoxoox 不連續活三
//xooxox 不連續活三
//xoooox 活四
//oooox 死四
//xxoooo 死四
void Check6(int y, int x, int type){
start_y=y;
start_x=x;
VH_TYPE=type;
if(getn(3)=='o'){
if(getn(4)=='o'){
if(getn(5)=='o'){
if(getn(2)=='o'){
if(getn(1)=='x'){
D4++;
}
}
}else{
if(getn(2)=='o'){
if(getn(1)=='o'){
if(getn(0)=='x'){
L4++;
}
}else{
L31++;
}
}else{
if(getn(1)=='o'){
if(getn(0)=='x'){
L32++;
}
}
}
}
}else{
if(getn(2)=='o'){
if(getn(1)=='o'){
if(getn(0)=='o'){
D4++;
}else{
L31++;
}
}
}
}
}else{
if(getn(4)=='o' && getn(5)=='x'){
if(getn(2)=='o' && getn(1)=='o'){
if(getn(0)=='x'){
L32++;
}
}
}
}
}
//5點斜線方向1種連續活三,2種死四
void Check5(int y, int x, int type){
start_y=y;
start_x=x;
VH_TYPE=type;
if(getn(2)=='o'){
if(getn(3)=='o'){
if(getn(4)=='o'){
if(getn(1)=='o'){
if(getn(0)=='x'){
D4++;
}
}
}else{
if(getn(1)=='o'){
if(getn(0)=='o'){
D4++;
}
else{
L31++;
}
}
}
}
}
}
void PrintNumber(int n){
switch(n){
case 1:break;
case 2:printf("雙"); break;
case 3:printf("參"); break;
case 4:printf("肆"); break;
case 5:printf("伍"); break;
case 6:printf("陸"); break;
case 7:printf("柒"); break;
case 8:printf("捌"); break;
case 9:printf("玖"); break;
default:printf("拾"); break;
}
}
int main(){
scanf("%s%s%s%s%s%s%s",
&d[0][0],&d[1][0],&d[2][0],&d[3][0],
&d[4][0],&d[5][0],&d[6][0]);
for(int i=0;i<7;i++){
//檢查水平7點
Check7(i, 0, 0);
//檢查垂直7點
Check7(0, i, 1);
}
//檢查7點的斜線
Check7(6, 0, 2);
//檢查7點的反斜線
Check7(0, 0, 3);
//檢查6點的斜線
Check6(5,0,2);
Check6(6,1,2);
//檢查6點的反斜線
Check6(0,1,3);
Check6(1,0,3);
//檢查5點的斜線
Check5(4,0,2);
Check5(6,2,2);
//檢查5點的反斜線
Check5(0,2,3);
Check5(2,0,3);
if(D4>0){
PrintNumber(D4);
printf("死四");
}
if(L4>0){
PrintNumber(L4);
printf("活四");
}
int L3=L31+L32;
if(L3>0){
PrintNumber(L3);
printf("活三");
}
}
C++