三子棋小游戏(C语言)

简介: 三子棋小游戏(C语言)

简介

三子棋,相信大家很多人小时候都玩过,横竖各画两线,在9个格子里面✔或者×,看谁先连成一线谁就胜利。在这里,我们的对手是电脑。

这个小游戏结合了数组,循环语句两大主要内容进行编写程序。再加上分文件编程,最后就能构成。

大体思路

分文件编程,好处就是程序简洁,分工有序,方便调试。这里,分成三个文件。分别是

game.h:头文件,把各个函数封装在一起,方便调用

game.c:游戏函数的定义

test.c:测试文件,用来实现最终效果


那么最主要的就是这个game.c文件了。思路主要为:初始化,打印棋盘,玩家下棋,电脑下棋,判断输赢(包含判断棋盘为满),这五个函数来写。

初始化以及打印

一般我们都是从主函数入手,首先要给出玩家一个菜单,明白要怎么操作,那么直接就打印出来即可。

void menu()
{
    printf("**********************\n");
    printf("********1.PLAY********\n");
    printf("********0.EXIT********\n");
    printf("**********************\n");
    printf("**********************\n");
}


由于游戏简单,所以我们设定可以多次玩这个小游戏,将游戏决定权交给玩家,那么我们就用do-while语句进行封装再加上switch封装选择即可。

int input = 0;
    do
    {
        menu();
        printf("请选择:");
        scanf("%d", &input);
        switch (input)
        {
        case 1:
            game();
            break;
        case 0:
            printf("已退出游戏。\n");
            break;
        default:
            printf("输入错误,请重新输入。\n");
            break;
        }
    } while (input);


进入游戏我们相先对棋盘进行初始化,初始化用空格字符即可。

void BoardInit(char board[ROW][COL], int row, int col)
{
    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < col; j++)
        {
            board[i][j] = ' ';
        }
    }
}


接下来就是将棋盘打印出来;上面我们说过,只有画出线将它分成9个格子,这样子给玩家才有一种明朗的感觉。三子棋,很明显有三行三列,而分隔线只有2条横竖,所以我们还要进行-1,不必画出多余的线条。利用两个for循环就能打印出一个二维平面。

void BoardPrint(char board[ROW][COL], int row, int col)
{
    for (int i = 0; i < row; i++)
    {
        //打印数据内容和竖列的分隔线
        for (int j = 0; j < col; j++)
        {
            printf(" %c ",board[i][j]);
            if (j < col - 1)
            {
                printf("|");
            }
        }
        //打完记得换行
        printf("\n");
        //打印横列的分隔线
        if (i < row - 1)
        {
            for (int j = 0; j < col; j++)
            {
                printf("---");
                if (j < col - 1)
                {
                    printf("|");
                }
            }
            printf("\n");
        }
    }
}


效果:

玩家和电脑下棋

接下来就是开始下棋了。先从玩家下棋开始,在玩家眼中,下标0对应的是坐标1,所以在输入坐标时,需要对玩家输入值进行-1的操作。在棋盘中,我们要判断玩家输入坐标是否超过范围,不超过范围时,该坐标是否被占领。这些问题想清楚,我们就可以编写代码了。

void PlayerMove(char board[ROW][COL], int row, int col)
{
    int x = 0, y = 0;
    printf("玩家下棋:\n");
    while (1)
    {
        printf("请输入下棋位置坐标,用空格隔开");
        scanf("%d %d", &x, &y);
        //在棋盘范围内
        if (x >= 1 && x <= row && y >= 1 && y <= col)
        {
            if (board[x-1][y-1] == ' ')
            {
                board[x-1][y-1] = '*';
                break;
            }
            else
            {
                printf("当前位置已有,请重新输入。\n");
            }
        }
        else//棋盘范围外
        {
            printf("超出输入范围,请重新输入。\n");
        }
    }
}

电脑下棋,我们要知道怎么让电脑自动下棋,在这里,我们利用随机数来进行随机下棋,只需将随机数进行取模即可。再判断是否为空的。

//随机数种子

srand((unsigned int)time(NULL));

void ComputerMove(char board[ROW][COL], int row, int col)
{
    int x=0, y=0;
    printf("电脑下棋:\n");
    while (1)
    {
    //rand()代表随机数
        x = rand() % row;
        y = rand() % col;
        if (board[x][y] == ' ')
        {
            board[x][y] = '#';
            break;
        }
    }
}


判断是否连成一条线

我们都知道,连成一条线一般分为三种,横,竖,斜。我们只需要统计行或列以及对角线的相同字符个数即可。

