【C语言】三子棋游戏——超细教学

🚩纸上得来终觉浅, 绝知此事要躬行。
🌟主页:June-Frost
🚀专栏:C语言

🔥该篇将结合之前的知识来实现 三子棋游戏。

目录:

  • 🌟思路框架:
    • 测试
    • 游戏
  • 🌟测试部分函数实现
  • 🌟游戏部分函数实现
  • 🌟完整的代码:
  • ❤️ 结语

🌟思路框架:

测试

通过迭代保证每次玩完游戏后可以再来一局或者退出。

游戏

博主将会对上图每一个板块进行函数实现。


🌟测试部分函数实现

  • 选择是否玩游戏

该板块的循环部分将会使用do while 循环来实现(保证一开始可以选择,运行完游戏部分后还可以继续选择)。

#include"game.h"int main()
{int input = 0;do{menu();//菜单printf("请选择:> ");scanf("%d", &input);switch (input){case 1:printf("三子棋游戏:\n");game();//游戏部分break;case 0:printf("退出游戏\n");break;default:printf("输入非法,请重新输入\n");break;}} while (input);return 0;
}

🌟游戏部分函数实现

在玩三子棋游戏中,每一步棋下完之后的状态需要保存,即需要数据的保存,所以可以创建一个3X3的数组,之后的数据操作就可以针对数组进行操作。

  • 菜单
void menu()
{printf("**************************\n");printf("********* 1.play *********\n");printf("********* 0.exit *********\n");printf("**************************\n");
}
  • 初始化棋盘

定义一个 3X3 数组后,我们将数组的元素都赋为 空格,这样就可以保证打印出来的效果是空的棋盘。

void BoardInit(char board[][Col], int row, int col)
{//遍历数组将每个元素赋为 空格int i = 0;for (i = 0; i < row; i++){int j = 0;for (j = 0; j < col; j++){board[i][j] = ' ';}}
}
  • 打印棋盘

需要产生的效果:

实现上述的效果,只需要两步拆解:
1.
将这样的棋盘首先分为三部分,每一个部分由数据部分分割线部分构成,分割线部分在最后一部分没有(只需要加一个限制条件即可)

    int i = 0;for (i = 0; i < row; i++){//打印数据printf("\n");//打印后换行//打印分割线if (i < row - 1)//保证最后一部分不打印分割线{}printf("\n");//打印后换行}


每个部分内部又可以划分为三部分,与第一次拆解逻辑一摸一样,注意第三部分没有 | 即可

void DisplayBoard(char board[][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");}
}
  • 玩家下棋:

这里需要注意 检查玩家输入的坐标是否合法,以及该坐标下是否已经有棋子。而且,在写条件的时候,需要代入玩家视角,输入区间为 1 —— 3,但访问区间为 0——2 。

void PlayerMove(char board[][Col], int row, int col)
{printf("玩家下棋:\n");printf("请输入下棋的坐标,中间使用空格:>");while (1){int x = 0;int y = 0;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] = 'X';//落子break;}else{printf("该位置已有棋子,请重新输入:>");}}else{printf("输入非法,请重新输入:>");}}
}
  • 电脑下棋
    这里需要使用伪随机数,并且直接将范围锁定在 0——2,可以直接访问数组元素。完成该功能只需要判断 坐标下是否有棋子,若有棋子,则重新生成随机数。若要了解随机数,可以参考——随机数 。
void ComputerMove(char board[][Col], int row, int col)
{printf("电脑下棋:\n");while (1){int x = rand() % row;int y = rand() % col;if (board[x][y] == ' '){board[x][y] = 'O';break;}}
}
  • 判断输赢

只需要从4种方向遍历数组,有符合获胜条件的直接返回数组元素,如果没有获胜,则需要判断是否棋盘已满(平局),除此之外就是未完成该局,继续下棋。

所以返回值 有四种情况:
电脑赢 —— 返回 ‘O’
玩家赢 —— 返回 ‘X’
平局 —— 返回 ‘P’
继续 —— 返回 ‘C’

int IsFull(char board[][Col], int row, int col)//判断是否已满,已满返回1
{//遍历int  i = 0;for (i = 0; i < row; i++){int j = 0;for (j = 0; j < col; j++){if (board[i][j] == ' ')return 0;}}return 1;
}
//判断输赢
char IsWin(char board[][Col], int row, int col)
{//一方获胜//从上到下遍历int i = 0;for (i = 0; i < row; i++){if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' '){return board[i][0];}}//从左至右遍历for (i = 0; i < col; 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[1][1];}//左下至右上if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[2][0] != ' '){return board[1][1];}//平局if (IsFull(board,row,col)){return 'P';}return 'C';}
  • 游戏逻辑部分

我们已经有了所有的功能函数,按照思路框架直接写出来即可。

void game()
{char board[Row][Col] = { 0 };BoardInit(board, Row, Col);DisplayBoard(board, Row, Col);//先手判断//假设玩家先手void(*Fir)(char board[][Col], int, int) = PlayerMove;void(*Sec)(char board[][Col], int, int) = ComputerMove;int flag = rand()%2; //1——玩家先手,0——电脑先手if (flag == 0){printf("电脑先手\n");Fir = ComputerMove;Sec = PlayerMove;}else{printf("玩家先手\n");}//char ret = 0;while (1){Fir(board, Row, Col);DisplayBoard(board, Row, Col);ret = IsWin(board, Row, Col);if (ret != 'C')break;Sec(board, Row, Col);DisplayBoard(board, Row, Col);ret = IsWin(board, Row, Col);if (ret != 'C')break;}if (ret == 'X'){printf("玩家获胜\n");}else if (ret == 'O'){printf("电脑获胜\n");}else{printf("平局\n");}
}

首先假设玩家是先手,如果flag =1,则照旧进行,如果flag = 0,就直接交换先后手。

🌟完整的代码:

test.c :

请记得设置随机数起点srand。

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"int main()
{int input = 0;srand((unsigned int)time(NULL));//起点do{menu();//菜单printf("请选择:> ");scanf("%d", &input);switch (input){case 1:printf("三子棋游戏:\n");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 menu();
//游戏(逻辑)
void game();
//初始化棋盘
void BoardInit(char board[][Col], int row, int col);
//打印棋盘
void DisplayBoard(char board[][Col], int row, int col);
//玩家下棋
void PlayerMove(char board[][Col], int row, int col);
//电脑下棋
void ComputerMove(char board[][Col], int row, int col);
//判断输赢
char IsWin(char board[][Col], int row, int col);

game.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"void menu()
{printf("**************************\n");printf("********* 1.play *********\n");printf("********* 0.exit *********\n");printf("**************************\n");
}void BoardInit(char board[][Col], int row, int col)
{//遍历数组将每个元素赋为 空格int i = 0;for (i = 0; i < row; i++){int j = 0;for (j = 0; j < col; j++){board[i][j] = ' ';}}
}void DisplayBoard(char board[][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");}
}void PlayerMove(char board[][Col], int row, int col)
{printf("玩家下棋:\n");printf("请输入下棋的坐标,中间使用空格:>");while (1){int x = 0;int y = 0;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] = 'X';//落子break;}else{printf("该位置已有棋子,请重新输入:>");}}else{printf("输入非法,请重新输入:>");}}
}void ComputerMove(char board[][Col], int row, int col)
{printf("电脑下棋:\n");while (1){int x = rand() % row;int y = rand() % col;if (board[x][y] == ' '){board[x][y] = 'O';break;}}
}int IsFull(char board[][Col], int row, int col)
{//遍历int  i = 0;for (i = 0; i < row; i++){int j = 0;for (j = 0; j < col; j++){if (board[i][j] == ' ')return 0;}}return 1;
}char IsWin(char board[][Col], int row, int col)
{//一方获胜//从上到下遍历int i = 0;for (i = 0; i < row; i++){if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' '){return board[i][0];}}//从左至右遍历for (i = 0; i < col; 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[1][1];}//左下至右上if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[2][0] != ' '){return board[1][1];}//平局if (IsFull(board,row,col)){return 'P';}return 'C';}void game()
{char board[Row][Col] = { 0 };BoardInit(board, Row, Col);DisplayBoard(board, Row, Col);//先手判断//假设玩家先手void(*Fir)(char board[][Col], int, int) = PlayerMove;void(*Sec)(char board[][Col], int, int) = ComputerMove;int flag = rand()%2; //1——玩家先手,0——电脑先手if (flag == 0){printf("电脑先手\n");Fir = ComputerMove;Sec = PlayerMove;}else{printf("玩家先手\n");}//char ret = 0;while (1){Fir(board, Row, Col);DisplayBoard(board, Row, Col);ret = IsWin(board, Row, Col);if (ret != 'C')break;Sec(board, Row, Col);DisplayBoard(board, Row, Col);ret = IsWin(board, Row, Col);if (ret != 'C')break;}if (ret == 'X'){printf("玩家获胜\n");}else if (ret == 'O'){printf("电脑获胜\n");}else{printf("平局\n");}
}

❤️ 结语

文章到这里就结束了,如果对你有帮助,你的点赞将会是我的最大动力,如果大家有什么问题或者不同的见解,欢迎大家的留言~

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

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

相关文章

python爬虫9:实战2

python爬虫9&#xff1a;实战2 前言 ​ python实现网络爬虫非常简单&#xff0c;只需要掌握一定的基础知识和一定的库使用技巧即可。本系列目标旨在梳理相关知识点&#xff0c;方便以后复习。 申明 ​ 本系列所涉及的代码仅用于个人研究与讨论&#xff0c;并不会对网站产生不好…

微服务基础概念【内含图解】

目录 拓展补充&#xff1a; 单体架构 分布式架构 面向服务的体系结构 云原生 微服务架构 什么是微服务&#xff1f; 微服务定义 拓展补充&#xff1a; 单体架构 单体架构&#xff1a;将业务的所有功能集中在一个项目中开发&#xff0c;最终打成一个包部署 优点&#x…

leetcode1094. 拼车(差分数组-java)

差分数组 leetcode 1094 拼车差分数组代码演示&#xff1a; 前缀和数组 leetcode 1094 拼车 难度 - 中等 原题链接 - 拼车 车上最初有 capacity 个空座位。车 只能 向一个方向行驶&#xff08;也就是说&#xff0c;不允许掉头或改变方向&#xff09; 给定整数 capacity 和一个数…

探究Java spring中jdk代理和cglib代理!

面对新鲜事物&#xff0c;我们要先了解在去探索事物的本质-默 目录 一.介绍二者代理模式 1.1.Jdk代理模式 1.2cglib代理模式 1.3二者区别 1.3.1有无接口 1.3.2灵活性 1.4对于两种代理模式的总结 1.4.1jdk代理模式 1.4.2cglib代理模式 二.两种代理模式应用场景 2.1jd…

SMS 与 WhatsApp 营销,哪个方式最适合你的业务?

SMS和 WhatsApp营销越来越受欢迎&#xff0c;因为它们为企业提供了接触目标受众的有效方式。超过 91%的客户希望收到来自企业的 SMS消息&#xff0c;使用WhatsAppAPI发送的消息的打开率高达99% &#xff0c;这证明了这两种形式的消息传递对于希望及时与客户沟通的企业来说变得重…

软考高级架构师下篇-12层次式架构设计理论与实践

目录 1. 考情分析2. 层次式体系结构概述3. 表现层框架设计4. 中间层框架设计5. 数据访问层设计6. 数据架构规划与设计7. 物联网层次架构设计8. 前文回顾1. 考情分析 根据考试大纲,层次式架构设计理论与实践知识点会涉及单选题型(约占2~5分)和案例题(25分),本小时内容偏重于方…

以创新点亮前路,戴尔科技开辟数实融合新格局

编辑&#xff1a;阿冒 设计&#xff1a;沐由 2023年&#xff0c;对于戴尔科技而言是特殊的一年&#xff0c;这是戴尔科技进入中国市场第25个年头——“巧合”的是&#xff0c;这25年也是中国产业经济发展最快&#xff0c;人们工作与生活发生变化最大的四分之一个世纪。 2023年&…

特斯拉Model 3的七年狂飙

‍ 作者 | 张祥威 编辑 | 德新 发布一周拿下32万张订单&#xff0c;之后用时五年&#xff0c;交付量突破100万辆。粗略计算&#xff0c;自2016年发布至今&#xff0c;特斯拉Model 3已交付超150万辆。 放眼新能源赛道&#xff0c;如此战绩 别无二家。 Model 3踩中纯电动车的…

SpringBoot 配置优先级

一般而言&#xff0c;SpringBoot支持配置文件进行配置&#xff0c;即在resources下的application.properties或application.yml。 关于配置优先级而言&#xff0c; application.properties>application.yml>application.yaml 另外JAVA程序程序还支持java系统配置和命令行…

Apipost数据模型功能详解

在API设计和开发过程中&#xff0c;存在许多瓶颈&#xff0c;其中一个主要问题是在遇到相似数据结构的API时会产生重复性较多的工作&#xff1a;在每个API中都编写相同的数据&#xff0c;这不仅浪费时间和精力&#xff0c;还容易出错并降低API的可维护性。 为了解决这个问题&a…

乖宝宠物上市,能否打破外资承包中国宠物口粮的现实

近日&#xff0c;乖宝宠物上市了&#xff0c;这是中国宠物行业成功挂牌的第三家公司。同时&#xff0c;昨日&#xff0c;宠物行业最大的盛事“亚洲宠物展”时隔3年&#xff0c;于昨日在上海成功回归。 这两件事情的叠加可谓是双喜临门&#xff0c;行业能够走到今天实属不易&…

VLAN实验

思路&#xff1a;交换机改接口模式&#xff0c;通过hybrid混杂模式更改权限&#xff0c;路由器用子接口 根据题干分析&#xff0c;得pc1 :v2 pc2:v3456 pc3:v2 pc4:v34 pc5:v35 pc6:v36 pc2/4/5/6不能允许v2&#xff0c;pc1/2访问&#xff0c;是通过路由器查找的&#xff0c;…

不得不说API效率快,批量采集淘宝1688等商品详情页面数据

API接口获取数据有以下几个好处&#xff1a; 1. 数据的实时性&#xff1a;通过API接口获取数据可以实时获取最新的数据&#xff0c;保证数据的及时性。这对于需要及时更新数据的应用非常重要&#xff0c;比如股票行情、天气预报等。 2. 数据的准确性&#xff1a;通过API接口获…

drools8尝试

drools7升级到drools8有很大很大的变更.几乎不能说是一个项目了. 或者说就是名字相同的不同项目, 初看下来变化是这样 两个最关键的东西都retired了 https://docs.drools.org/8.42.0.Final/drools-docs/drools/migration-guide/index.html business central变成了一个VS code…

PDF怎么转Word?8 个最佳 PDF 转 Word 转换器

PDF 转 Word 转换工具只是一个特殊程序&#xff0c;可以将 PDF&#xff08;本机和/或扫描&#xff09;转换为 Microsoft Office Word 格式。将 PDF 导出到 Word 的主要原因之一是满足可编辑文档的需求&#xff0c;尽管还有其他原因。 由于缺少 PDF 阅读器&#xff0c;您可以选…

积跬步至千里 || 矩阵可视化

矩阵可视化 矩阵可以很方面地展示事物两两之间的关系&#xff0c;这种关系可以通过矩阵可视化的方式进行简单监控。 定义一个通用类 from matplotlib import pyplot as plt import seaborn as sns import numpy as np import pandas as pdclass matrix_monitor():def __init…

AMBA总线协议(5)——AHB(三):猝发传输

一、前言 在之前的文章中我们详细讲述了关于AHB的基本操作流程&#xff0c;主机要先从仲裁器获得授权&#xff0c;然后进行总线的访问&#xff0c;这样可以避免总线冲突&#xff0c;获得授权后&#xff0c;主机给出地址和控制信号&#xff0c;从机根据自身情况进行响应&#xf…

多维时序 | MATLAB实现SCNGO-CNN-Attention多变量时间序列预测

多维时序 | MATLAB实现SCNGO-CNN-Attention多变量时间序列预测 目录 多维时序 | MATLAB实现SCNGO-CNN-Attention多变量时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.SCNGO-CNN-Attention超前24步多变量回归预测算法。 程序平台&#xff1a;无Attention适…

《一个操作系统的实现》windows用vm安装CentOS——从bochs环境搭建到第一个demo跑通

vm安装CentOS虚拟机带有桌面的版本。su输入密码123456。更新yum -y update 。一般已经安装好后面这2个工具&#xff1a;yum install -y net-tools wget。看下ip地址ifconfig&#xff0c;然后本地终端连接ssh root192.168.249.132输入密码即可&#xff0c;主要是为了复制网址方便…

ASR(自动语音识别)任务中的LLM(大语言模型)

一、LLM大语言模型的特点 二、大语言模型在ASR任务中的应用 浅度融合 浅层融合指的是LLM本身并没有和音频信息进行直接计算。其仅对ASR模型输出的文本结果进行重打分或者质量评估。 深度融合 LLM与ASR模型进行深度结合&#xff0c;统一语音和文本的编码空间或者直接利用ASR…