本人是大一新生,寒假无聊,抱着试试看的心态(没有想到可以完成),写了C++的简单五子棋程序,开心。
     下面是效果图:

     一、首先讲讲大致思路
            五子棋实现的基础
                   二维数组是五子棋实现的基础。二维数组就像一个棋盘,其中0等于空格,1等于黑棋,2等于白棋,这里电脑就好比只能理解0和1的仆人,我们通过映射,使得五子棋变成计算机能够处理的0和1,进而计算机知道做我们要它做什么。
举例:5个连成水平线的白棋  ———  00022222000;但是无论怎么样,我们不是电脑,必须看到真正棋才会下(除非你会下盲棋),所以我们需要一个函数,把二维数组中的数字信息转化为图像信息。我的代码如下:

  1. void gobang::display(){
  2. system("cls");
  3. for(int i = ; i < ; i ++){
  4. for(int j = ; j < ; j ++){
  5. if(i == Y && j == X){
  6. cout << "╋";
  7. }
  8. else if(chessboard[i][j] == ){
  9. cout << "○";
  10. }
  11. else if(chessboard[i][j] == ){
  12. cout << "●";
  13. }
  14. else{
  15. cout << ". ";
  16. }
  17.  
  18. }
  19. cout << endl;
  20. }
  21. }

这个显示函数是很“自由”的,你完全可以选择更好的显示方法,甚至有颜色什么的(我还不会...)。                      
 
                五子棋的类的大致浏览

数据:int chessboard[15][15]    //存储棋盘信息

                             int Y, X                            //光标,用于玩家选择位置落子
                             int player, computer        //记录玩家和电脑棋子的颜色
                             point laozi                       //记录最新落子位置,便于判断是否连成五子(point 是 创建的一个结构体:struct point{int y, x})
                  最主要函数:void play()                        //最主要的函数,下面是该函数调用的函数
                  次要函数:
                            int selMode()                    //选择模式
                            void turnPlayer()              //玩家操作
                            void turnComputer()        //电脑操作
                            bool isEnd()                     //判断是否连成五子
                  其他函数
                  具体代码如下:

  1. class gobang{
  2. private:
  3. int chessboard[][]; //记录棋盘信息
  4. int player; //玩家棋子
  5. int computer; //电脑棋子
  6. int Y, X; //光标位置
  7. point laozi; //落子位置
  8. public:
  9. void play();
  10. int selMode();
  11. void turnPlayer();
  12. void turnComputer();
  13. bool isEnd();
  14. protected:
  15. bool isInBoard(point p);
  16. void display();
  17. int score(point p, int who);
  18. point newPoint(point p, dir d, int lenth);
  19. };

五子棋的步骤(play函数):选择模式(选择电脑先手/玩家先手+数据初始化),循环(玩家/电脑操作 + 判断是否结束,如果是,说明胜利棋方跳出循环,如果不是,交换棋方)
           下面是所需要的代码(除了电脑操作部分,比其他复杂一些,最后说)。
            play函数

  1. void gobang::play(){
  2. int i = selMode();
  3. if(i == ){
  4. computer = ;
  5. player = ;
  6. }
  7. else{
  8. player = ;
  9. computer = ;
  10. }
  11. int cur = ;
  12. while(){
  13. if(cur == player){
  14. turnPlayer();
  15. }
  16. else{
  17. turnComputer();
  18. }
  19. if(isEnd()){
  20. if(cur == player){
  21. cout << "Player Win !";
  22. system("pause");
  23. break;
  24. }
  25. else{
  26. cout << "Computer Win !";
  27. system("pause");
  28. break;
  29. }
  30. }
  31. else{
  32. cur = (cur == ) ? : ;
  33. }
  34. }
  35. }

选择模式:这个函数包含两个部分,选择 和 数据初始化

  1. int gobang::selMode(){
  2. system("cls");
  3. cout << "*************************************************" << endl;
  4. cout << "******************0、退出************************" << endl;
  5. cout << "******************1、电脑先手********************" << endl;
  6. cout << "******************2、玩家先手********************" << endl;
  7. cout << "*************************************************" << endl;
  8. while(){
  9. int i;
  10. cin >> i;
  11. if(i == ){
  12. exit();
  13. }
  14. else if(i == || i == ){
  15. Y = ;
  16. X = ;
  17. for(int j = ; j < ; j ++){
  18. for(int k = ; k < ; k ++){
  19. chessboard[j][k] = ;
  20. }
  21. }
  22. display();
  23. return i;
  24. }
  25. else{
  26. cout << "非法输入,请重新输入!" << endl;
  27. }
  28. }
  29. }

玩家操作:玩家操作我采用光标Y,X可视化(display()) 和 键盘操作的方法(w:上 ,s : 下 , a : 左, d : 右, j : 确定落子)。其中操作函数中都会有laozi这个数据,是方便后面的判断是否结束的

  1. void gobang::turnPlayer(){
  2. cout << "turn player" << endl;
  3. while(){
  4. char c = getch();
  5. if(c == 'w'){
  6. if(Y != ){
  7. Y --;
  8. display();
  9. }
  10. }
  11. else if(c == 's'){
  12. if(Y != ){
  13. Y ++;
  14. display();
  15. }
  16.  
  17. }
  18. else if(c == 'a'){
  19. if(X != ){
  20. X --;
  21. display();
  22. }
  23. }
  24. else if(c == 'd'){
  25. if(X != ){
  26. X ++;
  27. display();
  28. }
  29. }
  30. else if(c == 'j' && chessboard[Y][X] == ){
  31. laozi.y = Y;
  32. laozi.x = X;
  33. chessboard[Y][X] = player;
  34. display();
  35. break;
  36. }
  37. }
  38. }

