三子棋(详解)

本期带大家一起来学习一下三子棋🌈🌈🌈

前言

相信大家在学习C语言的过程中,有时会感觉到有一些枯燥切乏味,今天就在这里教大家用C语言实现一个简单的小游戏三子棋,这个项目不需要很多的基础,只要学到了数组便可以实现,让我们在学习C语言的过程中可以获得更大的乐趣

游戏逻辑分析

首先,这个游戏是由玩家和电脑进行对局,玩家下棋后再由电脑下,当有任意一行三子连成一条线的时候便游戏结束判断胜利,因此在每一次落子之后便要进行判断胜负,若不分胜负,则平局,平局的判断条件便是当棋盘上的所有格子都有落子,但并没有三个连在一起的棋子。

游戏实现

菜单

首先,在打开一个程序之后,首先映入眼帘的便是程序的主菜单

//菜单界面
void menu()
{
    printf("*********************\n");
    printf("********1.play*******\n");
    printf("********2.exit*******\n");
    printf("*********************\n");
}

设计棋盘

在这个比较基础性的游戏中,没有引用界面库,是通过键盘输入进行游戏,所以我们要用字符来组成一个棋盘,用一个3x3的数组来存放棋子
在这里插入图片描述

//打印棋盘
void playboard(char board[ROW][COL])
{
    int i, j;
    for (i = 0; i < COL; i++)
    {
        for (j = 0; j < ROW; j++)
        {
            printf("  %c  ", board[i][j]);
            if (j != ROW - 1)
                printf("|");
        }
        printf("\n");
        for (j = 0; j < ROW; j++)
        {
            if (i != COL - 1)
                printf("-----");
            if (j != ROW - 1&& i != COL - 1)
                printf("|");
        }
        printf("\n");
    }
}

初始化棋子

在设计棋盘时我们将棋子设置成为了一个3x3的二维数组,在没有任何落子的时候所显示的效果是空白的,所以我们要将一开始的棋子都初始化为空格,下面为初始化棋子的代码实现

//初始化棋子
void IniBoard(char board[COL][ROW])
{
    int i, j;
    for (i = 0; i < COL; i++)
        for (j = 0; j < ROW; j++)
            board[i][j] = ' ';
}

实现落子

在三子棋中我们将’o‘的落子设置为玩家,’x‘设置为电脑落子,在输入想要落子对应的坐标后,便改变对应的变量为所落的棋子,并判断输入的坐标是否符合要求,在界定范围内,也没有下过棋子,以下分别为玩家和电脑落子的代码实现

//玩家下
void playermove(char board[COL][ROW])
{
    int x, y;
    do
    {
        printf("请选择您要下的的坐标(格式:行 列)\n");
        scanf("%d%d", &x, &y);
        if (x > 0 && x <= COL && y > 0 && y <= ROW && board[x-1][y-1] == ' ')
        {
            board[x - 1][y - 1] = 'o';
            break;
        }
        else
            printf("坐标非法,请重新输入\n");
    } while (1);
}
//电脑下
void computermove(char board[COL][ROW])
{
    do
    {
        int x = rand() % 3;
        int y = rand() % 3;
        if (board[x][y] == ' ')
        {
            board[x][y] = 'x';
            break;
        }
    } while (1);
}

判断胜负

在三子棋中每一次落子可能都会决出胜负,为了简化代码提高运行效率,我们以不同的返回值来判断一次落子后胜负,返回’o’则玩家胜利,返回’x’则电脑胜利,返回’D’平局,'C’继续游戏,以下便是判断函数的代码实现。

//判断胜负
char judge(char board[COL][ROW])
{
    int i, j;
    for (i = 0; i < COL; i++)
        if ((board[0][i] == board[1][i] && board[1][i] == board[2][i])|| (board[i][0] == board[i][1] && board[i][1] == board[i][2]))
            return board[1][i];
    if ((board[0][0] == board[1][1] && board[1][1] == board[2][2]) || (board[0][2] == board[1][1] && board[1][1] == board[2][0]))
        return board[1][1];
    for(i=0;i<ROW;i++)
        for (j = 0; j < COL; j++)
        {
            if (board[i][j] == ' ')
                return 'C';
        }
    return 'D';
}

游戏封装

#include"game.h"
int main()
{
    srand((unsigned)time(NULL));
    int input;
    do
    {
        menu();
        scanf("%d", &input);
        switch (input)
        {
        case PLAY:game(); break;
        case EXIT:break;
        default:
            printf("非法输入,请重新输入\n");
            Sleep(1000);
            system("cls");
            break;
        }
    } while (input != 2);
    return 0;
}

