无聊,写个小游戏,井字棋
思路:
棋盘表达:二维数组打印
棋盘状态:数组元素标识:未下棋,下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";elsecout << "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,就breakif(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和Xif(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化,就不用了,加上构造和析构,每次新开一个就好了)