判断是否结束:

  1. bool gobang::isEnd(){
  2. for(int i = ; i <= ; i ++){
  3. dir d;
  4. int count = ;
  5. switch(i){
  6. case :
  7. d = d1;
  8. break;
  9. case :
  10. d = d2;
  11. break;
  12. case :
  13. d = d3;
  14. break;
  15. case :
  16. d = d4;
  17. break;
  18. }
  19. for(int j = -; j <= ; j ++){
  20. point p1 = newPoint(laozi, d, j);
  21. if(isInBoard(p1) && chessboard[p1.y][p1.x] == chessboard[laozi.y][laozi.x]){
  22. count ++;
  23. }
  24. else{
  25. count = ;
  26. }
  27. if(count == ){
  28. return true;
  29. }
  30. }
  31. }
  32. return false;
  33. }

在这个函数里出现了一个新的函数——newpoint(point p, dir d, int lenth),其中point p 为 点的位置, int lenth 为长度, dir d 为单位向量
dir d 讲解 :dir 是创建的一个结构体,用来表示单位向量。它有很大的作用,通过它可以把横竖撇捺4个方向用一个简单的dir d 的 方向变量来处理,大大减少了代码量。代码如下:

  1. struct dir{
  2. int dy;
  3. int dx;
  4. };
  5.  
  6. const dir d1 = {, }; //横
  7. const dir d2 = {, }; //竖
  8. const dir d3 = {, -}; //撇
  9. const dir d4 = {, }; //捺
  10.  
  11. point gobang::newPoint (point p, dir d, int lenth){
  12. point p1 = {p.y + d.dy * lenth, p.x + d.dx * lenth};
  13. return p1;
  14. }

