【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,一经查实,立即删除!

相关文章

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

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

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

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

高级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…

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"; [ …

【LeetCode热题100】73. 矩阵置零(矩阵)

一.题目要求 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 二.题目难度 中等 三.输入样例 示例 1&#xff1a; 输入&#xff1a;matrix [[1,1,1],[1,0,1],[1,1,1]] 输出&#xff1a;[[1,0…

2024考研计算机考研复试-每日重点(第二十期)

公众号“准研计算机复试”&#xff0c;超全大佬复试资料&#xff0c;保姆级复试&#xff0c;80%的题目都是上岸大佬提供的。 研宝们&#xff0c;App更新啦&#xff01; 计算机组成原理&#xff1a; 10.☆什么是数据存储的大端模式和小端模式&#xff1f; 大端模式&#xff1a;数…

github拉取项目找不到前端代码

今天从github上拉取了一个项目&#xff0c;使用docker部署在了服务器上&#xff0c; 代码正常运行&#xff0c;但是想在下载的项目中找前端代码遇到了问题&#xff0c;项目结构中的template模板只有一个页面&#xff0c;于是查看nginx配置文件 查看index.html 引入了一些js文件…

使用Julia及R语言生成正态分布的随机数字并写入CSV文件

在操作之前需要先下载Julia的Distributions包&#xff0c;这个包用于进行相关概率分布的函数调用。 在输入 ] 进入Julia包管理模式后输入&#xff1a; add Distributions 这里我使用我们自己实验室的实测数据 &#xff0c;平均值0.67&#xff0c;方差0.11&#xff0c;数据分…

聚氨酯封孔剂因为热爱

忙忙碌碌又一天,对每个顾客都用心服务,因为热爱,所以不辛苦,因为热爱,即使无数遍的重复也不会厌倦。 聚氨酯封孔材料的主要性能特点&#xff1a; 1、粘度低&#xff0c;易渗入微小裂隙&#xff1b; 2、粘合能力很强&#xff0c;具有持久强粘结性&#xff1b; 3、柔韧性.越&am…

HCIP —— BGP 路径属性 (上)

目录 BGP 路径属性 1.优选Preferred-Value属性值最大的路由 2.优选Local-preference 属性数值大的路由 3.本地始发的BGP路由优先于其他对等体处学习到的路由。 4..优选AS_PATH属性值最短的路由 BGP 路径属性 BGP的路由选路是存在优选规则的&#xff0c;下图为华为官网提供…

2 配置虚拟机

1.打开VM&#xff0c;主页的界面如下&#xff0c;点击"创建新的虚拟机" 2.选择“自定义&#xff08;高级&#xff09;”&#xff0c;然后点击下一步&#xff0c;如下图所示&#xff1a; 3.下图直接点击“下一步” 4.下图的界面上&#xff0c;注意&#xff0c;不要选择…