C语言小游戏:三子棋

目录

🌍前言

🚅目录设计

💎游戏逻辑设置

⚔三子棋棋盘设计

⚔三子棋运行逻辑

👀怎么设置人下棋

👀怎么设置电脑下棋

✈如何判断输赢

✍结语


🌍前言

Hello,csdn的各位小伙伴你们好啊!这次小赵给大家带来的C语言小游戏是三子棋,三子棋也就是大家常玩的井字棋,这样的一个编程想必会让很多人都兴奋不已,好了好了那我们赶快开始吧。

🚅目录设计

目录的设计我们已经讲过好几遍了,还是最简单的那个,简单一个打印*加一些选项。然后用我们的switch函数来实现我们的选择,如输入1进入游戏,0跳出游戏,其他报错然后重新输入。

void meun()
{printf("*************************************************\n");printf("*********************0.exit**********************\n");printf("*********************1.play**********************\n");printf("*************************************************\n");printf("请输入你的选择:");
}
int main()
{int a = 0;do{meun();scanf("%d", &a);switch (a){case 1:game();break;case 0:printf("游戏结束\n");break;default:printf("输入错误,请重新输入\n");break;}} while (a);

 在这里我们就不多说了,详细的讲解大家可以看看前面的扫雷和猜数字游戏。(大家可以关注小赵的专栏c语言小游戏哦!

🚀游戏逻辑设置

前面的东西聊完了,那么我们就不得不聊聊我们的游戏逻辑设计,我们得先想明白我们下这个三子棋需要什么,棋盘,棋子对不对,这个至少不能少吧,那下面呢,是不是得看怎样才算赢了这了这盘棋,接着还需要考虑我们和谁下棋得问题,当然小赵在这里剧透一波,这里是和电脑哦!怎么样是不是瞬间对这个代码感到好奇了,那我们抓紧开始吧。

⚔三子棋棋盘设计

首先是棋盘设置,在这里小赵找到了一张我们正常的井字棋的图片。

小赵仿照这个图做了一个我们可以通过编程实现的较为简单的棋盘

​​​​​​​

我们可以注意到这样的一个棋盘就更好实现,因为里面的很多元素是重复的而且可以靠我们|-——来解决。当然这里我们还是和扫雷时候一样进行一个封装,将这个代码装入我们的函数中。

#define ROW  3//定义行
#define COL  3//定义列
void InitBoard(char arr[ROW][COL], int row, int col)
{for (int i = 0; i < row; i++){for (int j = 0; j < col; j++){arr[i][j] = ' ';//对数组初始化,每个位置都是空白}}
}
void PrintBoard(char arr[ROW][COL], int row, int col)
{for (int i = 0; i < row; i++){for (int j = 0; j < col; j++){printf(" %c ", arr[i][j]);//打印占棋子位子if (j < col - 1)printf("|");//打印棋盘元素//   |     |    (最后一个没有)}printf("\n");//换行for (int j = 0; j < col; j++){printf("---");if (j < col - 1)printf("|");//———|———|———(最后一个没有|)}printf("\n");}
}

那么我们的整个棋盘就算结束了,到这里。 

🚀下棋

下面就是下棋了,在这里我们先约定一下我们的棋子是什么,在这里小赵就定义一下*为我们的棋子,那么我们每次下棋实际上就是将这些空白地方放上我们的棋子,也就是取代我们的%c的空白位置。

👀怎么设置人下棋

那么人怎么下棋呢,你完全可以根据小赵的上周的博客那篇教你学C里面讲的二维数组一样,把这个棋盘的下棋位置当成二维数组的每个位置,那么我们在下的时候只需要根据我们的每个坐标来下棋就好了,在这里小赵也是封装成了一个函数。

void PersonSet(char arr[ROW][COL], int row, int col)
{int ret;do{int x, y;scanf("%d %d", &x, &y);if (x-1 < row && y-1 < col){if (arr[y-1][x-1] == ' '){arr[y-1][x-1] = '*';//对第几列第几行下棋ret = 0;}}else{printf("输入错误,请重新输入\n");//报错重新输入ret = 1;}} while (ret);
}

为了方便大家知道自己的棋是怎么下的,小赵又画了一张图供大家参考,当然画的不好请见谅。

👀怎么设置电脑下棋

这里的电脑下棋,小赵实在也不知道该如何去做一个去能分析对手下棋的强大AL,所以很抱歉,这里小赵用的还是未知数,当然如果大家有什么好的想法可以在小赵的评论区留下留言,让小赵也能学习学习。好了我们接着看电脑下棋,这里为了有所区别,小赵这里给电脑另一个棋字#,让我们有所区分。这里也是封装成一个函数了。

void ComputerSet(char arr[ROW][COL], int row, int col)
{srand((unsigned int)time(NULL));while (1) {int x = rand() % row + 1;int y = rand() % col + 1;if (arr[y - 1][x - 1] == ' '){arr[y - 1][x - 1] = '#';break;}}
}

🚀如何判断输赢

那么这个时候就是最关键的时候了。我们该如何判断输赢了,我们知道井字棋的结局共有三种,第一种是人赢了,第二种电脑赢,第三种平局(即棋盘下满了)。而且还要考虑到什么情况横着竖着和斜着,这里可以说是相当复杂了。我们一步一步来。

✊平局

平局怎么判定,其实就是棋盘上的棋子都下满了,那我们只需要用循环一个个扫就行了,确保棋盘上没有一个空的地方,且这个时候双方没有输赢(这个放在下面)。

int is_FULL(char arr[ROW][COL], int row, int col)
{for (int i = 0; i < row; i++){for(int j=0;j<col;j++)if (arr[i][j] =' '){return 0;//如果有空位,返回零}}return 1;//扫完所有放棋子,都没有空位,返回1
}

这里小赵用一种返还数字的方式来判断究竟有木有空的地方,这样我们在下面只需要将判断的三种结局的方式用一个函数穿起来就好了。 

✊判断输赢

在判断输赢这里,我们要尽可能的巧妙和省代码,比如判断人赢还是电脑赢,其实就是判断某一种棋子是否连三个相等。其次就是我们上面的平局用的1/0我们可以加入其中,如若是平局就进入if函数来出来,同时我们还要注意我们这个是一个判断,那么这个判断的时候就要注意我们判断的时候可能不是输赢平,那我们就要继续下,那我们可以再设置一个返还数字在下面,这样经过所有判断都没结果后,我们就输出一个字母意思是继续。

char is_win(char arr[ROW][COL], int row, int col)
{int i = 0;for (i = 0; i < row; i++){if (arr[i][0] ==arr[i][1] && arr[i][1] == arr[i][2] && arr[i][0] != ' '){return arr[i][0];//如果一竖行都是一种棋子,则返回这个棋子}}for (i = 0; i < col; i++){if (arr[0][i] == arr[1][i] && arr[1][i] == arr[2][i] && arr[0][i] != ' '){return arr[0][i];//如果一横行都是一种棋子,则返回这个棋子}}if (arr[0][0] == arr[1][1] && arr[1][1] ==arr[2][2] && arr[1][1] != ' '){return arr[1][1];//如果左斜着都是一种棋子,则返回这个棋子}if (arr[0][2] == arr[1][1] &&arr[1][1] == arr[2][0] && arr[1][1] != ' '){return arr[1][1];//如果右斜着都是一种棋子,则返回这个棋子}//判断平局if (is_FULL(arr, row, col))//返回1为真,0为假。{return 'Q';//如果是平局返还Q}return 'C';//若上面都不是,返还c意思是游戏继续}

🛸游戏运行逻辑

我们现在手上已经有了这么多的函数下面就要编我们的整个运行的逻辑吧。首先我们要确定的是我们的判断应该什么时候进行,我觉得应该下一次就判断一次,因为我们的函数中是有继续的选项的,所以完全可以下一次判断一次,同时下一次打印一次。

void game()
{char ret;char arr[ROW][COL];InitBoard(arr, ROW, COL);//定义数组PrintBoard(arr, ROW, COL);//打印棋盘while (1){PersonSet(arr, ROW, COL);//人下PrintBoard(arr, ROW, COL);//打印棋盘ret = is_win(arr, ROW, COL);//判断输赢if (ret != 'C')//如果输出的不是c,就是不是继续,跳出循环{break;}printf("电脑下\n");ComputerSet(arr, ROW, COL);//电脑下PrintBoard(arr, ROW, COL);//打印棋盘ret = is_win(arr, ROW, COL);//判断if (ret != 'C'){break;}}if (ret == '*')//输出人的棋{printf("玩家赢\n");}else if (ret == '#')//输出电脑的棋{printf("电脑赢\n");}else//都不是,即使Q{printf("平局\n");}}

🌍整个代码

最后我们将我们的所有代码像之前的扫雷一样,装在不同的文件中。

game.h

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#pragma once
#define ROW  3
#define COL  3
void InitBoard(char arr[ROW][COL], int row, int col);
void PrintBoard(char arr[ROW][COL], int row, int col);
void PersonSet(char arr[ROW][COL], int row, int col);
void ComputerSet(char arr[ROW][COL], int row, int col);
char is_win(char arr[ROW][COL], int row, int col);

game.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void meun()
{printf("*************************************************\n");printf("*********************1.exit**********************\n");printf("*********************2.play**********************\n");printf("*************************************************\n");printf("请输入你的选择:");
}
void game()
{char ret;char arr[ROW][COL];InitBoard(arr, ROW, COL);PrintBoard(arr, ROW, COL);while (1){PersonSet(arr, ROW, COL);PrintBoard(arr, ROW, COL);ret = is_win(arr, ROW, COL);if (ret != 'C'){break;}printf("电脑下\n");ComputerSet(arr, ROW, COL);PrintBoard(arr, ROW, COL);ret = is_win(arr, ROW, COL);if (ret != 'C'){break;}}if (ret == '*'){printf("玩家赢\n");}else if (ret == '#'){printf("电脑赢\n");}else{printf("平局\n");}}int main()
{int a = 0;do{meun();scanf("%d", &a);switch (a){case 2:game();break;case 1:printf("游戏结束\n");break;default:printf("输入错误,请重新输入\n");break;}} while (a);
}

✍结语

好了今天的分享就到这里了,大家等会可以试着去敲属于自己的三子棋C语言游戏哦!如果大家喜欢小赵的C语言游戏系列,也可以订阅小赵的C语言小游戏系列,如果大家对这个游戏代码有更好的改进完善方案也可以在评论区留言哦,小赵会一一回复的。

如果觉得文章对你有帮助的话,还请点赞,关注,收藏支持小赵,如有不足还请指点,小赵及时改正,感谢大家支持!!!

​​​​​​​​​​​​​​

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

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

相关文章

根据源码梳理Redisson的可重入、锁重试以及看门狗机制原理

Redisson可重入的原理 在上篇文章中我们已经知道了除了需要存储线程标识外&#xff0c;会额外存储一个锁重入次数。那么接下来我们查看使用Redisson时&#xff0c;Redisson的加锁与释放锁流程图。 当开始获取锁时&#xff0c;会先判断锁是否存在&#xff0c;如果存在再进行判断…

算法通关村第十六关-黄金挑战滑动窗口与堆的结合

大家好我是苏麟 , 今天带来一道小题 . 滑动窗口最大值 描述 : 给你一个整数数组 nums&#xff0c;有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动窗口中的最大值 。 题目 : …

EM32DX-C4【C#】

1外观&#xff1a; J301 直流 24V 电源输入 CAN0 CAN0 总线接口 CAN1 CAN1 总线接口 J201 IO 接线段子 S301-1、S301-2 输出口初始电平拨码设置 S301-3~S301-6 模块 CAN ID 站号拨码开关 S301-7 模块波特率拨码设置 S301-8 终端电阻选择开关 2DI&#xff1a; 公共端是…

XUbuntu22.04之OBS30.0设置录制音频降噪(一百九十六)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

LLM之Agent(三):HuggingGPT根据用户需求自动调用Huggingface合适的模型

​ 浙大和微软亚洲研究院开源的HuggingGPT&#xff0c;又名JARVIS&#xff0c;它可以根据用户的自然语言描述的需求就可以自动分析需要哪些AI模型&#xff0c;然后去Huggingface上直接调用对应的模型&#xff0c;最终给出用户的解决方案。 一、HuggingGPT的工作流程 它的…

Linux驱动开发学习笔记3《新字符设备驱动实验》

目录 一、新字符设备驱动原理 1.分配和释放设备号 2.新的字符设备注册方法 &#xff08;1&#xff09; 字符设备结构 &#xff08;2&#xff09;cdev_init函数 &#xff08;3&#xff09; cdev_add函数 &#xff08;4&#xff09;cdev_del 函数 二、自动创建设备节点 …

网络安全(二)-- Linux 基本安全防护技术

4.1. 概述 安全防护基础主要是会用Linux系统&#xff0c; 熟悉Linux基本操作命令。 在这个章节中&#xff0c;我们主要探讨自主访问控制&#xff08;许可位、ACL&#xff09;、文件属性、 PAM技术、能力机制等。 4.1.1. 补充命令 本章节中&#xff0c;涉及一些新的命令&#…

【C++】STL简介(了解)【STL的概念,STL的历史缘由,STL六大组件、STL的重要性、以及如何学习STL、STL的缺陷的讲解】

这里写自定义目录标题 一、什么是STL二、STL的版本1. 原始版本2. P. J. 版本3. RW版本★ 4. SGI版本 三、STL的六大组件四、STL的重要性五、如何学习STL六、STL的缺陷 一、什么是STL STL ( standard template libaray - 标准模板库 )&#xff1a;是C标准库 的重要组成部分&…

红队攻防之隐匿真实IP

0x01 前言 安全态势日益严峻&#xff0c;各大组织普遍采用了综合的安全产品&#xff0c;如态势感知系统、WAF和硬件防火墙等&#xff0c;这些措施加大了渗透测试和攻防演练的难度。即使是一些基本的漏洞验证、端口扫描&#xff0c;也可能导致测试IP被限制&#xff0c;从而阻碍…

DFT新手教程:VASP中ISIF取值设置

新手初学VASP计算时首先接触到的就是结构优化的计算任务。 在结构优化中&#xff0c;INCAR中的关键参数包括 IBRION &#xff0c;NSW&#xff0c;ISIF&#xff0c;EDIFF和EDIFFG 各个参数均可在vaspwiki查到可设置的参数以及该参数所具有的设置的含义。 https://www.vasp.at/…

佛罗里达大学利用神经网络,解密 GPCR-G 蛋白偶联选择性

内容一览&#xff1a;G 蛋白偶联受体 (GPCRs) 是一种将细胞膜外的刺激&#xff0c;传递到细胞膜内的跨膜蛋白&#xff0c;广泛参与到人体生理活动当中。近日&#xff0c;佛罗里达大学的研究者测定了 GPCRs 和 G 蛋白的结合选择性&#xff0c;并开发了预测二者选择性的算法&…

JVM简单了解内存溢出

JVM oracle官网文档&#xff1a;https://docs.oracle.com/en/java/javase/index.html 什么是JVM JVM(Java Virtual Machine)原名Java虚拟机&#xff0c;是一个可以执行Java字节码的虚拟计算机。它的作用是在不同平台上实现Java程序的跨平台运行&#xff0c;即使在不同的硬件…

MX6ULL学习笔记 (七) 中断实验

前言&#xff1a; 本章我们就来学习一 下如何在 Linux 下使用中断。在linux内核里面使用中断&#xff0c;不同于我们以往在别的裸机开发一样&#xff0c;需要进行各种寄存器的配置&#xff0c;中断使能之类的&#xff0c;而在Linux 内核中&#xff0c;提供了完善的中断框架…

AWS攻略——使用中转网关(Transit Gateway)连接同区域(Region)VPC

文章目录 环境准备创建VPC 配置中转网关给每个VPC创建Transit Gateway专属挂载子网创建中转网关创建中转网关挂载修改VPC的路由 验证创建业务Private子网创建可被外网访问的环境测试子网连通性Public子网到Private子网Private子网到Private子网 知识点参考资料 在《AWS攻略——…

java日历功能

java 日历功能 功能概述java代码打印结果 功能概述 输入年份和月份&#xff0c;打印该月份所有日期&#xff0c;头部信息为星期一至星期日 java代码 package com.java.core.demoTest; import java.util.Calendar; import java.util.Scanner;// 打印日历 public class Calend…

计算机网络之IP篇

目录 一、IP 的基本认识 二、DNS 三、ARP 四、DHCP 五、NAT 六、ICMP 七、IGMP 七、ping 的工作原理 ping-----查询报文的使用 traceroute —— 差错报文类型的使用 八、断网了还能 ping 通 127.0.0.1 吗&#xff1f; 8.1、什么是 127.0.0.1 &#xff1f; 8.2、为…

小程序1rpx边框不完美

问题展示 原因 rpx类似rem&#xff0c;渲染后实际转换成px之后可能存在小数&#xff0c;在不同的设备上多多少少会存在渲染的问题。而1rpx的问题就更加明显&#xff0c;因为不足1个物理像素的话&#xff0c;在IOS会进行四舍五入&#xff0c;而安卓好像统一向上取整&#xff0c…

人工智能|网络爬虫——用Python爬取电影数据并可视化分析

一、获取数据 1.技术工具 IDE编辑器&#xff1a;vscode 发送请求&#xff1a;requests 解析工具&#xff1a;xpath def Get_Detail(Details_Url):Detail_Url Base_Url Details_UrlOne_Detail requests.get(urlDetail_Url, headersHeaders)One_Detail_Html One_Detail.cont…

[MySQL--基础]多表查询

前言 ⭐Hello!这里是欧_aita的博客。 ⭐今日语录&#xff1a;生活中最大的挑战就是发现自己是谁。然后&#xff0c;坚定不移地成为那个人。 ⭐个人主页&#xff1a;欧_aita ψ(._. )>⭐个人专栏&#xff1a; 数据结构与算法 MySQL数据库 多表查询 前言多表关系概述&#x1f…

为什么 SQL 不适合图数据库

背景 “为什么你们的图形产品不支持 SQL 或类似 SQL 的查询语言&#xff1f;” 过去&#xff0c;我们的一些客户经常问这个问题&#xff0c;但随着时间的推移&#xff0c;这个问题变得越来越少。 尽管一度被忽视&#xff0c;但图数据库拥有无缝设计并适应其底层数据结构的查询…