简单的五子棋小游戏

本文介绍了如何使用C++编程语言实现一个简单的控制台五子棋游戏,包括数据结构的设计(二维数组表示棋盘)、函数设计(如初始化、落子、胜负判断等),以及游戏的整体逻辑和菜单设计。
摘要由CSDN通过智能技术生成

前言:

这是一个简单的控制台五子棋小游戏,我目前的情况是刚学完C,C++尚未入门,在下面的代码中虽然用的是C++,但我的思考方式主要是C,所以新手不必害怕,耐心看完很简单的(●ˇ∀ˇ●)

数据及函数设计:

一、数据设计:

将二维数组作为棋盘,规定数组内数据为0表示空,1表示黑,2表示白

int map[19][19];

利用flag判断当前回合轮到谁落子

int flag;

// 表示当前回合数  偶数表示黑棋落子  奇数表示白棋落子

// 如: flag = 20 表示当前是第[20]次落子  由黑方落子

二、函数设计:(按照功能可以分为功能函数和菜单函数)

功能函数控制游戏的运行,菜单函数主要作用是刷新游戏界面和显示游戏结果。

1. 初始化游戏数据(棋盘重置)

        将棋盘的值初始化为0

        当前回合设为黑棋(flag设为0)

void init();
2. 胜负判断    

    根据传入的坐标(map对应位置)和flag值 判断落点后是否获胜

    坐标(x,y): 依次先输入横坐标,再输入纵坐标

    通过返回值确定游戏的结果(每次落子完成都要进行检查)

        0表示没有获胜

        1表示黑子胜利

        2表示白子胜利

int isWin(int x, int y);
3. 落子/走子

    在指定位置落子

        如果map[x][y]是空地 则修改map[x][y]的值,否则不操作

        x: 当前回合落子的x坐标

        y: 当前回合落子的y坐标

    返回值:

        0表示落子失败 (棋盘已经有子)

        1表示落子成功

int playerMove(int x, int y);
4. 主菜单(提供初始选项)

    功能: 展示选项, 玩家可以在这里选择进入游戏, 进入设置或退出游戏

        进入游戏: 调用游戏界面函数gameView();

        进入设置: 敬请期待...

        退出游戏: 调用exit(0);

void menuView();
5. 游戏界面(显示棋盘)

    功能: 根据map数组 打印游戏棋盘

void gameView_ShowMap();
6. 显示结果

    功能: 根据flag的值  打印游戏胜利界面  用户可以按任意键回到主菜单

void winView();
7. 游戏的整体逻辑(确保各函数按照一定规则被调用)

    功能: 游戏界面整合

        初始化游戏数据(调用函数init())

        while(1){

            打印游戏界面(调用函数gameView_ShowMap())

            接收玩家坐标输入

            落子(调用落子函数playerMove())

                (如果落子失败 重新开始循环)

            判断游戏是否胜利(调用胜利判断函数isWin())

                (如果游戏胜利 调用胜利界面函数 然后结束当前界面)

            切换玩家(修改flag值)

        }

void gameView();

当然,游戏的运行逻辑也可以放在main函数中执行,这里为了方便就将其声明为一个单独的函数。

int main()

{

    menuView();

    return 0;

}

最终的代码:
 

下面的代码中添加了详细的注释,大家可以对照着阅读,应该比较容易理解(●ˇ∀ˇ●)

当然,如果对下面的代码存在什么问题的话也是可以在评论区提问的哦!

#include <iostream>

using namespace std;

int map[19][19];
int flag;

void init();
int isWin(int x, int y);
int playerMove(int x, int y);

void menuView();
void gameView_ShowMap();
void winView();
void gameView();

int main()
{
    menuView();
    return 0;
}

void init() {
    //将棋盘的值初始化为0
    // 五子棋棋盘大小为19x19
    for (int i = 0; i < 19; i++) {
        for (int j = 0; j < 19; j++) {
            map[i][j] = 0;
        }
    }

    //设置当前回合为黑棋
    flag = 0;
}

