吴昊品游戏核心算法 Round 11 —— 吴昊教你玩Tic-Tac-Toe(模拟) (HDOJ 3075)
井字棋是神马?
井字棋,大陆、台湾又称为井字游戏、圈圈叉叉;另外也有打井游戏、OX棋的称呼,香港多称井字过三关、过三关,是种纸笔游戏。
怎么玩?
两个玩家,一个打圈(O),一个打叉(X),轮流在3乘3的格上打自己的符号,最先以横、直、斜连成一线则为胜。
如果双方都下得正确无误,将得和局。
这种游戏实际上是由第一位玩家所控制,第一位玩家是攻,第二位玩家是守。
第一位玩家在角位行第一子的话赢面最大(见图一),第二位玩家若是在边,角位下子,第一位玩家就可以以两粒连线牵制着第二位玩家,然后制造“两头蛇”。(我这里不知道所谓的“两头蛇”是什么,不过,我觉得还是在中间走棋可以得到最大的势力)
Tic-Tac-Toe之歌(还是个中国歌手哦!)
在中国,居然有一位歌手写了一首歌,专门赞美Tic-Tac-Toe的。
徐婕儿的一首歌,歌词如下:
一加上一也许不等于二
徐婕儿
在爱情里也许没有规则
OH~BANY
每当我想给你更多自由
却又害怕对你失去了掌握
太多 太少
谁能说 什么是对错
OH~谁都想
让爱情 UNDER CONTROL
但真的 到最后 谁赢过~WU
爱情这游戏就像在玩TIC TAC TOE
○个○ ×个× 谁先谁后 谁爱谁的多
爱情这游戏就像在玩TIC TAC TOE
○个○ ×个× 比来比去 结果差不多
你加上我有太多的可能
爱情有时就像排列组合
OH~BABY
有时候因为爱你而快乐
有时候却因为爱你而困惑
是好 是谁能说
什么是 对错
OH~我只想 把爱情当作享受
不在乎 那最后 的结果~WU
爱情这游戏就像在玩TIC TAC TOE
○个○ ×个× 谁先谁后 谁爱谁的多
爱情这游戏就像在玩TIC TAC TOE
○个○ ×个× 比来比去 结果差不多
爱情这游戏就像在玩TIC TAC TOE
○个○ ×个× 谁先谁后 谁爱谁的多
爱情这游戏就像在玩TIC TAC TOE
○个○ ×个× 比来比去 结果差不多
爱情这游戏就像在玩TIC TAC TOE
○个○ ×个× 谁先谁后 谁爱谁的多
爱情这游戏就像在玩TIC TAC TOE
○个○ ×个× 比来比去 结果差不多
好啦!我们先不要管策略,我们先将其模拟出来(Source:HDOJ 3075)。
Input:分很多案例,每个案例一行,九个字符,代表一个(可能不完整)棋谱。
Output:对于每一个谱子,输出该走棋是否合乎规则(实际上就是需要你来模拟一下棋谱咯)
2 Highlights:
3 (1)利用vict函数判断此时局面的胜负情况
4 (2)通过调用check函数来判定这局棋是否符合规则
5 */
6
7 #include<iostream>
8 using namespace std;
9
10 //定义一个棋盘,i和j分别是行和列的下标
11 char map[4][4];
12 int i,j;
13
14 //想要获胜,有四种情况,为行,列,以及两个对角线
15 bool vict(char c)
16 {
17 for( i=0;i<3;i++) //搜索每一行
18 for( j=0;i<3;j++)
19 {
20 if(map[i][j]!=c)
21 break;
22 if(j==2) return 1;
23 }
24 for( i=0;i<3;i++) //搜索每一列
25 for( j=0;j<3;j++)
26 {
27 if(map[j][i]!=c)
28 break;
29 if(j==2)
30 return 1;
31 }
32 for( i=0;i<3;i++) //搜索左上到右下的对角线(反对角线)
33 {
34 if(map[i][i]!=c)
35 break;
36 if(i==2)
37 return 1;
38 }
39 for( i=0;i<3;i++) //搜索右上到左下的对角线(正对角线)
40 {
41 if(map[i][2-i]!=c)
42 break;
43 if(i==2)
44 return 1;
45 }
46 return 0;
47 }
48
49 bool check()
50 {
51 //记录O和X或者是没有走的点的数目
52 int no,nx,nf;
53 no=nx=nf=0;
54 for( i=0;i<3;i++)
55 for( j=0;j<3;j++)
56 {
57 if(map[i][j]=='O') no++;
58 else if(map[i][j]=='X') nx++;
59 else nf++;
60 if(nx<no || nx>no+1) return 0;//不符合停止条件,因为nx代表先手。
61 if(vict('O') && nx>no) return 0;//当后手赢时,应该nx=no,否则先手又走了一步,vict()函数判定这局棋是否有输赢出现
62 //当一局棋走完了(存在胜负平三种情况),或者还没有走完但是胜负出现了,则表示局面是符合规则的
63 if(!nf || vict('O') || vict('X'))
64 return 1;
65 }
66 return 0;
67 }
68
69 int main()
70 {
71 //e代表读入了end的第一个字符,程序退出
72 while(cin>>map[0][0] && map[0][0]!='e') //判断第一个数据是不是符合继续输入的标准
73 {
74 cin>>map[0][1]>>map[0][2]; //因为第一个判断了,所以这一行剩下的我就一个一个输入了(好原始的方法)。
75 for(i=1;i<3;i++)
76 {
77 for( j=0;j<3;j++)
78 {
79 cin>>map[i][j];
80 if(!check()) cout<<"in";
81 cout<<"valid\n";
82 }
83 }
84 }
85 return 0;
86 }
87
88