C语言实现三子棋游戏

先直接上代码:

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>         //2.实现三子棋游戏。
#include<Windows.h>       //Sleep() RAND_MAX 的头文件

void menu()                       //打印菜单
{
    printf("****************************\n");
    printf("**** 欢迎来到三子棋游戏 ****\n");
    printf("**** 1、   进入游戏     ****\n");
    printf("**** 0、   退出游戏     ****\n");
    printf("****************************\n");
    printf("请输入:->");
}

void print_chessboard(char coord[][3])    //打印棋盘函数
{        //多维数组在传参时,接收数组的形参最多只能是第一个方括号里没有数字(下标范围)
         //否则就会出错(因为此时编译器不知道你要把传过来的数组的元素划分成几行几列,
         //但是当除第一个方括号的其他方括号都有值时,就可以经过计算知道第一个方括号的值是多少
    int i = 0;
    int index_x = 0;
    int index_y = 0;
    for (i = 1; i <= 153; i++)
    {               
        char out_ch = ' ';
        if ((i % 51 == 20) || (i % 51 == 26) || (i % 51 == 32)  )
        {
            out_ch = coord[index_x][index_y];
            index_x++;
            if (index_x < 3)
            {
                index_x = 0;
                index_y++;
            }
        }
        else if ((i % 17 == 6) || (i % 17 == 12))
        {
            out_ch = '|';
        }
        else if( (i >= 35 && i <= 51 && i != 40 && i != 46) || \
                 (i >= 86 && i <= 102 && i != 91 && i != 97))
        {
            out_ch = '_';
        }
        putchar(out_ch);
        if (i % 17 == 0)                  //每输出 17 个字符换下一行输出
        {
            printf("\n");
        }
    }
}

void winer(char coord[][3], int *flag);     //赢家判断函数的声明

int computer(char coord[][3])                               //电脑下棋
{
    int flag = 0;
    int index_x2 = 0;
    int index_y2 = 0;
    srand((unsigned)time(NULL));
    while (1)
    {
        index_x2 = 2 * rand() / RAND_MAX;                  //产生 0--2 的随机数
        index_y2 = 2 * rand() / RAND_MAX;
        if ((coord[index_x2][index_y2] != '*') && (coord[index_x2][index_y2] != 'o'))
        {                                                 //判断该位置是否已有落子
            coord[index_x2][index_y2] = 'o';
            winer(coord, &flag);
            if (flag == 1)
            {
                return 1;
            }
            return 0;
        }
    }
}

int player(char coord[][3], int index_x1, int index_y1) //玩家下棋
{
    int flag = 0;
    int ret = 0;
    if ((coord[index_x1][index_y1] == '*') || (coord[index_x1][index_y1] == 'o'))
    {                                                      //判断该位置是否已有落子
        printf("此位置已有棋子,请重下!\n");
        return 0;
    }
    else
    {
        coord[index_x1][index_y1] = '*';
        winer(coord, &flag);
        if (flag == 1)
        {
            return 1;
        }
        ret = computer(coord);
        if (ret == 1)
        {
            return 1;
        }
        print_chessboard(coord);       //把打印棋盘放在是因为想在两人都走完一次后再打印当前棋盘状态
    }
    return 0;
}

void winer(char coord[][3],int *flag)           //判断是否产生赢家,赢家是谁
{
    char line_ch[8][4] = { { coord[0][0], coord[1][1], coord[2][2] }, { coord[0][0], coord[0][1], coord[0][2] }, \
                           { coord[0][0], coord[1][0], coord[2][0] }, { coord[0][1], coord[1][1], coord[2][1] }, \
                           { coord[0][2], coord[1][2], coord[2][2] }, { coord[1][0], coord[1][1], coord[1][2] }, \
                           { coord[2][0], coord[2][1], coord[2][2] }, { coord[0][2], coord[1][1], coord[2][0] } };
                           //把所有能赢的情况定义成一个字符串数组
    int i = 0;
    for (i = 0; i < 8; i++)
    {
        if (strcmp(line_ch[i],"***") == 0)   //判断此时玩家已输入的落子能不能组成一个使玩家能赢的字符串
        {
            print_chessboard(coord);         //先打印棋盘,再判断谁胜谁负
            printf("\n恭喜您赢了!\n");
            *flag = 1;                      //玩家赢,使最开始设置的赢的标志位为1,结束此次游戏
            return;
        }
        else if (strcmp(line_ch[i],"ooo") == 0)
        {
            print_chessboard(coord);
            printf("\n很遗憾,您输了!\n");
            *flag = 1;
            return;
        }
        else
        {
            ;
        }
    }
}