int isWin(int x, int y) {
    // 五子棋的胜利条件是:先在棋盘上形成五个相同颜色的棋子连成
    // 一条线(横、竖、斜线皆可)的一方获胜
    // ******************************************************************** 1. 横线(-)检查
    // 变量count用来计数,count=5时则分出胜负
    int count_1 = 1;

    // 先看横线(y固定)
    // 确定横坐标范围(x-4,x+4)
    int left = x - 4;
    int right = x + 4;

    // 横坐标满足x - 4 >= 0, x + 4 <= 18
    // 超出范围则按照边界计算
    if (left < 0) left = 0;
    if (right > 15) right = 18;

    //往左数
    int i = x - 1;
    while (map[x][y] == map[i][y] && i >= left) {
        count_1++;
        i--;
    }
    //往右数
    int j = x + 1;
    while (map[x][y] == map[j][y] && j <= right) {
        count_1++;
        j++;
    }

    // 若第一种情况已经达到要求,则返回map[x][y]的值,得出结论
    // 否则判断第二种情况
    if (count_1 == 5) {
        return map[x][y];
    }
    else if (count_1 != 5) {
        // ******************************************************************** 2. 纵线(|)检查
        // 变量count用来计数,count=5时则分出胜负
        int count_2 = 1;

        // 再看纵线(x固定)
        // 确定纵坐标范围(y-4,y+4)
        int up = y - 4;
        int below = y + 4;

        // 纵坐标满足y - 4 >= 0, y + 4 <= 18
        // 超出范围则按照边界计算
        if (up < 0) up = 0;
        if (below > 19) below = 18;

        //往上数
        int i = y - 1;
        while (map[x][y] == map[x][i] && i >= up) {
            count_2++;
            i--;
        }
        //往下数
        int j = y + 1;
        while (map[x][y] == map[x][j] && j <= below) {
            count_2++;
            j++;
        }

        // 若第二种情况已经达到要求,则返回map[x][y]的值,得出结论
        // 否则判断第三种情况
        if (count_2 == 5) {
            return map[x][y];
        }
        else if (count_2 != 5) {
            // ******************************************************************** 3. 正斜线(\)检查
            // 变量count用来计数,count=5时则分出胜负
            int count_3 = 1;

            // 确定左上和右下坐标范围
            int left_up_x = x - 4;
            int left_up_y = y - 4;
            int right_below_x = x + 4;
            int right_below_y = y + 4;

            // 横坐标满足x - 4 >= 0, x + 4 <= 18
            // 超出范围则按照边界计算
            // 纵坐标满足y - 4 >= 0, y + 4 <= 18
            // 超出范围则按照边界计算
            if (left_up_x < 0) left_up_x = 0;
            if (right_below_x > 18) right_below_x = 18;
            if (left_up_y < 0) left_up_y = 0;
            if (right_below_y > 18) right_below_y = 18;

            //往左上数
            int i_x = x - 1;
            int i_y = y - 1;
            while (map[x][y] == map[i_x][i_y] && i_x >= left_up_x && i_y >= left_up_y) {
                count_3++;
                i_x--;
                i_y--;
            }
            //往右下数
            int j_x = x + 1;
            int j_y = y + 1;
            while (map[x][y] == map[j_x][j_y] && j_x <= right_below_x && j_y <= right_below_y) {
                count_3++;
                j_x++;
                j_y++;
            }

            // 若第三种情况已经达到要求,则返回map[x][y]的值,得出结论
            // 否则判断第三种情况
            if (count_3 == 5) {
                return map[x][y];
            }
            else if (count_3 != 5) {
                // ******************************************************************** 4. 反斜线(/)检查
                // 变量count用来计数,count=5时则分出胜负
                int count_4 = 1;

                // 确定左上和右下坐标范围
                int left_below_x = x - 4;
                int left_below_y = y + 4;
                int right_up_x = x + 4;
                int right_up_y = y - 4;

                // 横坐标满足x - 4 >= 0, x + 4 <= 18
                // 超出范围则按照边界计算
                // 纵坐标满足y - 4 >= 0, y + 4 <= 18
                // 超出范围则按照边界计算
                if (left_below_x < 0) left_below_x = 0;
                if (right_up_x > 18) right_up_x = 18;
                if (left_below_y > 18) left_below_y = 18;
                if (right_up_y < 0) right_up_y = 0;

                //往右上数
                int i_x = x + 1;
                int i_y = y - 1;
                while (map[x][y] == map[i_x][i_y] && i_x <= right_up_x && i_y >= right_up_y) {
                    count_4++;
                    i_x++;
                    i_y--;
                }
                //往左下数
                int j_x = x - 1;
                int j_y = y + 1;
                while (map[x][y] == map[j_x][j_y] && j_x >= left_below_x && j_y <= left_below_y) {
                    count_4++;
                    j_x--;
                    j_y++;
                }

                // 若第四种情况已经达到要求,则返回map[x][y]的值,得出结论
                // 否则没有胜利
                if (count_4 == 5) {
                    return map[x][y];
                }
                else {
                    // **************************************************************** 5. 没有获胜
                    return 0;
                }
            }
        }
    }

}

int playerMove(int x, int y) {
    // 如果(x, y)位置为空,则修改map[x][y]的值,并返回1
    // 否则落子失败,返回0
    if (map[x][y] == 0) {
        map[x][y] = flag%2 + 1;
        return 1;
    }
    else {
        return 0;
    }
}

