无聊,写个小游戏,井字棋
思路:
棋盘表达:二维数组打印
棋盘状态:数组元素标识:未下棋,下O和下X。
棋手:加计数器,奇偶判断区分两棋手。
胜利判断:横竖斜,一方能先连起来,这个直接拿出数据来比一下。还有棋盘慢等情况。
来来来,V1.0诞生了
#include<iostream>
using namespace std;
typedef enum TicTacToeState{
TTTS_Default = 0,
TTTS_O = 1,
TTTS_X = 2,
}TTTS;
void Print(TTTS array[][3])
{
for(int i = 0;i < 3;i++)
{
for(int j = 0;j < 3;j++)
{
if(array[i][j] == TTTS_Default)
cout << "-";
else if(array[i][j] == TTTS_O)
cout << "O";
else
cout << "X";
}
cout << endl;
}
}
TTTS CheckWin(TTTS array[][3])
{
for(int i = 0;i < 3;i++)
if(array[i][0] == array[i][1] &&
array[i][0] == array[i][2] &&
array[i][0] != TTTS_Default)
return array[i][0];
for(int j = 0;j < 3;j++)
if(array[0][j] == array[1][j] &&
array[0][j]== array[2][j] &&
array[0][j] != TTTS_Default)
return array[0][j];
if(array[0][0] == array[1][1] &&
array[0][0] == array[2][2] &&
array[0][0] != TTTS_Default)
return array[0][0];
if(array[0][2] == array[1][1] &&
array[0][2] == array[2][0] &&
array[0][2] != TTTS_Default)
return array[0][2];
return TTTS_Default;
}
int main()
{
TTTS array[3][3] = {TTTS_Default};
int index_x,index_y;
int counter = 0;
Print(array);
while(cin >> index_x >> index_y)
{
if(! ((index_x >= 0 && index_x < 3)&&(index_y >= 0 && index_y < 3))
|| (array[index_x][index_y] != TTTS_Default))
{
cout << "wrong position,please retry!" << endl;
continue;
}
//随便约定个先手
array[index_x][index_y] = counter % 2 ? TTTS_O : TTTS_X;
//打印棋盘
Print(array);
//如果win,就break
if(TTTS_O == CheckWin(array))
{
cout << "game over,O win!!!!!" << endl;
break;
}else if(TTTS_X == CheckWin(array))
{
cout << "game over,O win!!!!!" << endl;
break;
}
counter++;//识别O和X
if(counter >= 9 )//总步数达到9,或者加个或运算,可以判断全盘是否还有TTTS_Default,懒的写了
{
cout << "game over,draw game!" << endl;
break;
}
}
}
可优化的部分
程序的OO化:
整体还是C的风格,用类封装一下,用一个对象表达一盘棋。可以用工厂模式同时开很多盘棋。
包裹一层循环,使得draw game可以直接开始下一盘
(不过如果打算OO化,就不用了,加上构造和析构,每次新开一个就好了)
必输和必胜情况的提前判定:
考虑:
OXX
OO-
X-X
此时,O怎么下都赢不了,X怎么下都赢,可以做成提前判定输赢(向后推演两棋手的棋招和结局,这不就是阿尔法狗干的事么,他不就是向后推N步,算输赢么,并且,还要更高级,并不是穷举所有结局,而是有优化过程,可惜我连最简单的还玩不转,不能窥其门径)
包裹一层循环,使得draw game可以直接开始下一盘
(不过如果打算OO化,就不用了,加上构造和析构,每次新开一个就好了)
友好度:
使用坐标,而非数组下标,不过这都没卵用了,简单。
还可以显示个
轮到O或者轮到X下棋了。
可以考虑再弄个五子棋出来,感觉除了棋盘更大,主要的一点是计算胜利方法更麻烦了。
一个笨方法是遍历棋盘,每次碰到一个棋子,向右、向下、向右下三个方向判断,五个连续同色,胜利。
但是方法太蠢了,看看有没有其他方法,而且本例井字棋的方法也是挺蠢的,直接判断行、判断列、判断手动输入的斜线。本可以抽象化,不过它就三行,本来就简单,不想折腾了。
包裹一层循环,使得draw game可以直接开始下一盘
(不过如果打算OO化,就不用了,加上构造和析构,每次新开一个就好了)