二、核心部分(电脑操作)讲解
             电脑的下棋就是要找出最佳点。什么是最佳点,最佳点的判断指标是什么?这就需要给每个点打分。
             打分的具体方法
                   1.在棋盘空位置上预先添加要判断的棋子;
                   2.选择横竖撇捺中的一个方向(利用dir d);
                   3.找出与中心点相连的棋子数量,并且利用left[5],right[5]数组存储连子左右两边各4个棋子的颜色情况(可能会遇到边界问题,解决办法:通过 isInBoard(point p) 函数判断棋子是否出边界,如果出边界,则棋子颜色视为反方(opp)棋子存储在数组中,如果没有出边界,则棋子按本来情况存储在数组中。
                   4.利用连子数量以及连子左右两边各4个棋子的颜色情况来判断棋型,是否为连五,活四(高级/低级),冲死,活三(高级或低级),眠三(高级或低级),活二,低级活二,眠二中的一种。
                   5.综合四个方向,进行打分:

情况1:能5, 给予14分;
情况2:能成4或者是双死4或者是43,给予13分;

情况3:能成双活3,给予12分;

情况4:能成33(高级),给予11分;

情况5:能成4,给予10分;

情况6:能成低级死4,给予9分;

情况7:能成单活3,给予8分;

情况8:能成跳活3,给予7分;

情况9:能成双活2,给予6分;

情况10:能成2,给予5分;

情况11:能成低级活2,给予4分;

情况12:能成3,给予3分;

情况13:能成2,给予2分;

情况14:其他情况(nothing),给予1分。

五子棋棋型知识(如果不知道可以看这里):

最常见的基本棋型大体有以下几种:连五,活四,冲四,活三,眠三,活二,眠二

①连五:顾名思义,五颗同色棋子连在一起,不需要多讲。
图2-1 

②活四:有两个连五点(即有两个点可以形成五),图中白点即为连五点。
稍微思考一下就能发现活四出现的时候,如果对方单纯过来防守的话,是已经无法阻止自己连五了。
图2-2 

③冲四:有一个连五点,如下面三图,均为冲四棋型。图中白点为连五点。
相对比活四来说,冲四的威胁性就小了很多,因为这个时候,对方只要跟着防守在那个唯一的连五点上,冲四就没法形成连五。
图2-3  图2-4  图2-5 

④活三:可以形成活四的三,如下图,代表两种最基本的活三棋型。图中白点为活四点。
活三棋型是我们进攻中最常见的一种,因为活三之后,如果对方不以理会,将可以下一手将活三变成活四,而我们知道活四是已经无法单纯防守住了。所以,当我们面对活三的时候,需要非常谨慎对待。在自己没有更好的进攻手段的情况下,需要对其进行防守,以防止其形成可怕的活四棋型。
图2-6  图2-7

其中图2-7中间跳着一格的活三,也可以叫做跳活三

⑤眠三只能够形成冲四的三,如下各图,分别代表最基础的六种眠三形状。图中白点代表冲四点。眠三的棋型与活三的棋型相比,危险系数下降不少,因为眠三棋型即使不去防守,下一手它也只能形成冲四,而对于单纯的冲四棋型,我们知道,是可以防守住的。
图2-8  图2-9  图2-10 

2-11 图2-12 图2-13

如上所示,眠三的形状是很丰富的。对于初学者,在下棋过程中,很容易忽略不常见的眠三形状,例如图2-13所示的眠三。

有新手学了活三眠三后,会提出疑问,说活三也可以形成冲四啊,那岂不是也可以叫眠三?
会提出这个问题,说明对眠三定义看得不够仔细:眠三的的定义是,只能够形成冲四的三。而活三可以形成眠三,但也能够形成活四。

此外,在五子棋中,活四棋型比冲四棋型具有更大的优势,所以,我们在既能够形成活四又能够形成冲四时,会选择形成活四。

温馨提示:学会判断一个三到底是活三还是眠三是非常重要的。所以,需要好好体会。
后边禁手判断的时候也会有所应用。

⑥活二:能够形成活三的二,如下图,是三种基本的活二棋型。图中白点为活三点。
活二棋型看起来似乎很无害,因为他下一手棋才能形成活三,等形成活三,我们再防守也不迟。但其实活二棋型是非常重要的,尤其是在开局阶段,我们形成较多的活二棋型的话,当我们将活二变成活三时,才能够令自己的活三绵绵不绝微风里,让对手防不胜防。
图2-14  图2-15  图2-16 

⑦眠二:能够形成眠三的二。图中四个为最基本的眠二棋型,细心且喜欢思考的同学会根据眠三介绍中的图2-13找到与下列四个基本眠二棋型都不一样的眠二。图中白点为眠三点。
图2-17 图2-18  
图2-19  图2-20 

这个部分是网上摘抄,网址:http://game.onegreen.net/wzq/HTML/142336.html   
      既然我们有了给每个点打分的方法,就该寻找最佳点了,但是这还不够,因为我们知道,下棋一般有两个思考方向,进攻或者防守(如果在给某点打分时放入的棋子为电脑棋子,则为进攻,反之,则为防守)。为什么要把进攻和防守分开考虑呢?为什么不可以把进攻得分和防守得分相加起来呢?我也试过,首先要把每种棋型的得分进行更改,即使这样也往往得不到一个好的结果。我可以通过一个比喻说明这个问题:某个学校举办学科竞赛,有语文和数学两个科目,但是每个班可以选择一名同学参加其中一项比赛,为此,老师对每个同学进行语文和数学测试,测试后,老师有2个方法寻找最佳的学生:1.语文和数学成绩一起考虑(比如相加)来寻找最佳学生;2.分别找出语文和数学成绩最好的两名同学,在比较选择。你们认为那种方法选出的学生比赛取得好成绩的概率更高呢?

通过这个比喻,我们寻找最佳点的方法也就出来,分别求出最佳进攻点,如果有多个最佳进攻点,则选择其中防守得分最高的,对于最佳防守点也如此。然后进一步比较,如果最佳进攻点得发大于等于最佳防守点,则以最佳进攻点为最佳点,反之,最佳防守点为最佳点。
具体代码如下:
void turnComputer()

  1. void gobang::turnComputer(){
  2. cout << "turn computer" << endl;
  3. point best1, best2;
  4. do{
  5. srand(time(NULL));
  6. best1.y = best2.y = rand()%;
  7. best1.x = best2.x = rand()%;
  8. }
  9. while(chessboard[best1.y][best1.x] != );
  10. int a1 = score(best1, computer), b1 = score(best1, player);
  11. for(int i = ; i < ; i ++){
  12. for(int j = ; j < ; j ++){
  13. if(chessboard[i][j] != ){
  14. continue;
  15. }
  16. point cur = {i, j};
  17. int m1 = score(cur, computer);
  18. int m2 = score(cur, player);
  19. if(m1 > a1){
  20. best1 = cur;
  21. a1 = m1;
  22. b1 = m2;
  23. }
  24. else if(m1 == a1){
  25. if(m2 > b1){
  26. best1 = cur;
  27. b1 = m2;
  28. }
  29. }
  30. }
  31. }
  32. int a2 = score(best2, player), b2 = score(best2, computer);
  33. for(int i = ; i < ; i ++){
  34. for(int j = ; j < ; j ++){
  35. if(chessboard[i][j] != ){
  36. continue;
  37. }
  38. point cur = {i, j};
  39. int m1 = score(cur, player);
  40. int m2 = score(cur, computer);
  41. if(m1 > a2){
  42. best2 = cur;
  43. a2 = m1;
  44. b2 = m2;
  45. }
  46. else if(m1 == a2){
  47. if(m2 > b2){
  48. best2 = cur;
  49. b2 = m2;
  50. }
  51. }
  52. }
  53. }
  54. if(a1 >= a2){
  55. laozi = best1;
  56. }
  57. else{
  58. laozi = best2;
  59. }
  60. chessboard[laozi.y][laozi.x] = computer;
  61. display();
  62. }

void score(point p, int who)

  1. int gobang::score(point p, int who){
  2. int win5 = , alive4 = , die4 = , ddie4 = , alive3 = ,
  3. dalive3 = , die3 = , alive2 = , dalive2 = , die2 = , nothing = ;
  4. int opp;
  5. if(who == ){
  6. opp = ;
  7. }
  8. else{
  9. opp = ;
  10. }
  11. for(int i = ; i <= ; i ++){
  12. dir d;
  13. switch(i){
  14. case :
  15. d = d1;
  16. break;
  17. case :
  18. d = d2;
  19. break;
  20. case :
  21. d = d3;
  22. break;
  23. case :
  24. d = d4;
  25. break;
  26. }
  27. int l = ;
  28. point le, ri, p1;
  29. int left[], right[];
  30. p1 = newPoint(p, d, -);
  31. le = p;
  32. while(isInBoard(p1) && chessboard[p1.y][p1.x] == who){
  33. le = p1;
  34. p1 = newPoint(p1, d, -);
  35. l ++;
  36. }
  37. p1 = newPoint(p, d, );
  38. ri = p;
  39. while(isInBoard(p1) && chessboard[p1.y][p1.x] == who){
  40. ri = p1;
  41. p1 = newPoint(p1, d, );
  42. l ++;
  43. }
  44. for(int j = ; j <= ; j ++){
  45. p1 = newPoint(le, d, -j);
  46. if(isInBoard(p1)){
  47. left[j] = chessboard[p1.y][p1.x];
  48. }
  49. else{
  50. left[j] = opp;
  51. }
  52. p1 = newPoint(ri, d, j);
  53. if(isInBoard(p1)){
  54. right[j] = chessboard[p1.y][p1.x];
  55. }
  56. else{
  57. right[j] = opp;
  58. }
  59. }
  60. //具体棋型判断
  61. if(l == ){
  62. win5 ++;
  63. }
  64. else if(l == ){
  65. if(left[] == && right[] == ){//alive4
  66. alive4 ++;
  67. }
  68. else if(left[] == || right[] == ){//die4
  69. die4 ++;
  70. }
  71. else{//nothing
  72. nothing ++;
  73. }
  74. }
  75. else if(l == ){
  76. if((left[] == && left[] == who) || (right[] == && right[] == who)){//ddie4
  77. ddie4 ++;
  78. }
  79. else if(left[] == && right[] == && (left[] == || right[] == )){//alive3
  80. alive3 ++;
  81. }
  82. else if((left[] == && left[] == ) || (right[] == && right[] == )){//die3
  83. die3 ++;
  84. }
  85. else if(left[] == && right[] == ){//die3
  86. die3 ++;
  87. }
  88. else{//nothing
  89. nothing ++;
  90. }
  91. }
  92. else if(l == ){
  93. if((left[] == && left[] == who && left[] == who) &&
  94. (right[] == && right[] == who && right[] == who)){//die4
  95. ddie4 ++;
  96. }
  97. else if(left[] == && right[] == &&
  98. ((left[] == who && left[] == ) || (right[] == who && right[] == ))){//dalive3
  99. dalive3 ++;
  100. }
  101. else if((left[] == && left[] == && left[] == who) ||
  102. (right[] == && right[] == && right[] == who)){//die3
  103. die3 ++;
  104. }
  105. else if((left[] == && right[] == ) &&
  106. (left[] == who || right[] == who)){//die3
  107. die3 ++;
  108. }
  109. else if((left[] == && left[] == && left[] == who) ||
  110. (right[] == && right[] == && right[] == who)){//die3
  111. die3 ++;
  112. }
  113. else if((left[] == && right[] == && right[] == && right[] == ) ||
  114. (left[] == && left[] == && right[] == && right[] == ) ||
  115. (left[] == && left[] == && left[] == && right[] == )){//alive2
  116. alive2 ++;
  117. }
  118. else if((left[] == && left[] == && left[] == ) ||
  119. (right[] == && right[] == && right[] == )){//die2
  120. die2 ++;
  121. }
  122. else{//nothing
  123. nothing ++;
  124. }
  125. }
  126. else if(l == ){
  127. if((left[] == && left[] == who && left[] == who && left[] == who) ||
  128. (right[] == && right[] == who && right[] == who && right[] == who)){//ddie4
  129. ddie4 ++;
  130. }
  131. else if((left[] == && right[] == ) && ((left[] == who && left[] == who && left[] == ) ||
  132. (right[] == who && right[] == who && right[] == ))){//dalive3
  133. dalive3 ++;
  134. }
  135. else if((left[] == && right[] == ) &&
  136. ((left[] == who && left[] == who) || (right[] == who && right[] == who))){//die3
  137. die3 ++;
  138. }
  139. else if((left[] == && left[] == && left[] == who && left[] == who) ||
  140. (right[] == && right[] == && right[] == who && right[] == who)){//die3
  141. die3 ++;
  142. }
  143. else if((left[] == && left[] == && left[] == who && left[] == who) ||
  144. (right[] == && right[] == && right[] == who && right[] == who)){//die3
  145. die3 ++;
  146. }
  147. else if((left[] == && left[] == && left[] == who && left[] == who) ||
  148. (right[] == && right[] == && right[] == who && right[] == who)){//die3
  149. die3 ++;
  150. }
  151. else if((left[] == && right[] == && right[] == && right[] == who) && (left[] == || right[] == )){//dalive2
  152. dalive2 ++;
  153. }
  154. else if((right[] == && left[] == && left[] == && left[] == who) &&
  155. (right[] == || left[] == )){//dalive2
  156. dalive2 ++;
  157. }
  158. else if((left[] == && right[] == && right[] == && right[] == && right[] == who) ||
  159. (right[] == && left[] == && left[] == && left[] == && left[] == who)){//dalive2
  160. dalive2 ++;
  161. }
  162. else if((left[] == && left[] == && left[] == && left[] == who) ||
  163. (right[] == && right[] == && right[] == && right[] == who)){//die2
  164. die2 ++;
  165. }
  166. else if((left[] == && right[] == && right[] == && left[] == who) ||
  167. (right[] == && left[] == && left[] == && right[] == who)){//die2
  168. die2 ++;
  169. }
  170. else if((left[] == && left[] == && left[] == && left[] == who) ||
  171. (right[] == && right[] == && right[] == && right[] == who)){//die2
  172. die2 ++;
  173. }
  174. else if((left[] == && left[] == && right[] == && left[] == who) ||
  175. (right[] == && right[] == && left[] == && right[] == who)){//die2
  176. die2 ++;
  177. }
  178. else if((left[] == && left[] == && left[] == && left[] == who) ||
  179. (right[] == && right[] == && right[] == && right[] == who)){//die2
  180. die2 ++;
  181. }
  182. else{//nothing
  183. nothing ++;
  184. }
  185. }
  186. }
  187. if (win5 >= )
  188. return ;//赢5
  189.  
  190. if (alive4 >= || die4 >= || (die4 >= && alive3 >= ))
  191. return ;//活4 双死4 死4活3
  192.  
  193. if (alive3 >= )
  194. return ;//双活3
  195.  
  196. if (die3 >= && alive3 >= )
  197. return ;//死3高级活3
  198.  
  199. if (die4 >= )
  200. return ;//高级死4
  201.  
  202. if (ddie4 >= )
  203. return ;//低级死4
  204.  
  205. if (alive3 >= )
  206. return ;//单活3
  207.  
  208. if (dalive3 >= )
  209. return ;//跳活3
  210.  
  211. if (alive2 >= )
  212. return ;//双活2
  213.  
  214. if (alive2 >= )
  215. return ;//活2
  216.  
  217. if (dalive2 >= )
  218. return ;//低级活2
  219.  
  220. if (die3 >= )
  221. return ;//死3
  222.  
  223. if (die2 >= )
  224. return ;//死2
  225.  
  226. return ;//没有威胁
  227. }

 

三、完整代码

  1. #include <iostream>
  2. #include <conio.h>
  3. #include <ctime>
  4. #include <cstdlib>
  5. using namespace std;
  6.  
  7. struct point{
  8. int y;
  9. int x;
  10. };
  11. struct dir{
  12. int dy;
  13. int dx;
  14. };
  15. const dir d1 = {, };//横
  16. const dir d2 = {, };//竖
  17. const dir d3 = {, -};//撇
  18. const dir d4 = {, };//捺
  19.  
  20. class gobang{
  21. private:
  22. int chessboard[][];//记录棋盘信息
  23. int player;//玩家棋子
  24. int computer;//电脑棋子
  25. int Y, X;//光标位置
  26. point laozi;//落子位置
  27. public:
  28. void play();
  29. int selMode();
  30. void turnPlayer();
  31. void turnComputer();
  32. bool isEnd();
  33. protected:
  34. bool isInBoard(point p);
  35. void display();
  36. int score(point p, int who);
  37. point newPoint(point p, dir d, int lenth);
  38. };
  39. void gobang::play(){
  40. int i = selMode();
  41. if(i == ){
  42. computer = ;
  43. player = ;
  44. }
  45. else{
  46. player = ;
  47. computer = ;
  48. }
  49. int cur = ;
  50. while(){
  51. if(cur == player){
  52. turnPlayer();
  53. }
  54. else{
  55. turnComputer();
  56. }
  57. if(isEnd()){
  58. if(cur == player){
  59. cout << "Player Win !";
  60. system("pause");
  61. break;
  62. }
  63. else{
  64. cout << "Computer Win !";
  65. system("pause");
  66. break;
  67. }
  68. }
  69. else{
  70. cur = (cur == ) ? : ;
  71. }
  72. }
  73. }
  74. int gobang::selMode(){
  75. system("cls");
  76. cout << "*************************************************" << endl;
  77. cout << "******************0、退出************************" << endl;
  78. cout << "******************1、电脑先手********************" << endl;
  79. cout << "******************2、玩家先手********************" << endl;
  80. cout << "*************************************************" << endl;
  81. while(){
  82. int i;
  83. cin >> i;
  84. if(i == ){
  85. exit();
  86. }
  87. else if(i == || i == ){
  88. Y = ;
  89. X = ;
  90. for(int j = ; j < ; j ++){
  91. for(int k = ; k < ; k ++){
  92. chessboard[j][k] = ;
  93. }
  94. }
  95. display();
  96. return i;
  97. }
  98. else{
  99. cout << "非法输入,请重新输入!" << endl;
  100. }
  101. }
  102. }
  103. void gobang::turnPlayer(){
  104. cout << "turn player" << endl;
  105. while(){
  106. char c = getch();
  107. if(c == 'w'){
  108. if(Y != ){
  109. Y --;
  110. display();
  111. }
  112. }
  113. else if(c == 's'){
  114. if(Y != ){
  115. Y ++;
  116. display();
  117. }
  118.  
  119. }
  120. else if(c == 'a'){
  121. if(X != ){
  122. X --;
  123. display();
  124. }
  125. }
  126. else if(c == 'd'){
  127. if(X != ){
  128. X ++;
  129. display();
  130. }
  131. }
  132. else if(c == 'j' && chessboard[Y][X] == ){
  133. laozi.y = Y;
  134. laozi.x = X;
  135. chessboard[Y][X] = player;
  136. display();
  137. break;
  138. }
  139. }
  140. }
  141. void gobang::turnComputer(){
  142. cout << "turn computer" << endl;
  143. point best1, best2;
  144. do{
  145. srand(time(NULL));
  146. best1.y = best2.y = rand()%;
  147. best1.x = best2.x = rand()%;
  148. }
  149. while(chessboard[best1.y][best1.x] != );
  150. int a1 = score(best1, computer), b1 = score(best1, player);
  151. for(int i = ; i < ; i ++){
  152. for(int j = ; j < ; j ++){
  153. if(chessboard[i][j] != ){
  154. continue;
  155. }
  156. point cur = {i, j};
  157. int m1 = score(cur, computer);
  158. int m2 = score(cur, player);
  159. if(m1 > a1){
  160. best1 = cur;
  161. a1 = m1;
  162. b1 = m2;
  163. }
  164. else if(m1 == a1){
  165. if(m2 > b1){
  166. best1 = cur;
  167. b1 = m2;
  168. }
  169. }
  170. }
  171. }
  172. int a2 = score(best2, player), b2 = score(best2, computer);
  173. for(int i = ; i < ; i ++){
  174. for(int j = ; j < ; j ++){
  175. if(chessboard[i][j] != ){
  176. continue;
  177. }
  178. point cur = {i, j};
  179. int m1 = score(cur, player);
  180. int m2 = score(cur, computer);
  181. if(m1 > a2){
  182. best2 = cur;
  183. a2 = m1;
  184. b2 = m2;
  185. }
  186. else if(m1 == a2){
  187. if(m2 > b2){
  188. best2 = cur;
  189. b2 = m2;
  190. }
  191. }
  192. }
  193. }
  194. if(a1 >= a2){
  195. laozi = best1;
  196. }
  197. else{
  198. laozi = best2;
  199. }
  200. chessboard[laozi.y][laozi.x] = computer;
  201. display();
  202. }
  203. int gobang::score(point p, int who){
  204. int win5 = , alive4 = , die4 = , ddie4 = , alive3 = ,
  205. dalive3 = , die3 = , alive2 = , dalive2 = , die2 = , nothing = ;
  206. int opp;
  207. if(who == ){
  208. opp = ;
  209. }
  210. else{
  211. opp = ;
  212. }
  213. for(int i = ; i <= ; i ++){
  214. dir d;
  215. switch(i){
  216. case :
  217. d = d1;
  218. break;
  219. case :
  220. d = d2;
  221. break;
  222. case :
  223. d = d3;
  224. break;
  225. case :
  226. d = d4;
  227. break;
  228. }
  229. int l = ;
  230. point le, ri, p1;
  231. int left[], right[];
  232. p1 = newPoint(p, d, -);
  233. le = p;
  234. while(isInBoard(p1) && chessboard[p1.y][p1.x] == who){
  235. le = p1;
  236. p1 = newPoint(p1, d, -);
  237. l ++;
  238. }
  239. p1 = newPoint(p, d, );
  240. ri = p;
  241. while(isInBoard(p1) && chessboard[p1.y][p1.x] == who){
  242. ri = p1;
  243. p1 = newPoint(p1, d, );
  244. l ++;
  245. }
  246. for(int j = ; j <= ; j ++){
  247. p1 = newPoint(le, d, -j);
  248. if(isInBoard(p1)){
  249. left[j] = chessboard[p1.y][p1.x];
  250. }
  251. else{
  252. left[j] = opp;
  253. }
  254. p1 = newPoint(ri, d, j);
  255. if(isInBoard(p1)){
  256. right[j] = chessboard[p1.y][p1.x];
  257. }
  258. else{
  259. right[j] = opp;
  260. }
  261. }
  262. //具体棋型判断
  263. if(l == ){
  264. win5 ++;
  265. }
  266. else if(l == ){
  267. if(left[] == && right[] == ){//alive4
  268. alive4 ++;
  269. }
  270. else if(left[] == || right[] == ){//die4
  271. die4 ++;
  272. }
  273. else{//nothing
  274. nothing ++;
  275. }
  276. }
  277. else if(l == ){
  278. if((left[] == && left[] == who) || (right[] == && right[] == who)){//ddie4
  279. ddie4 ++;
  280. }
  281. else if(left[] == && right[] == && (left[] == || right[] == )){//alive3
  282. alive3 ++;
  283. }
  284. else if((left[] == && left[] == ) || (right[] == && right[] == )){//die3
  285. die3 ++;
  286. }
  287. else if(left[] == && right[] == ){//die3
  288. die3 ++;
  289. }
  290. else{//nothing
  291. nothing ++;
  292. }
  293. }
  294. else if(l == ){
  295. if((left[] == && left[] == who && left[] == who) &&
  296. (right[] == && right[] == who && right[] == who)){//die4
  297. ddie4 ++;
  298. }
  299. else if(left[] == && right[] == &&
  300. ((left[] == who && left[] == ) || (right[] == who && right[] == ))){//dalive3
  301. dalive3 ++;
  302. }
  303. else if((left[] == && left[] == && left[] == who) ||
  304. (right[] == && right[] == && right[] == who)){//die3
  305. die3 ++;
  306. }
  307. else if((left[] == && right[] == ) &&
  308. (left[] == who || right[] == who)){//die3
  309. die3 ++;
  310. }
  311. else if((left[] == && left[] == && left[] == who) ||
  312. (right[] == && right[] == && right[] == who)){//die3
  313. die3 ++;
  314. }
  315. else if((left[] == && right[] == && right[] == && right[] == ) ||
  316. (left[] == && left[] == && right[] == && right[] == ) ||
  317. (left[] == && left[] == && left[] == && right[] == )){//alive2
  318. alive2 ++;
  319. }
  320. else if((left[] == && left[] == && left[] == ) ||
  321. (right[] == && right[] == && right[] == )){//die2
  322. die2 ++;
  323. }
  324. else{//nothing
  325. nothing ++;
  326. }
  327. }
  328. else if(l == ){
  329. if((left[] == && left[] == who && left[] == who && left[] == who) ||
  330. (right[] == && right[] == who && right[] == who && right[] == who)){//ddie4
  331. ddie4 ++;
  332. }
  333. else if((left[] == && right[] == ) && ((left[] == who && left[] == who && left[] == ) ||
  334. (right[] == who && right[] == who && right[] == ))){//dalive3
  335. dalive3 ++;
  336. }
  337. else if((left[] == && right[] == ) &&
  338. ((left[] == who && left[] == who) || (right[] == who && right[] == who))){//die3
  339. die3 ++;
  340. }
  341. else if((left[] == && left[] == && left[] == who && left[] == who) ||
  342. (right[] == && right[] == && right[] == who && right[] == who)){//die3
  343. die3 ++;
  344. }
  345. else if((left[] == && left[] == && left[] == who && left[] == who) ||
  346. (right[] == && right[] == && right[] == who && right[] == who)){//die3
  347. die3 ++;
  348. }
  349. else if((left[] == && left[] == && left[] == who && left[] == who) ||
  350. (right[] == && right[] == && right[] == who && right[] == who)){//die3
  351. die3 ++;
  352. }
  353. else if((left[] == && right[] == && right[] == && right[] == who) && (left[] == || right[] == )){//dalive2
  354. dalive2 ++;
  355. }
  356. else if((right[] == && left[] == && left[] == && left[] == who) &&
  357. (right[] == || left[] == )){//dalive2
  358. dalive2 ++;
  359. }
  360. else if((left[] == && right[] == && right[] == && right[] == && right[] == who) ||
  361. (right[] == && left[] == && left[] == && left[] == && left[] == who)){//dalive2
  362. dalive2 ++;
  363. }
  364. else if((left[] == && left[] == && left[] == && left[] == who) ||
  365. (right[] == && right[] == && right[] == && right[] == who)){//die2
  366. die2 ++;
  367. }
  368. else if((left[] == && right[] == && right[] == && left[] == who) ||
  369. (right[] == && left[] == && left[] == && right[] == who)){//die2
  370. die2 ++;
  371. }
  372. else if((left[] == && left[] == && left[] == && left[] == who) ||
  373. (right[] == && right[] == && right[] == && right[] == who)){//die2
  374. die2 ++;
  375. }
  376. else if((left[] == && left[] == && right[] == && left[] == who) ||
  377. (right[] == && right[] == && left[] == && right[] == who)){//die2
  378. die2 ++;
  379. }
  380. else if((left[] == && left[] == && left[] == && left[] == who) ||
  381. (right[] == && right[] == && right[] == && right[] == who)){//die2
  382. die2 ++;
  383. }
  384. else{//nothing
  385. nothing ++;
  386. }
  387. }
  388. }
  389. if (win5 >= )
  390. return ;//赢5
  391.  
  392. if (alive4 >= || die4 >= || (die4 >= && alive3 >= ))
  393. return ;//活4 双死4 死4活3
  394.  
  395. if (alive3 >= )
  396. return ;//双活3
  397.  
  398. if (die3 >= && alive3 >= )
  399. return ;//死3高级活3
  400.  
  401. if (die4 >= )
  402. return ;//高级死4
  403.  
  404. if (ddie4 >= )
  405. return ;//低级死4
  406.  
  407. if (alive3 >= )
  408. return ;//单活3
  409.  
  410. if (dalive3 >= )
  411. return ;//跳活3
  412.  
  413. if (alive2 >= )
  414. return ;//双活2
  415.  
  416. if (alive2 >= )
  417. return ;//活2
  418.  
  419. if (dalive2 >= )
  420. return ;//低级活2
  421.  
  422. if (die3 >= )
  423. return ;//死3
  424.  
  425. if (die2 >= )
  426. return ;//死2
  427.  
  428. return ;//没有威胁
  429. }
  430. bool gobang::isEnd(){
  431. for(int i = ; i <= ; i ++){
  432. dir d;
  433. int count = ;
  434. switch(i){
  435. case :
  436. d = d1;
  437. break;
  438. case :
  439. d = d2;
  440. break;
  441. case :
  442. d = d3;
  443. break;
  444. case :
  445. d = d4;
  446. break;
  447. }
  448. for(int j = -; j <= ; j ++){
  449. point p1 = newPoint(laozi, d, j);
  450. if(isInBoard(p1) && chessboard[p1.y][p1.x] == chessboard[laozi.y][laozi.x]){
  451. count ++;
  452. }
  453. else{
  454. count = ;
  455. }
  456. if(count == ){
  457. return true;
  458. }
  459. }
  460. }
  461. return false;
  462. }
  463. bool gobang::isInBoard(point p){
  464. if(p.y >= && p.y < && p.x >= && p.x < ){
  465. return true;
  466. }
  467. else{
  468. return false;
  469. }
  470. }
  471.  
  472. point gobang::newPoint (point p, dir d, int lenth){
  473. point p1 = {p.y + d.dy * lenth, p.x + d.dx * lenth};
  474. return p1;
  475. }
  476. void gobang::display(){
  477. system("cls");
  478. for(int i = ; i < ; i ++){
  479. for(int j = ; j < ; j ++){
  480. if(i == Y && j == X){
  481. cout << "╋";
  482. }
  483. else if(chessboard[i][j] == ){
  484. cout << "○";
  485. }
  486. else if(chessboard[i][j] == ){
  487. cout << "●";
  488. }
  489. else{
  490. cout << ". ";
  491. }
  492.  
  493. }
  494. cout << endl;
  495. }
  496. }
  497. int main(){
  498. gobang game;
  499. game.play();
  500. return ;
  501. }

  

四、写五子棋程序的建议:          
               1.首先要寻找好的代码,如果是那种完全是代码却一点都没有讲解的还是不要看了,给我帮助的博客有:https://www.cnblogs.com/songdechiu/p/5768999.html                              https://www.jb51.net/article/105675.htm
               2.要先有规划,这就好比新年家里要大扫除,如果不做规划,就不知道从何开始,进行到哪里,做得怎么样。我一开始没有规划,盲目打代码,结果必定的错误百出,而且还难以寻找错误(连自己的代码为什么这样写都糊里糊涂),后来重新开始,先写一个思路图,在打代码,最后检查错误,时间节省了很多。
             
               3.完成之后,不妨教给别人(写博客是个好方法,可是应该没什么人看),在写的过程中,我要思考如何把一些问题讲清楚明白,让不会的人能理解,虽然我只是学到了皮毛,但是在这个过程中对程序的理解又有所提升。
        最后、因为我这个五子棋程序很简单,下赢它不难(我不太会五子棋,下不赢5555),我希望自己可以用博弈树在写一个五子棋程序,加油吧!

C++ 之 简单的五子棋AI程序的更多相关文章

  1. 使用QT creator实现一个五子棋AI包括GUI实现(8K字超详细)

    五子棋AI实现 五子棋游戏介绍 五子棋的定义 五子棋是全国智力运动会竞技项目之一,是具有完整信息的.确定性的.轮流行动的.两个游戏者的零和游戏.因此,五子棋是一个博弈问题. 五子棋的玩法 五子棋有两种 ...

  2. 五子棋AI大战OC实现

    Gobang 五子棋AI大战,该项目主要用到MVC框架,用算法搭建AI实现进攻或防守 一.项目介绍 1.地址: github地址:Gobang 2.效果图: 二.思路介绍 大概说下思路,具体看代码实现 ...

  3. 用c语言实现简单的五子棋

    用c语言实现简单的五子棋 这个小游戏是从零开始的实现的,框架灵感来自于小游戏<走迷宫>. 游戏代码配置: 二维数组+简单逻辑+getch读取键盘+windows函数(刷屏,改颜色,改窗口大 ...

  4. 五子棋AI清月连珠开源

    经过差不多两年的业余时间学习和编写,最近把清月连珠的无禁手部分完善得差不多了.这中间进行了很多思考,也有很多错误认识,到现在有一些东西还没有全面掌握,所以想通过开源于大家共同交流. 最近一直发表一些五 ...

  5. 一个简单的P2P传输程序

    写了一个简单的P2P传输程序,在P2P的圈子中传输文件,不过为了简便,这个程序没有真正的传输文件,只是简单的判断一下文件的位置在哪里.这个程序可以处理当有一个peer闪退的情况,在这种情况下,剩下的p ...

  6. 循序渐进做项目系列(2):最简单的C/S程序——消息异步调用与消息同步调用

    上篇博客 循序渐进做项目系列(1):最简单的C/S程序——让服务器来做加法 实现了一个最简单的C/S程序,即让服务器来做加法.当时为了通俗易懂采用了消息异步调用的方式.今天我们要采用消息同步调用的方式 ...

  7. IOS开发之小实例--使用UIImagePickerController创建一个简单的相机应用程序

    前言:本篇博文是本人阅读国外的IOS Programming Tutorial的一篇入门文章的学习过程总结,难度不大,因为是入门.主要是入门UIImagePickerController这个控制器,那 ...

  8. iOS开发UI篇—简单的浏览器查看程序

    iOS开发UI篇—简单的浏览器查看程序 一.程序实现要求 1.要求 2. 界面分析 (1) 需要读取或修改属性的控件需要设置属性 序号标签 图片 图片描述 左边按钮 右边按钮 (2) 需要监听响应事件 ...

  9. iOS开发UI篇—使用嵌套模型完成的一个简单汽车图标展示程序

    iOS开发UI篇—使用嵌套模型完成的一个简单汽车图标展示程序 一.plist文件和项目结构图 说明:这是一个嵌套模型的示例 二.代码示例: YYcarsgroup.h文件代码: // // YYcar ...

随机推荐

  1. HTML5 CSS3专题 诱人的实例 CSS3打造百度贴吧的3D翻牌效果

    首先感谢w3cfuns的老师~ 今天给大家带来一个CSS3制作的翻牌效果,就是鼠标移到元素上,感觉可以看到元素背后的信息.大家如果制作考验记忆力的连连看.扑克类的游戏神马的,甚至给女朋友写一些话语,放 ...

  2. 【转载】JavaScript基础知识体系

    前言 最近总是有一种感觉,对于知识没有积淀,很多时候都是忘记了哪里就去查一下,比如JS这种语言,很是浪费时间,如果能够把这些知识形成知识体系塞进大脑,做到即用即取就好了,那么就可以借助思维导图来帮助我 ...

  3. python中RabbitMQ的使用(安装和简单教程)

    1,简介 RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现的产品,RabbitMQ是一个消息代理,从"生产者"接收消息 ...

  4. machine learning 之 Anomaly detection

    自Andrew Ng的machine learning课程. 目录: Problem Motivation Gaussian Distribution Algorithm Developing and ...

  5. j2ee 使用db.properties连接mysql数据库

    转自: http://blog.csdn.net/u013815546/article/details/50808493 注: 下面的方法是未安装构架的写法,需要自己加载驱动并建立连接. 若引入了Ac ...

  6. bzoj 2653 middle 二分答案 主席树判定

    判断中位数是否可行需要将当前的解作为分界,大于其的置为1,小于为-1,然后b-c必选,ab,cd可不选,这个用线段树判定就好 但不能每次跑,所以套主席树,按权值排序,构建主席树,更新时将上一个节点改为 ...

  7. stm32的NVIC是什么?

    NVIC的全称是Nested vectoredinterrupt controller,即嵌套向量中断控制器.    对于M3和M4内核的MCU,每个中断的优先级都是用寄存器中的8位来设置的.8位的话 ...

  8. BZOJ1500 [NOI2005]维修数列-fhq_Treap

    题面见这里 反正是道平衡树,就拿 fhq_Treap 写了写... 这道题思路基本是围绕“用 Treap 维护中序遍历” 和 中序遍历的性质 来进行的操作 所以就可以类比线段树进行一些操作 1. 建树 ...

  9. OpenLayer实现路径运动

    近期由于业务的需求,让我这从未想过要碰Web Gis的业余前端开发者,走了Web Gis的开发道路.功能需求很简单,但却也是让自己难为了好几天.如,应该选择那个Gis框架,Gis框架的兼容性如何,直接 ...

  10. PHP过滤数组中的空值

    php对数组的操作已经很完善了,提供给我们很多内置函数用以操作数组,其实可以用array_filter函数对PHP数组中的控制进行过滤 array_filter() 函数用回调函数过滤数组中的值.该函 ...