char IsWin(char board[ROW][COL], int row, int col)
{
    //行项
    for (int i = 0; i < row; i++)
    {
        //Ni记录人,电脑,空
        char NI = board[i][0];
        //num记录相同的
        int num = 0;
        if (NI != ' ')
        {
            num = 1;
        }
        for (int j = 1; j < col; j++)
        {
            if (NI != ' '&&board[i][j]==NI)
            {
                num++;
            }
            if (num == row)
            {
                return NI;
            }
        }
    }
    //列项
    for (int i = 0; i < col; i++)
    {
        //Ni记录人,机,空
        char NI = board[0][i];
        //num记录相同的
        int num = 0;
        if (NI != ' ')
        {
            num = 1;
        }
        for (int j = 1; j < row; j++)
        {
            if (NI != ' ' && board[j][i] == NI)
            {
                num++;
            }
            if (num == row)
            {
                return NI;
            }
        }
    }
    //正对角线
    char NI1 = board[0][0];
    int num1 = 0;
    if (NI1 != ' ')
    {
        num1 = 1;
    }
    for (int i = 1; i < row; i++)
    {
        if (NI1 != ' ' && board[i][i] == NI1)
        {
            num1++;
        }
        if (num1 == row)
        {
            return NI1;
        }
    }
    //反对角线
    char NI2 = board[0][row - 1];
    int num2 = 0;
    if (NI2 != ' ')
    {
        num2 = 1;
    }
    for (int i = 1,j=1; i < row,j<col; i++,j++)
    {
            if (NI2 != ' ' && board[i][row - 1 - j]==NI2)
            {
                num2++;
            }
            if (num2 == row)
            {
                return NI2;
            }
    }
    //平局
    if (IsFull(board, row, col) == 1)
    {
        return 'Q';
    }
    //继续
    return 'C';
}


在这里,我们根据返回值的形式判断输赢,

当棋盘满时,即为平局。

最后的封装

进入游戏后,我们进入的是game()函数,我们先定义一个二维数组,对它进行初始化,打印,接着就是玩家和电脑下棋,下棋时,我们用循环进行多次下棋,并根据上面的返回值进行判断即可。

在这里,我们用了宏定义定义了行数和列数,

这样做,我们只需修改这两个宏变量的值,就能改变棋盘的大小。


原代码

//test.c
#include"game.h"
void menu()
{
    printf("**********************\n");
    printf("********1.PLAY********\n");
    printf("********0.EXIT********\n");
    printf("**********************\n");
    printf("**********************\n");
}
void game()
{
    char board[ROW][COL] = { 0 };
    //初始化
    BoardInit(board, ROW, COL);
    //打印
    BoardPrint(board, ROW, COL);
    //开始下棋
    char ret = 0;
    while (1)
    {
        //人
        PlayerMove(board, ROW, COL);
        BoardPrint(board, ROW, COL);
        //进行判断输赢
        ret = IsWin(board, ROW, COL);
        //非继续就退出循环
        if (ret != 'C')
        {
            break;
        }
        //电脑
        ComputerMove(board, ROW, COL);
        BoardPrint(board, ROW, COL);
        //判断
        ret = IsWin(board, ROW, COL);
        if (ret != 'C')
        {
            break;
        }
    }
    if (ret == '*')
    {
        printf("你赢了。\n");
    }
    else if (ret == '#')
    {
        printf("电脑赢了。\n");
    }
    else
    {
        printf("平局。\n");
    }
}
int main()
{
    //随机种子
    srand((unsigned int)time(NULL));
    int input = 0;
    do
    {
        menu();
        printf("请选择:");
        scanf("%d", &input);
        switch (input)
        {
        case 1:
            game();
            break;
        case 0:
            printf("已退出游戏。\n");
            break;
        default:
            printf("输入错误,请重新输入。\n");
            break;
        }
    } while (input);
    return 0;
}
//game.h
#pragma once//防止头文件重复包含
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
//行数和列数,可改变
#define ROW 3
#define COL 3
//初始化
void BoardInit(char board[ROW][COL], int row, int col);
//打印棋盘
void BoardPrint(char board[ROW][COL], int row, int col);
//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col);
//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col);
//判断
char IsWin(char board[ROW][COL], int row, int col);
//game.c
#include"game.h"
//初始化
void BoardInit(char board[ROW][COL], int row, int col)
{
    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < col; j++)
        {
            board[i][j] = ' ';
        }
    }
}
//打印
void BoardPrint(char board[ROW][COL], int row, int col)
{
    for (int i = 0; i < row; i++)
    {
        //打印数据内容和竖列的分隔线
        for (int j = 0; j < col; j++)
        {
            printf(" %c ",board[i][j]);
            if (j < col - 1)
            {
                printf("|");
            }
        }
        //打完记得换行
        printf("\n");
        //打印横列的分隔线
        if (i < row - 1)
        {
            for (int j = 0; j < col; j++)
            {
                printf("---");
                if (j < col - 1)
                {
                    printf("|");
                }
            }
            printf("\n");
        }
    }
}
//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col)
{
    int x = 0, y = 0;
    printf("玩家下棋:\n");
    while (1)
    {
        printf("请输入下棋位置坐标,用空格隔开");
        scanf("%d %d", &x, &y);
        //在棋盘范围内
        if (x >= 1 && x <= row && y >= 1 && y <= col)
        {
            if (board[x-1][y-1] == ' ')
            {
                board[x-1][y-1] = '*';
                break;
            }
            else
            {
                printf("当前位置已有,请重新输入。\n");
            }
        }
        else//棋盘范围外
        {
            printf("超出输入范围,请重新输入。\n");
        }
    }
}
//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col)
{
    int x=0, y=0;
    printf("电脑下棋:\n");
    while (1)
    {
        x = rand() % row;
        y = rand() % col;
        if (board[x][y] == ' ')
        {
            board[x][y] = '#';
            break;
        }
    }
}
//判断棋盘是否已经满了
int IsFull(char board[ROW][COL], int row, int col)
{
    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < col; j++)
        {
            if (board[i][j] == ' ')
            {
                return 0;
            }
        }
    }
    return 1;
}
//判断是否赢了
char IsWin(char board[ROW][COL], int row, int col)
{
    //行项
    for (int i = 0; i < row; i++)
    {
        //Ni记录人,机,空
        char NI = board[i][0];
        //num记录相同的
        int num = 0;
        if (NI != ' ')
        {
            num = 1;
        }
        for (int j = 1; j < col; j++)
        {
            if (NI != ' '&&board[i][j]==NI)
            {
                num++;
            }
            if (num == row)
            {
                return NI;
            }
        }
    }
    //列项
    for (int i = 0; i < col; i++)
    {
        //Ni记录人,机,空
        char NI = board[0][i];
        //num记录相同的
        int num = 0;
        if (NI != ' ')
        {
            num = 1;
        }
        for (int j = 1; j < row; j++)
        {
            if (NI != ' ' && board[j][i] == NI)
            {
                num++;
            }
            if (num == row)
            {
                return NI;
            }
        }
    }
    //正对角线
    char NI1 = board[0][0];
    int num1 = 0;
    if (NI1 != ' ')
    {
        num1 = 1;
    }
    for (int i = 1; i < row; i++)
    {
        if (NI1 != ' ' && board[i][i] == NI1)
        {
            num1++;
        }
        if (num1 == row)
        {
            return NI1;
        }
    }
    //反对角线
    char NI2 = board[0][row - 1];
    int num2 = 0;
    if (NI2 != ' ')
    {
        num2 = 1;
    }
    for (int i = 1,j=1; i < row,j<col; i++,j++)
    {
            if (NI2 != ' ' && board[i][row - 1 - j]==NI2)
            {
                num2++;
            }
            if (num2 == row)
            {
                return NI2;
            }
    }
    //平局
    if (IsFull(board, row, col) == 1)
    {
        return 'Q';
    }
    //继续
    return 'C';
}