void menuView() {
    cout << "*************** >菜单< **************" << endl;
    cout << "************ 1. 进入游戏 ************" << endl;
    cout << "************ 2. 进入设置 ************" << endl;
    cout << "************ 3. 退出游戏 ************" << endl;
    cout << "请选择:";

    // 玩家进行选择
    int choice;
    cin >> choice;
    // 检查输入的有效性
    while (choice <= 0 || choice > 3 || cin.fail()) {
        cout << "无效输入,请重新选择:";
        cin.clear(); // 清除错误标志
        cin.ignore(numeric_limits<streamsize>::max(), '\n'); // 忽略之前输入的内容
        cin >> choice;
    }

    // 当输入1,2,3时,调用相关的函数或打印相关的文字
    // 当输入不为1,2,3时,则要求重新输入一个有效值
    if (choice == 1) gameView();
    else if (choice == 2) cout << "敬请期待..." << endl;
    else if (choice == 3) exit(0);
    else {
        cout << "选择无效,请重新选择(1,2,3)" << endl << endl;
        menuView();
    }
}

void gameView_ShowMap() {
    //这是一个19x19的棋盘,共计361个可下棋的位置,也就是打印个225
    for (int i = 0; i <= 18; i++) {
        for (int j = 0; j <= 18; j++) {
            cout << map[i][j] << " ";
        }
        cout << endl;
    }
}

void winView() {
    system("clear || cls");  // 清除画面
    // 打印胜利游戏界面
    gameView_ShowMap();
    //flag 为偶数,表示黑棋落子后胜利
    // 否则白棋胜利
    if (flag % 2 == 0) {
        cout << "********** 黑棋胜利! *********" << endl;
    }
    else {
        cout << "********** 白棋胜利! *********" << endl;
    }
    printf("点击任意按钮返回主菜单\n");
    // 判断是否有键盘输入
    // cin.ignore()的作用在于清除输入缓冲区中的剩余字符,包括换行符,以确保下一个输入操作不受影响
    // 否则,当用户输入(ENTER)时会立即结束程序
    cin.ignore();  // 忽略之前的输入

    cin.get();     // 获取一个字符
    // 调用 menuView() 返回主菜单
    menuView();
}

void gameView() {
    //初始化游戏数据
    init();
    while (1) {
        // 打印游戏界面
        gameView_ShowMap();

        cout << endl;
        if (flag % 2 == 0) {
            cout << "-->黑子回合:" << endl;
        }
        else
            cout << "-->白子回合:" << endl;
        // 接收玩家坐标输入, 坐标(i,j)
        int i, j;
        cout << "            输入横坐标x:";
        cin >> i;
        // 检查横坐标的有效性
        while (i < 0 || i >= 18 || cin.fail()) {
            cout << " 无效输入,请重新输入x:";
            cin.clear(); // 清除错误标志
            cin.ignore(numeric_limits<streamsize>::max(), '\n'); // 忽略之前输入的内容
            cin >> i;
        }
        cout << "            输入纵坐标y:";
        cin >> j;
        // 检查纵坐标的有效性
        while (j < 0 || j >= 18 || cin.fail()) {
            cout << " 无效输入,请重新输入y:";
            cin.clear(); // 清除错误标志
            cin.ignore(numeric_limits<streamsize>::max(), '\n'); // 忽略之前输入的内容
            cin >> j;
        }

        // 落子, 传入坐标(i,j)
        // 利用playerMove(i, j)的返回值判断是否需要重新落子
        // 1:成功
        // 0: 失败
        int control = playerMove(i, j);
        while (control == 0) {
            cout << "已有落子, 请重新输入。" << endl;

            // 接收玩家坐标输入, 坐标(i,j)
            int i, j;
            cout << "            输入横坐标x:";
            cin >> i;
            // 检查横坐标的有效性
            while (i < 0 || i >= 18 || cin.fail()) {
                cout << " 无效输入,请重新输入x:";
                cin.clear(); // 清除错误标志
                cin.ignore(numeric_limits<streamsize>::max(), '\n'); // 忽略之前输入的内容
                cin >> i;
            }
            cout << "            输入纵坐标y:";
            cin >> j;
            // 检查纵坐标的有效性
            while (j < 0 || j >= 18 || cin.fail()) {
                cout << " 无效输入,请重新输入y:";
                cin.clear(); // 清除错误标志
                cin.ignore(numeric_limits<streamsize>::max(), '\n'); // 忽略之前输入的内容
                cin >> j;
            }
            control = playerMove(i, j);
        }

        // 判断玩家是否胜利, 利用value接受返回值,用于后续判断
        int value = isWin(i, j);

        // 游戏胜利时value = 1或2,此时调用胜利界面函数,然后结束当前界面
        if (value) {
            winView();
            break;
        }

        // 切换玩家
        flag += 1;
    }
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值