C 语言实现的井字棋(三字棋)游戏代码

目录

 C 语言实现的井字棋游戏代码

一.引言

二.代码功能概述

三.主函数代码(sanziqi.c)

1. 头文件包含

2. game 函数

3. menu 函数

4. main 函数

四.头文件代码声明函数(game.h)

1.代码功能概述

2.代码详细分析

1. 头文件包含

2. 符号定义

3. 函数声明

五.核心模块实现具体游戏内容(game.c)

1.代码整体架构与功能概述

2.代码详细解析

棋盘初始化函数 noboard

棋盘显示函数 inboard

玩家下棋函数 player

电脑下棋函数 computermove

棋盘是否已满检测函数 FULL

棋局输赢判断函数 win

3.电脑下棋策略优化

六.总结


 C 语言实现的井字棋游戏代码

一.引言

在编程学习的道路上,通过实践项目来巩固知识是一种极为有效的方式。井字棋游戏,作为一个经典且简单的项目,蕴含了诸多编程概念和技巧。本文将用 C 语言编写的井字棋游戏代码。

二.代码功能概述

这段 C 语言代码实现了一个简单的井字棋游戏,玩家可以与电脑进行对战。玩家通过菜单选择开始游戏或退出游戏,在游戏过程中,玩家和电脑轮流下棋,程序会实时判断输赢情况,直至游戏结束。

三.主函数代码(sanziqi.c)

1. 头文件包含
#include "game.h"

这行代码包含了自定义的头文件 game.h,该头文件中定义了游戏所需的常量、函数声明等内容。

2. game 函数

void game() {
    char ret;
    //创建棋盘
    char board[ROW][COL];
    //初始化
    noboard(board, ROW, COL);
    //打印棋盘
    inboard(board, ROW, COL);
    while (1) {
        //玩家下棋
        player(board, ROW, COL);
        inboard(board, ROW, COL);
        //判断输赢
        ret = win(board, ROW, COL);
        if (ret != 'c') {
            break;
        }
        //电脑下棋
        computermove(board, ROW, COL);
        inboard(board, ROW, COL);
        ret = win(board, ROW, COL);
        if (ret != 'c') {
            break;
        }
    }
    if (ret == '*') {
        printf("玩家赢\n");
    }
    else if (ret == '#') {
        printf("电脑赢\n");
    }
    else if (ret == 'q') {
        printf("平局\n");
    }
    inboard(board, ROW, COL);
}

  • 棋盘创建与初始化:创建了一个二维字符数组 board 作为棋盘,调用 noboard 函数对棋盘进行初始化。
  • 游戏循环:使用 while (1) 创建一个无限循环,在循环中玩家和电脑轮流下棋。每次下棋后,调用 inboard 函数打印当前棋盘状态,并调用 win 函数判断输赢情况。如果 win 函数返回值不是 'c'(表示游戏继续),则跳出循环。
  • 结果判断:根据 win 函数的返回值判断游戏结果,分别输出玩家赢、电脑赢或平局的信息,并再次打印最终的棋盘状态。

3. menu 函数

void menu() {
    printf("******************************\n");
    printf("**********1.play**************\n");
    printf("**********0.exit**************\n");
    printf("******************************\n");
}

该函数用于打印游戏菜单,向用户展示可选择的操作:开始游戏(输入 1)或退出游戏(输入 0)。

4. main 函数

int main() {
    int input = 0;
    srand((unsigned int)time(NULL));
    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;
}

2. 符号定义
#define ROW 3
#define COL 3

这里使用 #define 预处理指令定义了两个符号常量 ROW 和 COL,它们的值均为 3。在井字棋游戏里,这两个常量分别代表棋盘的行数和列数。采用符号常量的好处在于,若后续需要对棋盘大小进行调整,只需修改这两个定义,而无需在代码的各个地方逐个修改具体的数值,提高了代码的可维护性和可扩展性。

