zoukankan      html  css  js  c++  java
  • C++小程序之五子棋

    1)运行的环境:VS2015。

    2)目的:主要是在控制台实现简单的五子棋操作,黑棋先行,输入xy(坐标)即表示落子。代码如下:

      1 #include <iostream>
      2 #include <conio.h>
      3 #include <string>
      4 
      5 using namespace std;
      6 char board[16][16], o;
      7 
      8 //此函数是存储一个棋盘矩阵16*16,注意board是全局变量,所以没有返回
      9 void init() {
     10     for (int i = 1; i <= 31; i++)
     11         for (int j = 1; j <= 31; j++)
     12             board[i][j] = '+';
     13     for (int i = 1, ii = 0; ii <= 30; i++, ii += 2) board[0][i] = i + 64;   // A的ascll码对应65
     14     for (int j = 1, jj = 0; jj <= 30; j++, jj += 2) board[j][0] = j + 64;
     15     board[0][0] = '*';
     16     //// 调试
     17     //for (int i = 0; i < 16; ++i) {
     18     //    for (int j = 0; j < 16; ++j) cout << board[i][j] << " ";
     19     //    cout << endl;
     20     //}
     21     
     22 }
     23 
     24 // 打印棋盘状态,其实就是打印全局变量board,+是棋子放置的中心点
     25 void display() {
     26     cout << "|================================================|" << endl;
     27     for (int i = 0; i <= 15; i++) {
     28         cout << "|";
     29         for (int j = 0; j <= 15; j++) {
     30             cout << board[i][j];
     31             if (j != 15 && i != 0) cout << "--";
     32             else cout << "  ";
     33         }
     34         cout << "|" << endl << "|   |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |" << endl;
     35     }
     36     cout << "|================================================|" << endl;
     37 }
     38 
     39 /*
     40 此函数是放置棋子。
     41 先确定是何种颜色的棋子,然后根据输入的放置位置(行,列),判断是否是非法放置。
     42 若是非法放置,重新放置,回掉;否则修改board,将对应位置的+变字母。
     43 color:0代表黑棋,1代表白色。
     44 */
     45 void place(bool color) {
     46     string colour;
     47     char x, y;   // x是行,y是列数
     48     x = y = ' ';
     49     system("cls");
     50     display();
     51     if (!color) colour = "";
     52     if (color) colour = "";
     53     cout << colour << "方放置棋子,请输入棋子的行和列(大写字母):";
     54     cin >> x >> y;
     55     if (x - 64>16 || y - 64>16 || x - 64<1 || y - 64<1) {
     56         cout << "该位置超出棋盘范围,请重新放置!" << x << y << endl;
     57         system("pause");
     58         place(color);
     59     }
     60     if (board[x - 64][y - 64] == 'b' || board[x - 64][y - 64] == 'w') {
     61         cout << "该位置已有棋子" << board[x - 64][y - 64] << ",请重新放置!" << endl;
     62         system("pause");
     63         place(color);
     64     }
     65     if (!color) board[x - 64][y - 64] = 'b';
     66     if (color) board[x - 64][y - 64] = 'w';
     67 }
     68 
     69 // 判断输赢,返回225是和棋,0是黑方胜,1是白的胜利。
     70 int compute() {
     71     int num=0;   // 统计棋盘上棋子的总共个数
     72     for (int i = 1; i <= 15; i++)
     73         for (int j = 1; j <= 15; j++)
     74             if (board[i][j] == 'b' || board[i][j] == 'w') num++;
     75     if (num == 225) return 2;
     76     // 下面判断输赢,这段应该可以优化,存在重复判断了
     77     for (int i = 1; i <= 15; i++)
     78         for (int j = 1; j <= 15; j++) {
     79             if (board[i][j] == 'b'&&board[i][j] == board[i + 1][j] && board[i][j] == board[i + 2][j] && board[i][j] == board[i + 3][j] && board[i][j] == board[i + 4][j]) return 0;
     80             if (board[i][j] == 'w'&&board[i][j] == board[i + 1][j] && board[i][j] == board[i + 2][j] && board[i][j] == board[i + 3][j] && board[i][j] == board[i + 4][j]) return 1;
     81             if (board[i][j] == 'b'&&board[i][j] == board[i][j + 1] && board[i][j] == board[i][j + 2] && board[i][j] == board[i][j + 3] && board[i][j] == board[i][j + 4]) return 0;
     82             if (board[i][j] == 'w'&&board[i][j] == board[i][j + 1] && board[i][j] == board[i][j + 2] && board[i][j] == board[i][j + 3] && board[i][j] == board[i][j + 4]) return 1;
     83             if (board[i][j] == 'b'&&board[i][j] == board[i + 1][j + 1] && board[i][j] == board[i + 2][j + 2] && board[i][j] == board[i + 3][j + 3] && board[i][j] == board[i + 4][j + 4]) return 0;
     84             if (board[i][j] == 'w'&&board[i][j] == board[i + 1][j + 1] && board[i][j] == board[i + 2][j + 2] && board[i][j] == board[i + 3][j + 3] && board[i][j] == board[i + 4][j + 4]) return 1;
     85             if (board[i][j] == 'b'&&board[i][j] == board[i - 1][j + 1] && board[i][j] == board[i - 2][j + 2] && board[i][j] == board[i - 3][j + 3] && board[i][j] == board[i - 4][j + 4]) return 0;
     86             if (board[i][j] == 'w'&&board[i][j] == board[i - 1][j + 1] && board[i][j] == board[i - 2][j + 2] && board[i][j] == board[i - 3][j + 3] && board[i][j] == board[i - 4][j + 4]) return 1;
     87         }
     88     return -1;
     89 }
     90 int main() {
     91 game_start:
     92     init();
     93     system("cls");                            //  system()函数是发出一条DOS命令,“cls”应该是清空的意思
     94     system("title 双人五子棋");              //  设置CMD窗口标题
     95     cout << "Copyright (C) XiyuWang 2018 All rights reserved." << endl;
     96     cout << "双人五子棋小游戏" << endl;
     97     cout << "小提示:棋盘中b代表黑方(black),w代表白方(white)" << endl;
     98     cout << "请按任意键开始游戏......";
     99     _getch();           // 从控制台读取一个字符,但不显示在屏幕上。可以赋值,此函数有返回值
    100     while (true) {
    101         place(0);
    102         if (compute() == 0) {
    103             system("cls");
    104             display();
    105             cout << "黑方胜!" << endl;
    106             break;
    107         }
    108         if (compute() == 2) {
    109             system("cls");
    110             display();
    111             cout << "平局!" << endl;
    112             break;
    113         }
    114         place(1);
    115         if (compute() == 1) {
    116             system("cls");
    117             display();
    118             cout << "白方胜!" << endl;
    119             break;
    120         }
    121         if (compute() == 2) {
    122             system("cls");
    123             display();
    124             cout << "平局!" << endl;
    125             break;
    126         }
    127     }
    128     cout << "再来一局?Y/N  ";
    129     o = _getch();             // 这里_getch()抓取控制台输入,但是控制台不显示
    130     if (o == 'Y' || o == 'y') goto game_start;
    131     return 0;
    132 }
    第一版

    3)问题:

    调试发现存在bug,比如:黑棋已经落在(A,A)点,此时白棋输入(A,A)后判断为非法输入,会被要求重新输入。

    至此没问题,但是重新输入合法的白棋位置后,刷新显示,发现上一次错误输入的(A,A)也变成白棋。

    4) 找到问题原因:

    如重复放置,会进入60行判断,并进入此if。然后再这if中回调自身。接着再次输入,正确,不进入此if,一直运行到65行,并成功放置。

    但是此时只是上一次错误放置进入if中的那个会调结束。因此,还会再次进入65行,并进去。就像递归。不行可以打断点调试。

    5)尝试解决如下:修改重复放置的判断

    将连if改为if .... else if就可以,因为回调的函数返回是在else if (重复放)里面,这个已经与下面两个是排斥的选择。

    #include <iostream>
    #include <conio.h>
    #include <string>
    
    using namespace std;
    char board[16][16], o;
    
    //此函数是存储一个棋盘矩阵16*16,注意board是全局变量,所以没有返回
    void init() {
        for (int i = 1; i <= 31; i++)
            for (int j = 1; j <= 31; j++)
                board[i][j] = '+';
        for (int i = 1, ii = 0; ii <= 30; i++, ii += 2) board[0][i] = i + 64;   // A的ascll码对应65
        for (int j = 1, jj = 0; jj <= 30; j++, jj += 2) board[j][0] = j + 64;
        board[0][0] = '*';
        //// 调试
        //for (int i = 0; i < 16; ++i) {
        //    for (int j = 0; j < 16; ++j) cout << board[i][j] << " ";
        //    cout << endl;
        //}
        
    }
    
    // 打印棋盘状态,其实就是打印全局变量board,+是棋子放置的中心点
    void display() {
        cout << "|================================================|" << endl;
        for (int i = 0; i <= 15; i++) {
            cout << "|";
            for (int j = 0; j <= 15; j++) {
                cout << board[i][j];
                if (j != 15 && i != 0) cout << "--";
                else cout << "  ";
            }
            cout << "|" << endl << "|   |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |" << endl;
        }
        cout << "|================================================|" << endl;
    }
    
    /*
    此函数是放置棋子。
    先确定是何种颜色的棋子,然后根据输入的放置位置(行,列),判断是否是非法放置。
    若是非法放置,重新放置,回掉;否则修改board,将对应位置的+变字母。
    color:0代表黑棋,1代表白色。
    */
    void place(bool color) {
        string colour;
        char x, y;   // x是行,y是列数
        x = y = ' ';
        system("cls");
        display();
        if (!color) colour = "";
        if (color) colour = "";
        cout << colour << "方放置棋子,请输入棋子的行和列(大写字母):";
        cin >> x >> y;
        if (x - 64>16 || y - 64>16 || x - 64<1 || y - 64<1) {
            cout << "该位置超出棋盘范围,请重新放置!" << x << y << endl;
            system("pause");
            place(color);
        }
        else if (board[x - 64][y - 64] == 'b' || board[x - 64][y - 64] == 'w') {
            cout << "该位置已有棋子" << board[x - 64][y - 64] << ",请重新放置!" << endl;
            system("pause");
            place(color);
        }
        else if (!color) board[x - 64][y - 64] = 'b';
        else  board[x - 64][y - 64] = 'w';
    }
    
    // 判断输赢,返回225是和棋,0是黑方胜,1是白的胜利。
    int compute() {
        int num=0;   // 统计棋盘上棋子的总共个数
        for (int i = 1; i <= 15; i++)
            for (int j = 1; j <= 15; j++)
                if (board[i][j] == 'b' || board[i][j] == 'w') num++;
        if (num == 225) return 2;
        // 下面判断输赢,这段应该可以优化,存在重复判断了
        for (int i = 1; i <= 15; i++)
            for (int j = 1; j <= 15; j++) {
                if (board[i][j] == 'b'&&board[i][j] == board[i + 1][j] && board[i][j] == board[i + 2][j] && board[i][j] == board[i + 3][j] && board[i][j] == board[i + 4][j]) return 0;
                if (board[i][j] == 'w'&&board[i][j] == board[i + 1][j] && board[i][j] == board[i + 2][j] && board[i][j] == board[i + 3][j] && board[i][j] == board[i + 4][j]) return 1;
                if (board[i][j] == 'b'&&board[i][j] == board[i][j + 1] && board[i][j] == board[i][j + 2] && board[i][j] == board[i][j + 3] && board[i][j] == board[i][j + 4]) return 0;
                if (board[i][j] == 'w'&&board[i][j] == board[i][j + 1] && board[i][j] == board[i][j + 2] && board[i][j] == board[i][j + 3] && board[i][j] == board[i][j + 4]) return 1;
                if (board[i][j] == 'b'&&board[i][j] == board[i + 1][j + 1] && board[i][j] == board[i + 2][j + 2] && board[i][j] == board[i + 3][j + 3] && board[i][j] == board[i + 4][j + 4]) return 0;
                if (board[i][j] == 'w'&&board[i][j] == board[i + 1][j + 1] && board[i][j] == board[i + 2][j + 2] && board[i][j] == board[i + 3][j + 3] && board[i][j] == board[i + 4][j + 4]) return 1;
                if (board[i][j] == 'b'&&board[i][j] == board[i - 1][j + 1] && board[i][j] == board[i - 2][j + 2] && board[i][j] == board[i - 3][j + 3] && board[i][j] == board[i - 4][j + 4]) return 0;
                if (board[i][j] == 'w'&&board[i][j] == board[i - 1][j + 1] && board[i][j] == board[i - 2][j + 2] && board[i][j] == board[i - 3][j + 3] && board[i][j] == board[i - 4][j + 4]) return 1;
            }
        return -1;
    }
    int main() {
    game_start:
        init();
        system("cls");                            //  system()函数是发出一条DOS命令,“cls”应该是清空的意思
        system("title 双人五子棋");              //  设置CMD窗口标题
        cout << "Copyright (C) XiyuWang 2018 All rights reserved." << endl;
        cout << "双人五子棋小游戏" << endl;
        cout << "小提示:棋盘中b代表黑方(black),w代表白方(white)" << endl;
        cout << "请按任意键开始游戏......";
        _getch();           // 从控制台读取一个字符,但不显示在屏幕上。可以赋值,此函数有返回值
        while (true) {
            place(0);
            if (compute() == 0) {
                system("cls");
                display();
                cout << "黑方胜!" << endl;
                break;
            }
            if (compute() == 2) {
                system("cls");
                display();
                cout << "平局!" << endl;
                break;
            }
            place(1);
            if (compute() == 1) {
                system("cls");
                display();
                cout << "白方胜!" << endl;
                break;
            }
            if (compute() == 2) {
                system("cls");
                display();
                cout << "平局!" << endl;
                break;
            }
        }
        cout << "再来一局?Y/N  ";
        o = _getch();             // 这里_getch()抓取控制台输入,但是控制台不显示
        if (o == 'Y' || o == 'y') goto game_start;
        return 0;
    }
    修改后
  • 相关阅读:
    我对闭包的几点初步认识
    python 字符串的split()函数详解
    使用两个不同类型的数据进行加法计算时,使用异常处理语句捕获由于数据类型错误而出现的异常,发生生成错误。是否继续并运行上次的成功生成?
    自定义一个抽象类,用来计算圆的面积
    接口里不能包括字段,构造函数,析构函数,静态成员或常量等,否则会导致错误
    抽象类与抽象方法的使用
    如何设置修改WPS批注上的用户信息名称
    在双击控件进入到程序代码编辑界面后,没写东西不影响运行,但删除后报错
    电影管理系统修改后,为啥不能识别数据库
    添加现有项到当前项目的几点注意事项
  • 原文地址:https://www.cnblogs.com/maxiaonong/p/13293902.html
Copyright © 2011-2022 走看看