相关文章
|
6天前
|
C语言
【C语言】猜数字小游戏的一步一步实现2
【C语言】猜数字小游戏的一步一步实现
|
6天前
|
算法 C语言
【C语言】猜数字小游戏的一步一步实现1
【C语言】猜数字小游戏的一步一步实现
|
6天前
|
C语言
C语言之三子棋小游戏
C语言之三子棋小游戏
|
6天前
|
C语言
C语言之实现贪吃蛇小游戏篇(2)
C语言之实现贪吃蛇小游戏篇(2)
27 1
|
6天前
|
存储 小程序 编译器
C语言之三子棋小游戏的应用
C语言之三子棋小游戏的应用
|
6天前
|
算法 编译器 C语言
C语言猜数字小游戏(也包含python实现的用法)
本文基于VS2022、pycharm和前面的知识,写一个凭借分支与循环的小游戏,比如: 写一个猜数字游戏 游戏要求: 电脑自动生成1~100的随机数 玩家猜数字,猜数的过程中,根据猜测数据的大小给出大了或小了的反馈,直到猜对,游戏结束 在pyhton中生成随机数是比较简单的,可以直接导入random的包,直接生成随机数,导致写猜数字小游戏变成了判读语句和循环语句嵌套就能写出来,所以我不做过多的介绍了,可以直接看后面的代码展示,想了解更多的python可看python的基础知识,这里面有我在学习python的过程中写的笔记
35 0
|
6天前
|
C语言
爱上C语言:扫雷小游戏,展开一片功能实现
爱上C语言:扫雷小游戏,展开一片功能实现
爱上C语言:扫雷小游戏,展开一片功能实现
|
6天前
|
人工智能 机器人 测试技术
【C语言】C语言实现猜单词小游戏(源码+报告)【独一无二】
【C语言】C语言实现猜单词小游戏(源码+报告)【独一无二】
|
6天前
|
存储 定位技术 C语言
基于C语言实现扫雷小游戏
本文介绍了使用C语言实现扫雷小游戏的过程。扫雷是一款经典的单机游戏,玩家需要通过点击方格来揭示数字或地雷,最终清除所有非地雷方格。实现过程中,首先定义了游戏所需的数据结构,如游戏地图、玩家信息等。然后,实现了游戏的初始化、渲染、输入处理等核心功能。在游戏逻辑方面,处理了点击事件、数字计算和胜负判断等。通过不断优化和完善,最终完成了基于C语言的扫雷小游戏实现,为玩家提供了一种简单有趣的游戏体验。
29 0
|
6天前
|
机器学习/深度学习 小程序 C语言
C语言初学者:原来我也可以实现扫雷小游戏(简易版)!
C语言初学者:原来我也可以实现扫雷小游戏(简易版)!

相关实验场景

更多