3. 函数声明
//初始化
void noboard(char board[ROW][COL], int  row, int col);
//打印棋盘
void inboard(char board[ROW][COL],int  row,int  col);
//玩家走
void player(char board[ROW][COL],int row, int col);
//电脑走
void computermove(char board[ROW][COL], int row, int col);
//判断输赢
char win(char board[ROW][COL], int row, int col);

  • 随机数种子设置:使用 srand((unsigned int)time(NULL)) 设置随机数种子,电脑下棋的逻辑中会用到随机数。
  • 菜单循环:使用 do-while 循环不断显示菜单,根据用户输入的数字进行相应操作。输入 1 则调用 game 函数开始游戏,输入 0 则退出游戏,输入其他数字则提示输入错误并要求重新选择。

    四.头文件代码声明函数(game.h)

    1.代码功能概述

    这段代码是井字棋游戏的头文件内容,其主要功能为包含必要的标准库头文件、定义游戏所需的符号常量,以及声明游戏实现过程中会用到的各类函数。

    2.代码详细分析

    1. 头文件包含
    #include <stdio.h>
    #include <time.h>
    #include <stdlib.h>
    

  • #include <stdio.h>:此头文件包含了标准输入输出库的相关内容,为程序提供了诸如 printf 和 scanf 等基础的输入输出函数,在游戏中可用于显示信息和获取用户输入。
  • #include <time.h>:该头文件包含了与时间相关的函数和类型定义,在游戏里会被用于生成随机数时作为种子,以确保电脑的落子具有随机性。
  • #include <stdlib.h>:此头文件涵盖了标准库的多种功能,例如内存分配、随机数生成等。在井字棋游戏中,主要用于生成随机数,为电脑的决策提供支持。
  • void noboard(char board[ROW][COL], int row, int col);:该函数用于对棋盘进行初始化操作。它接收一个二维字符数组 board 作为棋盘,以及 row 和 col 表示棋盘的行数和列数。函数的返回值类型为 void,意味着它不返回任何值。
  • void inboard(char board[ROW][COL], int row, int col);:此函数的作用是将当前棋盘的状态打印输出,方便玩家查看。同样接收棋盘数组和行数、列数作为参数,返回值类型为 void
  • void player(char board[ROW][COL], int row, int col);:该函数处理玩家的落子操作。在游戏过程中,它会提示玩家输入落子的位置,并将玩家的选择反映在棋盘上。
  • void computermove(char board[ROW][COL], int row, int col);:该函数负责电脑的落子决策。借助随机数或特定算法,电脑会在合适的位置落子。
  • char win(char board[ROW][COL], int row, int col);:该函数用于判断当前游戏的输赢状态。它会检查棋盘上是否有玩家或电脑达成获胜条件,或者是否出现平局的情况。函数返回一个字符,用于表示不同的游戏结果,如玩家赢、电脑赢、平局或游戏继续等。

五.核心模块实现具体游戏内容(game.c)

1.代码整体架构与功能概述

这段代码围绕井字棋游戏的核心功能展开,涵盖了棋盘初始化、棋盘显示、玩家与电脑的下棋操作、棋局输赢判断以及棋盘是否已满的检测等关键部分。通过多个自定义函数的协同工作,构建了一个完整的井字棋游戏交互逻辑。

2.代码详细解析

棋盘初始化函数 noboard
void noboard(char board[ROW][COL], int row, int col) {
    int i, j;
    for (i = 0; i < row; i++) {
        for (j = 0; j < col; j++)
            board[i][j] = ' ';
    }
}

该函数的作用是将棋盘数组中的每个元素初始化为空格字符 ' '。通过两层嵌套的 for 循环遍历二维数组 board,将每一个位置的字符都设置为空格,为游戏的开始做好准备。这样的初始化操作确保了棋盘在初始状态下没有任何棋子,干净整洁,等待玩家和电脑的操作。

棋盘显示函数 inboard
void inboard(char board[ROW][COL], int row, int col) {
    int i = 0;
    for (i = 0; i < row; i++) {
        int j = 0;
        for (j = 0; j < col; j++) {
            printf(" %c ", board[i][j]);
            if (j < col - 1) {
                printf("|");
            }
        }
        printf("\n");
        if (i < row - 1) {
            int j = 0;
            for (j = 0; j < col; j++) {
                printf("---");
                if (j < col - 1) {
                    printf("|");
                }
            }
            printf("\n");
        }
    }
}

这个函数负责将当前棋盘的状态以可视化的形式输出到控制台。同样使用两层嵌套的 for 循环,外层循环控制行数,内层循环控制列数。在每一行中,依次输出每个格子中的字符,并在相邻格子之间添加分隔符 |。每一行输出完毕后换行,并且在除了最后一行的每一行下方,输出由 --- 和 | 组成的分隔线,以增强棋盘的视觉效果。这样的显示方式能够清晰地呈现棋盘的布局和棋子的分布,方便玩家了解游戏进展。

