【C语言步行梯】C语言实现三子棋游戏(含详细分析)

在这里插入图片描述

🎯每日努力一点点,技术进步看得见
🏠专栏介绍:【C语言步行梯】专栏用于介绍C语言相关内容,每篇文章将通过图片+代码片段+网络相关题目的方式编写,欢迎订阅~~

文章目录

  • 需求分析
  • 具体实现
    • 主函数体
    • 菜单实现
    • 游戏实现
      • 棋盘初始化
      • 显示棋盘
      • 玩家下棋
      • 电脑下棋
      • 判断棋盘是否已满
      • 判断输赢
      • 游戏函数主体
    • 完整代码
    • 分文件编写


需求分析

上课摸鱼的时候,我们可以画个九宫格,在里面画上圆圈,或者叉。现在,我们通过C语言实现这个三子棋游戏,实现用户与电脑下棋。
在这里插入图片描述

具体实现

主函数体

在主函数体内,我们需要调用一个menu函数,用它提醒用户:输入1开始游戏,输入0退出游戏。接收用户输入后,通过switch语句,执行game()函数或者退出游戏。menu和game函数将在下文中讲解。

int main()
{int input = 0;do{menu();printf("请输入您的选择>");scanf("%d", &input);switch(input){case 1:game();//游戏具体实现函数break;case 0:printf("游戏结束\n");break;default:printf("输入有误,请重新输入\n");}}while(input);return 0;
}

菜单实现

首先,我们需要一个菜单,提示用户:输入1可以开始游戏,输入0会退出游戏。我通过封装一个menu函数实现↓↓↓

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

游戏实现

棋盘初始化

我们通过一个char board[3][3]来存储棋盘。如果board[i][j]为空格,表示该位置还没有下棋;如果board[i][j]存储’*‘(星号),表示该位置用户已经下棋;如果board[i][j]存储‘#’(井号),表示该位置电脑已经下棋。
在这里插入图片描述
但在开始游戏前,我们需要将棋盘数组每个元素都初始化空格。↓↓↓

void initBoard(char board[ROW][COL], int rows, int cols)
{for(int i = 0; i < rows; i++){for(int j = 0; j < cols; j++){board[i][j] = ' ';}}
}

显示棋盘

在游戏过程中,玩家或者电脑下完棋后,需要显示棋盘。用户才能知道当前棋盘的落子情况。

void displayBoard(char board[ROW][COL], int rows, int cols)
{for(int i = 0; i < rows; i++){for(int j = 0; j < cols; j++){printf(" %c ", board[i][j]);if(j != cols - 1)printf("|");elseprintf("\n");}if(i != rows - 1){for(int j = 0; j < cols; j++){printf("---");if(j != cols - 1)printf("|");elseprintf("\n");}}}
}

上方打印棋盘效果如下图所示。
在这里插入图片描述

玩家下棋

提示玩家输入下棋的坐标,接收到坐标后,我们需要判断该坐标是否为空格(表示还没有棋子),如果是空格,则下棋成功;如果不是空格,则下棋失败。

void playerAddChess(char board[ROW][COL], int rows, int cols)
{printf("玩家下棋\n");displayBoard(board, rows, cols);int x = 0;int y = 0;while (1){printf("请输入下棋坐标>");scanf("%d %d", &x, &y);if (x > rows || x <= 0 || y > cols || y <= 0){printf("该坐标超出棋盘边界,请重新输入\n");continue;}if (board[x - 1][y - 1] != ' '){printf("该坐标已经下过棋子,请重新输入\n");continue;}board[x - 1][y - 1] = '*';break;}}

电脑下棋

通过随机数函数生成x,y坐标。如果生成的坐标位置为空格,则电脑下棋完成;如果该坐标已被占用,则重新生成坐标。

void computerAddChess(char board[ROW][COL], int rows, int cols)
{printf("电脑下棋\n");int x = 0;int y = 0;while(1){x = rand() % 3 + 1;y = rand() % 3 + 1;if(board[x][y] != ' ')continue;else{board[x - 1][y - 1] = '#';break;}}displayBoard(board, rows, cols);
}

判断棋盘是否已满

假设经过判断,没有三个棋子能连成一条直线,那就无法判断谁赢谁输。若在此时,棋盘已经满了,但还是没有三个棋子练成一条直线,则双方平手(平局)。如下图所示。
在这里插入图片描述
因此,我们需要一个函数,用来判断棋盘是否已经满了。如果满了,则游戏结束;没有满则游戏继续。

int isFull(char board[ROW][COL], int rows, int cols)
{for(int i = 0; i < rows; i++){for(int j = 0; j < cols; j++){if(board[i][j] == ' ')return 0;}}return 1;
}

判断输赢

在电脑或者玩家下完棋后,我们需要判断当前状态下,是否有人获胜。根据三子棋的规则,三个棋子连成直线即获胜。下面函数中,如果玩家获胜,则返回’*‘(星号);如果电脑获胜,则返回’#‘(井号);如果棋盘满了,则返回Q,表示平局;如果没人获胜,棋盘也没满,则游戏继续,返回’C’。

char isWin(char board[ROW][COL], int rows, int cols)
{//对每一行判断for(int i = 0; i < rows; i++){if(board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')return board[i][0];}//对每一列判断for(int i = 0; i < cols; i++){if(board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')return board[0][i];}//对角线if(board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')return board[0][0];if(board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')return board[0][2];if(isFull(board, rows, cols))return 'Q';return 'C';
}

游戏函数主体

在实现了上述各个函数后,我们只要稍加组织,就可以实现游戏了。

void game()
{char board[ROW][COL] = { 0 };initBoard(board, ROW, COL);char ret = 0;while (1){playerAddChess(board, ROW, COL);ret = isWin(board, ROW, COL);if (ret != 'C')break;computerAddChess(board, ROW, COL);ret = isWin(board, ROW, COL);if (ret != 'C')break;}switch (ret){case '*':printf("玩家获胜\n");break;case '#':printf("电脑获胜\n");break;case 'Q':printf("平局\n");break;}
}

完整代码

上面代码中主函数中没有加入随机数种子,在下面代码中加入了srand((unsigned int)time(NULL)),同时对于上面出现ROW、COL的宏定义等也在下方代码整体给出。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>#define ROW 3
#define COL 3void menu()
{printf("*********************************************\n");printf("************** 1.play  0.exit ***************\n");printf("*********************************************\n");
}void initBoard(char board[ROW][COL], int rows, int cols)
{for (int i = 0; i < rows; i++){for (int j = 0; j < cols; j++){board[i][j] = ' ';}}
}void displayBoard(char board[ROW][COL], int rows, int cols)
{for (int i = 0; i < rows; i++){for (int j = 0; j < cols; j++){printf(" %c ", board[i][j]);if (j != cols - 1)printf("|");elseprintf("\n");}if (i != rows - 1){for (int j = 0; j < cols; j++){printf("---");if (j != cols - 1)printf("|");elseprintf("\n");}}}
}void playerAddChess(char board[ROW][COL], int rows, int cols)
{printf("玩家下棋\n");displayBoard(board, rows, cols);int x = 0;int y = 0;while (1){printf("请输入下棋坐标>");scanf("%d %d", &x, &y);if (x > rows || x <= 0 || y > cols || y <= 0){printf("该坐标超出棋盘边界,请重新输入\n");continue;}if (board[x - 1][y - 1] != ' '){printf("该坐标已经下过棋子,请重新输入\n");continue;}board[x - 1][y - 1] = '*';break;}}void computerAddChess(char board[ROW][COL], int rows, int cols)
{printf("电脑下棋\n");int x = 0;int y = 0;while (1){x = rand() % 3 + 1;y = rand() % 3 + 1;if (board[x - 1][y - 1] != ' ')continue;else{board[x - 1][y - 1] = '#';break;}}displayBoard(board, rows, cols);
}int isFull(char board[ROW][COL], int rows, int cols)
{for (int i = 0; i < rows; i++){for (int j = 0; j < cols; j++){if (board[i][j] == ' ')return 0;}}return 1;
}char isWin(char board[ROW][COL], int rows, int cols)
{//对每一行判断for (int i = 0; i < rows; i++){if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')return board[i][0];}//对每一列判断for (int i = 0; i < cols; i++){if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')return board[0][i];}//对角线if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')return board[0][0];if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')return board[0][2];if (isFull(board, rows, cols))return 'Q';return 'C';
}void game()
{char board[ROW][COL] = { 0 };initBoard(board, ROW, COL);char ret = 0;while (1){playerAddChess(board, ROW, COL);ret = isWin(board, ROW, COL);if (ret != 'C')break;computerAddChess(board, ROW, COL);ret = isWin(board, ROW, COL);if (ret != 'C')break;}switch (ret){case '*':printf("玩家获胜\n");break;case '#':printf("电脑获胜\n");break;case 'Q':printf("平局\n");break;}
}int main()
{int input = 0;do{menu();printf("请输入您的选择>");scanf("%d", &input);switch (input){case 1:game();//游戏具体实现函数break;case 0:printf("游戏结束\n");break;default:printf("输入有误,请重新输入\n");}} while (input);return 0;
}

分文件编写

可以创建game.h保存头文件,及各函数的函数声明;game.c保存各个函数的具体实现;main.c中保存主函数。

game.h ↓↓↓

#pragma once#include <stdio.h>
#include <stdlib.h>
#include <time.h>#define ROW 3
#define COL 3//初始化棋盘
void initBoard(char board[ROW][COL], int rows, int cols);//菜单
void menu();//打印棋盘
void displayBoard(char board[ROW][COL], int rows, int cols);//玩家下棋
void playerAddChess(char board[ROW][COL], int rows, int cols);//电脑下棋
void computerAddChess(char board[ROW][COL], int rows, int cols);//游戏
void game();//判断棋盘是否已经满了
int isFull(char board[ROW][COL], int rows, int cols);//判断是否赢
char isWin(char board[ROW][COL], int rows, int cols);

game.c ↓↓↓

#include "game.h"void menu()
{printf("*********************************************\n");printf("************** 1.play  0.exit ***************\n");printf("*********************************************\n");
}void initBoard(char board[ROW][COL], int rows, int cols)
{for (int i = 0; i < rows; i++){for (int j = 0; j < cols; j++){board[i][j] = ' ';}}
}void displayBoard(char board[ROW][COL], int rows, int cols)
{for (int i = 0; i < rows; i++){for (int j = 0; j < cols; j++){printf(" %c ", board[i][j]);if (j != cols - 1)printf("|");elseprintf("\n");}if (i != rows - 1){for (int j = 0; j < cols; j++){printf("---");if (j != cols - 1)printf("|");elseprintf("\n");}}}
}void playerAddChess(char board[ROW][COL], int rows, int cols)
{printf("玩家下棋\n");displayBoard(board, rows, cols);int x = 0;int y = 0;while (1){printf("请输入下棋坐标>");scanf("%d %d", &x, &y);if (x > rows || x <= 0 || y > cols || y <= 0){printf("该坐标超出棋盘边界,请重新输入\n");continue;}if (board[x - 1][y - 1] != ' '){printf("该坐标已经下过棋子,请重新输入\n");continue;}board[x - 1][y - 1] = '*';break;}}void computerAddChess(char board[ROW][COL], int rows, int cols)
{printf("电脑下棋\n");int x = 0;int y = 0;while (1){x = rand() % 3 + 1;y = rand() % 3 + 1;if (board[x - 1][y - 1] != ' ')continue;else{board[x - 1][y - 1] = '#';break;}}displayBoard(board, rows, cols);
}int isFull(char board[ROW][COL], int rows, int cols)
{for (int i = 0; i < rows; i++){for (int j = 0; j < cols; j++){if (board[i][j] == ' ')return 0;}}return 1;
}char isWin(char board[ROW][COL], int rows, int cols)
{//对每一行判断for (int i = 0; i < rows; i++){if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')return board[i][0];}//对每一列判断for (int i = 0; i < cols; i++){if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')return board[0][i];}//对角线if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')return board[0][0];if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')return board[0][2];if (isFull(board, rows, cols))return 'Q';return 'C';
}void game()
{char board[ROW][COL] = { 0 };initBoard(board, ROW, COL);char ret = 0;while (1){playerAddChess(board, ROW, COL);ret = isWin(board, ROW, COL);if (ret != 'C')break;computerAddChess(board, ROW, COL);ret = isWin(board, ROW, COL);if (ret != 'C')break;}switch (ret){case '*':printf("玩家获胜\n");break;case '#':printf("电脑获胜\n");break;case 'Q':printf("平局\n");break;}
}

main.c ↓↓↓

int main()
{int input = 0;do{menu();printf("请输入您的选择>");scanf("%d", &input);switch (input){case 1:game();//游戏具体实现函数break;case 0:printf("游戏结束\n");break;default:printf("输入有误,请重新输入\n");}} while (input);return 0;
}

🚩这篇文章结束了~~
如果文章中出现了错误,欢迎私信或留言。(๑•̀ㅂ•́)و✧
有任何疑问请评论或私信哦~~o( ̄▽ ̄)ブ

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/743504.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

速盾:怎么看cdn有没有加速生效?

CDN&#xff08;内容分发网络&#xff09;是一种通过在全球范围内部署服务器节点来提供高速访问内容的技术&#xff0c;可以加速网站的加载速度并提高用户体验。当我们使用CDN服务后&#xff0c;如何判断CDN是否生效成为了一个重要的问题。 要判断CDN是否生效&#xff0c;我们…

基于微信小程序的车位共享平台的设计与实现【附项目源码】分享

基于微信小程序的车位共享平台的设计与实现: 源码地址&#xff1a;https://download.csdn.net/download/qq_41810183/88842865 基于微信小程序的车位共享平台设计与实现需求文档 一、引言 随着城市化进程的加快&#xff0c;停车难问题日益凸显。为解决这一难题&#xff0c;我…

abap opensql 官方文档 abap 整洁之道

abap 整洁之道 https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP_zh.md 支持 in 语法 in &#xff08;’12‘&#xff0c;’34‘&#xff09; SELECT mainquery_clauses[UNION ...]INTO|APPENDING target[UP TO ...] [OFFSET ...][abap_options].... [END…

C#验证哥德巴赫猜想

目录 1.哥德巴赫猜想 2.验证哥德巴赫猜想 1.哥德巴赫猜想 哥德巴赫猜想&#xff08;Goldbach’s Conjecture&#xff09;是数学领域的一个著名猜想&#xff0c;由德国数学家克里斯蒂安哥德巴赫&#xff08;Christian Goldbach&#xff09;在1742年提出。这个猜想的内容是&…

VB+ACCESS学籍管理系统-264-(代码+说明)

转载地址: http://www.3q2008.com/soft/search.asp?keyword264 设计要求&#xff1a; 第一&#xff1a;一篇论文&#xff08;5000到10000字&#xff09;不包括图表和程序代码。A4纸20页之内。 论文结构如下&#xff1a; 设计题目&#xff1a;学籍管理系统 附&#xff1a;程…

KB5034441 0x80070643 reagentc.exe 无法更新引导配置数据

微软2024年1月的更新补丁正常更新会出现0x80070643错误&#xff0c;原因是正常安装系统默认的恢复分区留小了&#xff0c;通过压缩系统盘空间然后在diskgenius扩容恢复分区空间可以解决这个问题&#xff0c;但是笔者在进行上述操作时依旧出现了报错&#xff0c;按照网上的说法可…

高级JAVA工程师解决生产环境JVM宕机Java进程挡掉操作系统内存异常实例讲解

高级JAVA工程师解决生产环境JVM宕机Java进程挡掉内存溢出实例讲解 一、事故描述 生产环境Java进程莫名挡掉&#xff0c;JVM宕机。监控平台报警。生产停了&#xff0c;老板急了&#xff0c;客户爆了&#xff0c;怎么迅速解决事故&#xff1f;每次出现生产事故&#xff0c;都是…

使用公式在Excel中指定列值的变化实现自动间隔着色(不是按照固定的行数)

如果你的文件很小&#xff0c;可以手工着色&#xff1b;但如果很大&#xff0c;就要借助公式来着色&#xff1b; 目的是什么&#xff0c;其中之一是&#xff1a;提升可读性。 一起往下看吧&#xff01;&#xff01; 如果你想要根据Excel某列中值的变化来间隔着色&#xff0c;…

easyrecovery破解版百度云(含Mac/Win版)以及EasyRecovery可以恢复哪些设备

软件介绍 当不小心将回收站的文件删除了怎么办&#xff1f;想找回但是不知道怎么找回需要的数据文件&#xff1f;别担心今天小编就为大家介绍一款非常专业的电脑数据文件恢复工具&#xff0c;easyrecovery14是由Ontrack专为电脑用户推出的一款专业的数据恢复软件&…

景联文科技:提供行业垂直大模型训练数据

近年来&#xff0c;以大模型为代表的人工智能技术已成为国家科技实力竞争的焦点。其中垂直大模型作为重要方向&#xff0c;在相关政策引导及市场需求的驱动下&#xff0c;已展现出较强的发展活力。 行业垂直大模型是针对特定行业的需求和场景进行深度定制的。这意味着模型在训练…

蓝桥杯专题 bfs习题详解

1.离开中山路 #include<iostream> #include<cstring> #include<queue> #include<algorithm> #include<string> using namespace std; int x1,x2,y1,y2; int n,n1,m1; const int N1010;typedef pair<int,int> PII; queue<PII> q;int …

GIS软件应用(二)

任务&#xff1a; 1. 正确划分渔网并裁剪出研究区域 2. 渔网与poi数据正确空间链接并统计网格内类别POI数量 步骤&#xff1a; 将南京市边界进行投影变换&#xff0c;具体看我的这篇文章&#xff1a;GIS软件应用&#xff08;一&#xff09;-CSDN博客 选择ArcToolbox中的 Cr…

海豚调度系列之:集群部署(Cluster)

海豚调度系列之&#xff1a;集群部署Cluster 一、前置准备工作二、准备 DolphinScheduler 启动环境1.配置用户免密及权限2.配置机器 SSH 免密登陆3.启动 zookeeper4.初始化数据库5.修改相关配置5.修改 dolphinscheduler_env.sh 文件 三、启动DolphinScheduler四、登录 DolphinS…

3.Linux/UNIX平台Python的下载、安装和配置环境变量——《跟老吕学Python编程》

3.Linux/UNIX平台Python的下载、安装和配置环境变量——《跟老吕学Python编程》 一、下载Linux/UNIX版Python1.Python官网2.Linux/UNIX版Python下载网址 二、在Linux/UNIX安装Python1.在Ubuntu Linux安装Python1.1 检查Python版本1.2 高级包管理工具1.3 添加存储库1.4 更新软件…

HTML静态网页成品作业(HTML+CSS)——电影肖申克的救赎介绍设计制作(1个页面)

&#x1f389;不定期分享源码&#xff0c;关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 &#x1f3f7;️本套采用HTMLCSS&#xff0c;未使用Javacsript代码&#xff0c;共有1个页面。 二、作品演示 三、代…

【Flink SQL】Flink SQL 基础概念:SQL 动态表 连续查询

Flink SQL 基础概念&#xff1a;SQL 动态表 & 连续查询 1.SQL 应用于流处理的思路2.流批处理的异同点及将 SQL 应用于流处理核心解决的问题3.SQL 流处理的输入&#xff1a;输入流映射为 SQL 动态输入表4.SQL 流处理的计算&#xff1a;实时处理底层技术 - SQL 连续查询5.SQL…

Netty架构详解

文章目录 概述整体结构Netty的核心组件逻辑架构BootStrap & ServerBootStrapChannelPipelineFuture、回调和 ChannelHandler选择器、事件和 EventLoopChannelHandler的各种ChannelInitializer类图 Protocol Support 协议支持层Transport Service 传输服务层Core 核心层模块…

Windows C++ 使用WinAPI实现RPC

demo下载地址&#xff1a;https://download.csdn.net/download/2403_83063732/88958730 1、创建IDL文件以及acf文件&#xff08;创建helloworld.idl helloworld.acf&#xff09; 其中IDL文件&#xff1a; import "oaidl.idl"; import "ocidl.idl"; [ …

uView Slider 滑动选择器

该组件一般用于表单中&#xff0c;手动选择一个区间范围的场景。 说明 该组件在H5&#xff0c;微信小程序和APP-VUE等平台上使用了WXS技术&#xff0c;在NVUE平台使用了BindingX技术&#xff0c; 故在滑动过程中可以获得细腻流畅的跟随效果。 #平台差异说明 App&#xff08…

字符串和字节的使用

字符串和字节的使用 学习目标&#xff1a; 了解 常见字符以及字符集掌握 str&#xff0c;bytes以及互相转换的方法 1 字符、字符集 字符(Character)是各种文字和符号的总称&#xff0c;包括各国家文字、标点符号、图形符号、数字等 字符集(Character set)是多个字符的集合 …