源代码展示

game.c

#include"game.h"
//游戏菜单
void menu()
{
    printf("*********************\n");
    printf("********1.play*******\n");
    printf("********2.exit*******\n");
    printf("*********************\n");
}
//游戏
void game()
{
    char ret;
    system("cls");
    char board[COL][ROW];
    IniBoard(board);
    playboard(board);
    do 
    {
        playermove(board);
        playboard(board);
        ret = judge(board);
        if (ret == 'o')
        {
            printf("玩家胜利\n");
            system("cls");
            break;
        }
        else if(ret=='D')
        {
            printf("平局\n");
            break;
        }
        system("cls");
        computermove(board);
        playboard(board);
        ret = judge(board);
        if (ret == 'x')
        {
            printf("电脑胜利\n");
            system("cls");
            break;
        }
        else if (ret == 'D')
        {
            printf("平局\n");
            break;
        }
    } while (1);
 
}
//初始化棋盘
void IniBoard(char board[COL][ROW])
{
    int i, j;
    for (i = 0; i < COL; i++)
        for (j = 0; j < ROW; j++)
            board[i][j] = ' ';
}
//打印棋盘
//     |     |
//-----|-----|-----
//     |     |
//-----|-----|-----
//     |     |     
void playboard(char board[ROW][COL])
{
    int i, j;
    for (i = 0; i < COL; i++)
    {
        for (j = 0; j < ROW; j++)
        {
            printf("  %c  ", board[i][j]);
            if (j != ROW - 1)
                printf("|");
        }
        printf("\n");
        for (j = 0; j < ROW; j++)
        {
            if (i != COL - 1)
                printf("-----");
            if (j != ROW - 1&& i != COL - 1)
                printf("|");
        }
        printf("\n");
    }
}
//玩家下
void playermove(char board[COL][ROW])
{
    int x, y;
    do
    {
        printf("请选择您要下的的坐标(格式:行 列)\n");
        scanf("%d%d", &x, &y);
        if (x > 0 && x <= COL && y > 0 && y <= ROW && board[x-1][y-1] == ' ')
        {
            board[x - 1][y - 1] = 'o';
            break;
        }
        else
            printf("坐标非法,请重新输入\n");
    } while (1);
}
//电脑下
void computermove(char board[COL][ROW])
{
    do
    {
        int x = rand() % 3;
        int y = rand() % 3;
        if (board[x][y] == ' ')
        {
            board[x][y] = 'x';
            break;
        }
    } while (1);
}
//判断胜负
char judge(char board[COL][ROW])
{
    int i, j;
    for (i = 0; i < COL; i++)
        if ((board[0][i] == board[1][i] && board[1][i] == board[2][i])|| (board[i][0] == board[i][1] && board[i][1] == board[i][2]))
            return board[1][i];
    if ((board[0][0] == board[1][1] && board[1][1] == board[2][2]) || (board[0][2] == board[1][1] && board[1][1] == board[2][0]))
        return board[1][1];
    for(i=0;i<ROW;i++)
        for (j = 0; j < COL; j++)
        {
            if (board[i][j] == ' ')
                return 'C';
        }
    return 'D';
}

test.c

#include"game.h"
int main()
{
    srand((unsigned)time(NULL));
    int input;
    do
    {
        menu();
        scanf("%d", &input);
        switch (input)
        {
        case PLAY:game(); break;
        case EXIT:break;
        default:
            printf("非法输入,请重新输入\n");
            Sleep(1000);
            system("cls");
            break;
        }
    } while (input != 2);
    return 0;
}

game.h

#include<stdio.h>
#include<Windows.h>
#include<time.h>
#define ROW 3
#define COL 3
//定义菜单枚举变量
enum menu
{
    PLAY = 1,
    EXIT
};
void menu();
void game();
void IniBoard(char* board);
void playboard(char* board);
void playermove(char board[ROW][COL]);
void computermove(char board[ROW][COL]);
char judge(char board[COL][ROW]);

感谢与交流

🌹🌹🌹如果大家通过本篇博客收获了,对结构体及枚举,特别是结构体内存对齐和位段在VS当中的存储有了新的认知,那么希望支持一下哦如果还有不明白的,疑惑的话,或者什么比较好的建议的话,可以发到评论区,
我们一起解决,共同进步 ❗️❗️❗️
最后谢谢大家❗️❗️❗️💯💯💯
在这里插入图片描述

评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值