玩家下棋函数 player
void player(char board[ROW][COL], int row, int col) {
    int x, y;
    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");
        }
    }
}

该函数处理玩家的下棋操作。首先提示玩家输入下棋的坐标,然后进入一个无限循环,直到玩家输入合法且未被占用的坐标为止。在循环内部,对玩家输入的坐标进行合法性检查,确保其在棋盘的有效范围内。接着检查该坐标对应的棋盘位置是否为空,如果为空,则将该位置设置为玩家的棋子 '*',并跳出循环。如果坐标不合法或已被占用,则提示玩家重新输入,保证了游戏操作的准确性和规范性。

电脑下棋函数 computermove
void computermove(char board[ROW][COL], int row, int col) {
    printf("电脑走:>\n");
    while (1) {
        int x = rand() % row;
        int y = rand() % col;
        if (board[x][y] == ' ') {
            board[x][y] = '#';
            break;
        }
    }
}

此函数实现了电脑的下棋逻辑。电脑通过调用 rand 函数生成随机数来确定下棋的坐标。在一个无限循环中,不断生成随机的行和列坐标,然后检查该坐标对应的棋盘位置是否为空。如果为空,则将该位置设置为电脑的棋子 '#',并跳出循环。这种随机下棋的方式虽然简单,但能在一定程度上模拟电脑的决策过程,为玩家提供对手。

棋盘是否已满检测函数 FULL
int FULL(char board[ROW][COL], int row, int col) {
    int i, j;
    for (i = 0; i < row; i++) {
        for (j = 0; j < col; j++) {
            if (board[i][j] == ' ')
                return 0;
        }
    }
    return 1;
}

这个函数用于检测棋盘是否已满。通过两层嵌套的 for 循环遍历整个棋盘数组,检查每一个位置是否为空字符 ' '。如果发现有任何一个位置为空,则立即返回 0,表示棋盘未满;如果遍历完整个棋盘都没有发现空位置,则返回 1,表示棋盘已满,此时棋局可能以平局结束。

棋局输赢判断函数 win
char win(char board[ROW][COL], int row, int col) {
    int i, j;
    //三行
    for (i = 0; i < row; i++) {
        if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ') {
            return board[i][1];
        }
    }
    //三列
    for (j = 0; j < col; j++) {
        if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] != ' ') {
            return board[1][j];
        }
    }
    //对角线
    if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ') {
        return board[1][1];
    }
    if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ') {
        return board[1][1];
    }
    //检测是否填满
    //满了返回一不满返回0
    int ret = FULL(board, row, col);
    if (ret == 1) {
        return 'q';
    }
    return 'c';
}

该函数是整个游戏逻辑的核心之一,用于判断棋局的输赢状态。首先通过三层检查来判断是否有玩家或电脑获胜:

检查行:遍历每一行,检查该行的三个棋子是否相同且不为空,如果满足条件,则返回该行的棋子字符,表示对应的玩家或电脑获胜。

检查列:类似地,遍历每一列,检查该列的三个棋子是否相同且不为空,若满足则返回该列的棋子字符。

检查对角线:分别检查两条对角线的棋子是否相同且不为空,若满足则返回对角线上的棋子字符。
如果没有检测到获胜情况,则调用 FULL 函数检查棋盘是否已满。如果棋盘已满,则返回 'q' 表示平局;否则返回 'c' 表示游戏继续进行。

3.电脑下棋策略优化

当前电脑的下棋策略仅仅是随机选择一个空位置落子,这种策略过于简单,缺乏智能性。可以实现更复杂的电脑下棋策略,例如优先选择能够获胜的位置、阻止玩家获胜的位置,或者采用更高级的博弈算法,如极小极大算法,来提升电脑的下棋水平,增加游戏的挑战性。

    六.总结

    通过对这段 C 语言井字棋游戏代码的分析,我们了解了游戏的基本实现思路和结构。这个项目不仅让我们熟悉了 C 语言的基本语法和控制结构,还涉及到了数组、函数调用、循环和条件判断等重要编程概念。希望本文能帮助你更好地理解和掌握 C 语言编程以及游戏开发的基本方法。

    感谢大家观看

    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值