int main()
{
    while (1)
    {
        int num = 0;            //决定开始或退出游戏
        int x = 0;
        int y = 0;
        int i = 4;              //一次游戏最多的内层while循环可循环的次数
        int ret = 0;            //是否结束此次游戏的标志位
        int is_play = 0;        //是否再次玩游戏的标志位
        char coordinate[3][3] = { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' };
                                //为了拓展游戏比较方便,可以把行和列定义成宏定义
        menu();                 
        scanf("%d", &num);
        if (num == 0)
        {
            printf("5秒后退出程序!\n");
            Sleep(5000);
            exit(0);
        }
        computer(coordinate);      //因为设计电脑智商低,所以游戏开始前先让电脑落一子
        print_chessboard(coordinate);
        while ((i))                //因为总共有九个位置可以落子,已用一个,还剩八个,每次循环不结束的话会用掉两个
                                   //所以最多循环四次
        {
            printf("请输入 X、Y 的坐标(0--2)来确定你下棋的位置:");   //也可以加一个判断输入是否合法
            scanf("%d %d", &x, &y);
            ret = player(coordinate, x, y);
            if (ret == 1)
            {
                break;
            }
            i--;
        } 
        printf("\n");
        printf("请选择接下来的操作:\n");
        printf("1、 再玩一次游戏    0、退出游戏系统\n");
        scanf("%d", &is_play);
        if(is_play == 0)
        {
            printf("5秒后退出程序!\n");
            Sleep(5000);
            exit(0);
        }
        else
        {
            system("cls");
        }
    }
    system("pause");
    return 0;
}

这里写图片描述

这里写图片描述

程序一共设计了六个函数,一个主函数,五个自定义函数— 菜单打印函数、棋盘打印函数、电脑下棋函数、玩家下棋函数、赢家判断函数。
其中最难设计的就是棋盘打印函数和赢家判断函数。这两个函数需要完成的任务多,计算量大,逻辑设计麻烦。

下面来分析一下几个函数的设计思路:

  1. 菜单打印函数
    这个函数很简单,一看就能明白,这儿就不多说了。
  2. 棋盘打印函数
    首先得构思一下三子棋的棋盘应该是什么样

这里写图片描述

简单点,上图就可以作为三子棋棋盘(其实就是利用 putchar() 函数和 printf() 把显示在屏幕上的字符一个个,一行行打印上去)。设计时可把其分成四部分来看,(1) 短竖杠 ; (2) 短横杠 ; (3) 棋子(用一个二维字符数组来定义每一个棋子,用二维是因为方便输入的 X 和 Y 值与数组下标对应) ; (4) 空格(一开始打印的时候,因为还没有落子,所以把棋子也设计成空格)。 先确定要输入几行几列字符,以确定循环输出的次数,还有确定每个位置该输出的字符,这样就可以依靠循环和判断打印出棋盘了。

3 . 赢家判断函数
在每次落子后都要先进行一次判断,看是否已经产生赢家了。
因为会出现赢家的情况就八种———–
{ coord[0][0], coord[1][1], coord[2][2] }, { coord[0][0], coord[0][1], coord[0][2] },
{ coord[0][0], coord[1][0], coord[2][0] }, { coord[0][1], coord[1][1], coord[2][1] },
{ coord[2][0], coord[2][1], coord[2][2] }, { coord[1][0], coord[1][1], coord[1][2] },
{ coord[2][0], coord[2][1], coord[2][2] }, { coord[0][2], coord[1][1], coord[2][0] }
定义一个字符串数组,里面共有八个字符串,每一个字符串就是上面的一个花括弧里的内容,当某个字符串的内容与 * 或 ooo 相等,那么说明产生赢家了,否则不会产生赢家,那么就用一个循环,遍历字符串数组里的每一个字符串,判断是否会产生赢家。
4. 玩家下棋函数
玩家通过输入 x,y 坐标来确定落子的位置, x,y 对应的就是 定义的棋子二维字符数组的下标,每次先判断输入的 x,y 值对应数组下标的元素是否是 * 或 o ,是的话就说明此处已有落子,得重新输入,不是的话就落下该棋子,接着判断是否产生赢家,是的话就结束此次游戏,不是的话就判断棋盘上是否还有空位置没落子,有的话就轮到电脑继续落子,没有的话就结束此次游戏。
5. 电脑下棋函数
因为电脑是自动落子,所以得为电脑产生一个随机的 棋子二维数组下标值,使电脑随机落子,这个用srand((unsigned)time(NULL)); index_x2 = 2 * rand() / RAND_MAX; index_y2= 2 * rand() / RAND_MAX;来实现把它们放在一个while 死循环里,因为可能产生的两个随机下标那儿已经有棋子了,需要重新产生一次随机下标,当下标值与已落棋子不冲突时,就落下该棋子,接着判断是否产生赢家,是的话,就结束此次游戏,不是的话就判断棋盘上是否还有空位置没落子,有的话就轮到玩家继续落子,没有的话就结束此次游戏。
6. 主函数
在主函数里适当调用以上定义的几个函数,实现正确的逻辑功能。

因为博主技术及思路有限,只能达到这个水平,希望博友们指出错误,让博主得以进步。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
好的,设计三子棋游戏可以分为以下几个步骤: 1. 定义棋盘:通常使用一个三行三列的二维数组来表示棋盘,用数字0表示空位,用数字1表示玩家1下的棋子,用数字2表示玩家2下的棋子。 2. 实现落子功能:用户输入行列坐标,程序判断该位置是否为空位,如果是则将该位置设置为当前玩家下的棋子。 3. 判断胜负:每次玩家下完棋后,程序需要判断是否有一方取得胜利,可以通过遍历棋盘来实现。 4. 实现人机对战:可以使用随机数来模拟电脑的落子,也可以使用一些简单的算法来提高电脑的智能程度。 下面是一个简单的C语言三子棋游戏代码示例,供参考: ``` #include <stdio.h> #include <stdlib.h> #include <time.h> int chessboard[3][3]; // 棋盘 int check_win(int player) // 判断胜负 { int i, j; for (i = 0; i < 3; i++) { if (chessboard[i][0] == player && chessboard[i][1] == player && chessboard[i][2] == player) { return 1; } if (chessboard[0][i] == player && chessboard[1][i] == player && chessboard[2][i] == player) { return 1; } } if (chessboard[0][0] == player && chessboard[1][1] == player && chessboard[2][2] == player) { return 1; } if (chessboard[0][2] == player && chessboard[1][1] == player && chessboard[2][0] == player) { return 1; } return 0; } void print_chessboard() // 打印棋盘 { int i, j; for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) { if (chessboard[i][j] == 0) { printf(" "); } else if (chessboard[i][j] == 1) { printf("X"); } else if (chessboard[i][j] == 2) { printf("O"); } if (j < 2) { printf("|"); } } printf("\n"); if (i < 2) { printf("-+-+-\n"); } } } int main() { int player = 1; // 玩家先手 int row, col; srand((unsigned)time(NULL)); // 初始化随机数生成器 printf("Welcome to the Tic-Tac-Toe game!\n"); printf("Player 1: X\n"); printf("Player 2: O\n"); while (1) { printf("Player %d's turn.\n", player); if (player == 1) { printf("Please input the row and column numbers to place your chess(X).\n"); scanf("%d%d", &row, &col); if (chessboard[row][col] != 0) { printf("This place has been taken, please choose another place.\n"); continue; } chessboard[row][col] = 1; } else { printf("Thinking...\n"); while (1) { row = rand() % 3; col = rand() % 3; if (chessboard[row][col] == 0) { break; } } chessboard[row][col] = 2; } print_chessboard(); if (check_win(player)) { printf("Player %d wins!\n", player); break; } if (player == 1) { player = 2; } else { player = 1; } } return 0; } ``` 注意:以上代码仅作为参考,可能存在一些漏洞和不足之处,需要在实际使用中进行完善。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值