三子棋游戏

目录

1.创建项目

2.主函数编写

3.菜单函数编写

4.宏定义棋盘行和列

5.棋盘初始化

6.打印棋盘

7.玩家下棋

8.电脑下棋

9.平局判断 

10.输赢判断

11.game函数


三子棋游戏,玩家与电脑下棋

1.创建项目

新建项目,并在源文件中添加test.c、game.c文件,在头文件中添加game.h文件。

2.主函数编写

int main()
{srand((unsigned int)time(NULL));//设置随机数的生成起点int input = 0;do{menu();//菜单打印printf("请选择\n");scanf("%d", &input);switch (input){case 1:printf("开始游戏\n");game();break;case 0:printf("退出游戏\n");break;default:printf("选择错误\n");}} while (input);return 0;
}

3.菜单函数编写

打印菜单栏

//菜单打印
void menu()
{printf("*******   三子棋   ******\n");printf("*****1. play 0. exit*****\n");printf("************************\n");}

4.宏定义棋盘行和列

通过更改ROW、COL后面数字可以改变棋盘的行列。改变CON后面的数组可以更改为棋数限制,可以改成4子棋,五子棋。

#define ROW 3
#define COL 3
#define CON 3

5.棋盘初始化

初始化棋盘,使棋盘内容为”

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

6.打印棋盘

第一种写法,这种写法将行和列写死了,后续无法通过宏定义控制行列。

//打印棋盘
//第一个版本
void board_Display(char board[ROW][COL], int row, int col)
{int i = 0;for (i = 0; i < row; i++){//打印数据printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);//打印分隔符if (i < row-1)printf("---|---|---\n");}
}

版本二:

用循环的方式写,这种方法可以使用宏定义棋盘数

//打印棋盘Mark2
void board_Display2(char board[ROW][COL], int row, int col)
{int i = 0;for (i = 0; i < row; i++){//打印数据//printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);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){//printf("---|---|---\n");int j = 0;for (j = 0; j < col; j++){printf("---");if (j < col - 1)printf("|");}printf("\n");}}
}

7.玩家下棋

//玩家下棋
void Player_move(char board[ROW][COL], int row, int col)
{int x = 0;int y = 0;printf("玩家下棋\n");while (1){printf("玩家请选择下棋位置\n");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;}elseprintf("坐标已被占用,请重新选择位置\n");}elseprintf("坐标非法,请重新输入\n");}
}

8.电脑下棋

//电脑下棋
//找没有下棋的位置随机下棋
void Computer_move(char board[ROW][COL], int row, int col)
{printf("电脑下棋\n");int x = 0;int y = 0;while (1){x = rand() % row;//0-2y = rand() % col;//0-2if (board[x][y] == ' '){board[x][y] = '#';break;}}}

9.平局判断

//平局判断
//满了返回1
//不满返回0
int IsFull(char board[ROW][COL], int row, int col)
{int i = 0;int j = 0;for (i = 0; i < row; i++){for (j = 0; j < col; j++){if (board[i][j] == ' '){return 0;}	}}return 1;
}

10.输赢判断

方案一:这种判断方法不能用宏定义更改行列。将程序写死了。

//判断输赢
//
//玩家赢-'*'
//电脑赢-'#'
//平局-'Q'
//游戏继续-'c'
//
char IsWin(char board[ROW][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][1] != ' ')return board[i][1];}//列int j = 0;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];}//平局if (IsFull(board,row,col)){return 'Q';}//游戏继续return 'C';
}

方案二:

这种方法可以使用宏定义通过更改count的值来更改棋数限制(可以改成四子棋,五子棋)。

//判断输赢Mark2
char IsWin2(char board[ROW][COL], int row, int col, char tmp)//判断输赢,返回字符
{int i = 0;int j = 0;int count = 0;//判断行for (i = 0; i < ROW; i++)//判断是否有三个字符相同{int count = 0;for (j = 0; j < COL; j++){if (board[i][j] != tmp)//有一个不同就break跳出本次循环break;elsecount++;//有一个相同count就+1if (count == CON)//当count等于3时就代表一行中有三个相同return tmp;//当一行中有三个相同的字符时就代表该字符所对应的赢了返回该字符}}//判断列for (j = 0; j < COL; j++)//同理判断一列中是否有三个字符相同{int count = 0;for (i = 0; i < ROW; i++){if (board[i][j] != tmp)break;elsecount++;if (count == CON)return tmp;}}//判断//*//  *//    * //对角线方向for (count = 0, i = 0; i < ROW; i++)//判断从左往右的直线三个字符是否相同{if (board[i][i] != tmp)break;elsecount++;if (count == CON)return tmp;}//判断//      *//   *//*//对角线方向for (count = 0, j = COL - 1, i = 0; j >= 0, i <ROW; j--, i++)//判断从左往右的直线{if (board[i][j] != tmp)break;elsecount++;if (count == CON)return tmp;}//平局if (IsFull(board, row, col)){return 'Q';}//游戏继续return 'C';
}

11.game函数

game()
{char ret = 0;char board[ROW][COL] = { 0 };//棋盘初始化board_Init(board,ROW ,COL );board_Display2(board, ROW, COL);//下棋while (1){//玩家下棋Player_move(board,ROW,COL);//判断输赢//ret = IsWin(board,ROW,COL);ret = IsWin2(board, ROW, COL, '*');if (ret != 'C'){break;}board_Display2(board, ROW, COL);//电脑下棋Computer_move(board, ROW, COL);//判断输赢//ret = IsWin(board, ROW, COL);ret = IsWin2(board, ROW, COL, '#');if (ret != 'C'){break;}board_Display2(board, ROW, COL);}if (ret == '*'){printf("玩家赢\n");}else if (ret == '#'){printf("电脑赢\n");}else{printf("平局\n");}board_Display2(board, ROW, COL);
}

12.源程序代码

test.c文件代码

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include "game.h"game()
{char ret = 0;char board[ROW][COL] = { 0 };//棋盘初始化board_Init(board,ROW ,COL );board_Display2(board, ROW, COL);//下棋while (1){//玩家下棋Player_move(board,ROW,COL);//判断输赢//ret = IsWin(board,ROW,COL);ret = IsWin2(board, ROW, COL, '*');if (ret != 'C'){break;}board_Display2(board, ROW, COL);//电脑下棋Computer_move(board, ROW, COL);//判断输赢//ret = IsWin(board, ROW, COL);ret = IsWin2(board, ROW, COL, '#');if (ret != 'C'){break;}board_Display2(board, ROW, COL);}if (ret == '*'){printf("玩家赢\n");}else if (ret == '#'){printf("电脑赢\n");}else{printf("平局\n");}board_Display2(board, ROW, COL);
}//菜单打印
void menu()
{printf("*******   三子棋   ******\n");printf("*****1. play 0. exit*****\n");printf("************************\n");}int main()
{srand((unsigned int)time(NULL));//设置随机数的生成起点int input = 0;do{menu();//菜单打印printf("请选择\n");scanf("%d", &input);switch (input){case 1:printf("开始游戏\n");game();break;case 0:printf("退出游戏\n");break;default:printf("选择错误\n");}} while (input);return 0;
}

game.c文件代码

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"//棋盘初始化
void board_Init(char board[ROW][COL], int row, int col)
{int i = 0;int j = 0;for (i = 0; i < row; i++){for (j = 0; j < col; j++){board[i][j] = ' ';}}
}//打印棋盘
//第一个版本
void board_Display(char board[ROW][COL], int row, int col)
{int i = 0;for (i = 0; i < row; i++){//打印数据printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);//打印分隔符if (i < row-1)printf("---|---|---\n");}
}//打印棋盘Mark2
void board_Display2(char board[ROW][COL], int row, int col)
{int i = 0;for (i = 0; i < row; i++){//打印数据//printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);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){//printf("---|---|---\n");int j = 0;for (j = 0; j < col; j++){printf("---");if (j < col - 1)printf("|");}printf("\n");}}
}//玩家下棋
void Player_move(char board[ROW][COL], int row, int col)
{int x = 0;int y = 0;printf("玩家下棋\n");while (1){printf("玩家请选择下棋位置\n");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;}elseprintf("坐标已被占用,请重新选择位置\n");}elseprintf("坐标非法,请重新输入\n");}
}//电脑下棋
//找没有下棋的位置随机下棋
void Computer_move(char board[ROW][COL], int row, int col)
{printf("电脑下棋\n");int x = 0;int y = 0;while (1){x = rand() % row;//0-2y = rand() % col;//0-2if (board[x][y] == ' '){board[x][y] = '#';break;}}}//平局判断
//满了返回1
//不满返回0
int IsFull(char board[ROW][COL], int row, int col)
{int i = 0;int j = 0;for (i = 0; i < row; i++){for (j = 0; j < col; j++){if (board[i][j] == ' '){return 0;}	}}return 1;
}//判断输赢
//
//玩家赢-'*'
//电脑赢-'#'
//平局-'Q'
//游戏继续-'c'
//
char IsWin(char board[ROW][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][1] != ' ')return board[i][1];}//列int j = 0;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];}//平局if (IsFull(board,row,col)){return 'Q';}//游戏继续return 'C';
}//判断输赢Mark2
char IsWin2(char board[ROW][COL], int row, int col, char tmp)//判断输赢,返回字符
{int i = 0;int j = 0;int count = 0;//判断行for (i = 0; i < ROW; i++)//判断是否有三个字符相同{int count = 0;for (j = 0; j < COL; j++){if (board[i][j] != tmp)//有一个不同就break跳出本次循环break;elsecount++;//有一个相同count就+1if (count == CON)//当count等于3时就代表一行中有三个相同return tmp;//当一行中有三个相同的字符时就代表该字符所对应的赢了返回该字符}}//判断列for (j = 0; j < COL; j++)//同理判断一列中是否有三个字符相同{int count = 0;for (i = 0; i < ROW; i++){if (board[i][j] != tmp)break;elsecount++;if (count == CON)return tmp;}}//判断//*//  *//    * //对角线方向for (count = 0, i = 0; i < ROW; i++)//判断从左往右的直线三个字符是否相同{if (board[i][i] != tmp)break;elsecount++;if (count == CON)return tmp;}//判断//      *//   *//*//对角线方向for (count = 0, j = COL - 1, i = 0; j >= 0, i <ROW; j--, i++)//判断从左往右的直线{if (board[i][j] != tmp)break;elsecount++;if (count == CON)return tmp;}//平局if (IsFull(board, row, col)){return 'Q';}//游戏继续return 'C';
}

game.h文件代码

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 3
#define COL 3
#define CON 3
//棋盘初始化
void board_Init(char board[ROW][COL], int row, int col);
//打印棋盘
void board_Display(char board[ROW][COL], int row, int col);
//玩家下棋
void Player_move(char board[ROW][COL], int row, int col);
//电脑下棋
void Computer_move(char board[ROW][COL], int row, int col);
//判断输赢
char IsWin(char board[ROW][COL], int row, int col);
char IsWin2(char board[ROW][COL], int row, int col, char tmp);

13.结语:

以上就是用C语言做的简单的三子棋游戏,这个不止是三子棋游戏,可以通过更改宏定义让他变成五子棋等等,缺点是对手电脑是用随机数生成的,它所下的位置是随机的,所以我们想输都难,后续可以尝试写一个让电脑聪明点的函数,体验会更好一些。

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

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

相关文章

【AI编辑器】Cursor与DeepSeek模型的集成:提升开发效率的新选择

目录 一、为什么选择DeepSeek模型 1.1 模型参数与训练 1.2 技术创新 1、FP8格式介绍 2、FP8混合精度训练的优势 3、FP8混合精度训练的技术要点 4、FP8混合精度训练的应用与挑战 1.3 性能表现 1.4 应用与部署 1.5 争议与前景 二、注册DeepSeek账号并获取API Key 三、…

什么情况会导致JVM退出?

大家好&#xff0c;我是锋哥。今天分享关于【什么情况会导致JVM退出?】面试题。希望对大家有帮助&#xff1b; 什么情况会导致JVM退出? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 JVM&#xff08;Java Virtual Machine&#xff09;在不同情况下可能会退出&am…

软件工程实验-实验2 结构化分析与设计-总体设计和数据库设计

一、实验内容 1. 绘制工资支付系统的功能结构图和数据库 在系统设计阶段&#xff0c;要设计软件体系结构&#xff0c;即是确定软件系统中每个程序是由哪些模块组成的&#xff0c;以及这些模块相互间的关系。同时把模块组织成良好的层次系统&#xff1a;顶层模块通过调用它的下层…

《Rust权威指南》学习笔记(三)

泛型和trait 1.泛型可以提高代码的复用能力&#xff0c;泛型是具体类型或其他属性的抽象代替&#xff0c;可以看成是一种模版&#xff0c;一个占位符&#xff0c;编译器在编译时会将这些占位符替换成具体的类型&#xff0c;这个过程叫做“单态化”&#xff0c;所以使用泛型的…

计算机网络基础(7)中科大郑铨老师笔记

应用层 目标&#xff1a;  网络应用的 原理&#xff1a;网络应用协议的概念和实现方面 传输层的服务模型 客户-服务器模式 对等模式(peerto-peer) 内容分发网络  网络应用的 实例&#xff1a;互联网流行的应用层协 议  HTTP  FTP  SMTP / POP3 / IMAP  DNS…

2022浙江大学信号与系统笔记

原视频地址&#xff1a;2022浙江大学信号与系统&#xff08;含配套课件和代码&#xff09; - 胡浩基老师-哔哩哔哩 ⭐⭐⭐ 我的笔记&#xff1a;飞书链接 - 信号与系统 基于视频&#xff0c;记得笔记&#xff0c;加了点自己的补充&#xff08;有的是问 ChatGPT 的&#xff09;…

数学建模入门——建模流程

摘要&#xff1a;本文介绍了数学建模的一般流程概述。 目录 一、前言 二、数据预处理 三、描述性统计分析 四、模型建立 五、模型评价 一、前言 本文将为想要入门数学建模的同学讲述数学建模的一般流程。但数学建模流程并非一成不变。虽有大致步骤&#xff0c;像分析问题、…

如何使用OpenCV进行抓图-多线程

前言 需求&#xff1a; 1、如何使用OpenCV捕抓Windows电脑上USB摄像头的流、 2、采用多线程 3、获知当前摄像头的帧率。 这个需求&#xff0c;之前就有做了&#xff0c;但是由于出现了一个问题&#xff0c;人家摄像头的帧率目前都可以达到60帧/s 了&#xff0c;而我的程序…

NLP CH3复习

CH3 3.1 几种损失函数 3.2 激活函数性质 3.3 哪几种激活函数会发生梯度消失 3.4 为什么会梯度消失 3.5 如何解决梯度消失和过拟合 3.6 梯度下降的区别 3.6.1 梯度下降&#xff08;GD&#xff09; 全批量&#xff1a;在每次迭代中使用全部数据来计算损失函数的梯度。计算成本…

01 数据分析介绍及工具准备

数据分析介绍及工具准备 一、工具准备二、下载和使用Anaconda三、jupyter notebook常用快捷键 一、工具准备 数据科学库 NumPy&#xff0c;SciPy&#xff0c;Pandas&#xff0c;Scikit-Learn 数据可视化库 Matplotlib&#xff0c;Seaborn 编译器 Jupyter Notebook 数据科…

机组的概述

计算机系统组成 硬件系统和软件系统 计算机硬件 1.冯诺依曼机基本思想 特点 1.采用“存储程序”工作方式 2.硬件系统由运算器&#xff0c;存储器&#xff0c;控制器&#xff0c;输入输出设备组成 3.指令和数据存在存储器中&#xff0c;形式无区别 4.指令和数据用二进制代…

Windows应用开发-解析MP4视频文件(第1部分)

下载本应用 本Windows应用解析MP4视频文件&#xff0c;以表格的方式显示MP4文件结构。并可以将结果保存到bmp图片。 使用方法 选择“打开MP4视频文件”菜单项&#xff0c;打开MP4文件&#xff0c;就可以获得如下图像&#xff1a; box的每一项&#xff0c;用3个矩形表示&…

Scala_【4】流程控制

第四章 分支控制if-else单分支双分支多分支返回值嵌套分支 For循环控制包含边界不包含边界循环守卫循环步长嵌套循环循环返回值 While循环Break友情链接 分支控制if-else 单分支 双分支 多分支 返回值 嵌套分支 For循环控制 Scala也为for循环这一常见的控制结构提供了非常多的…

电商Google广告:2025年提升转化率的5种策略

展望 2025 年&#xff0c;Google 广告领域将迎来一系列显著变化&#xff0c;这些趋势对于提升广告转化率至关重要&#xff0c;值得我们提前关注与布局。 智能化程度持续加深&#xff0c;用户搜索习惯愈发精细&#xff0c;广告格式推陈出新&#xff0c;视频广告势头正猛...那么…

一文大白话讲清楚TCP连接的三次握手和断开连接的四次挥手的原理

文章目录 一文大白话讲清楚TCP连接的三次握手和断开连接的四次挥手的原理1.TCP建立连接需要3次握手1.1 先讲个你兄弟的故事1.2 TCP 3次握手1.2 TCP 3次握手8件事1.3 TCP握手能不能是两次 2. TCP 断开连接要4次挥手2.1 还回到你兄弟的故事上2.2 TCP 4次挥手2.2 TCP4次挥手4件事2…

基于springboot的课程作业管理系统(源码+数据库+文档)

亲测完美运行带论文&#xff1a;文末获取源码 文章目录 项目简介&#xff08;论文摘要&#xff09;运行视频包含的文件列表&#xff08;含论文&#xff09;前端运行截图后端运行截图 项目简介&#xff08;论文摘要&#xff09; 随着科学技术的飞速发展&#xff0c;社会的方方面…

【ArcGIS微课1000例】0136:制作千层饼(DEM、影像、等高线、山体阴影图层)

文章目录 一、效果展示二、数据准备三、制作过程1. 打开软件2. 制作DEM图层3. 制作影像层4. 制作TIN层5. 制作等高线层四、注意事项一、效果展示 二、数据准备 订阅专栏后,从专栏配套案例数据包中的0136.rar中获取。 1. dem 2. 影像 3. 等高线 4. tin 三、制作过程 1. 打开软…

蓝桥杯备赛:C++基础,顺序表和vector(STL)

目录 一.C基础 1.第一个C程序&#xff1a; 2.头文件&#xff1a; 3.cin和cout初识&#xff1a; 4.命名空间&#xff1a; 二.顺序表和vector&#xff08;STL&#xff09; 1.顺序表的基本操作&#xff1a; 2.封装静态顺序表&#xff1a; 3.动态顺序表--vector&#xff1a;…

探索AI在地质科研绘图中的应用:ChatGPT与Midjourney绘图流程与效果对比

文章目录 个人感受一、AI绘图流程1.1 Midjourney&#xff08;1&#xff09;环境配置&#xff08;2&#xff09;生成prompt&#xff08;3&#xff09;完善prompt&#xff08;4&#xff09;开始绘图&#xff08;5&#xff09;后处理 1.2 ChatGPT不合理的出图结果解决方案 二、主题…

融合表面信息和等变扩散的分子对接模型 SurfDock - 评测

SurfDock 是一个几何扩散模型&#xff0c;蛋白质序列、三维结构图、以及表面结构等结构特征&#xff0c;采用的是非欧里几何的范式处理小分子的旋转、平移以及扭转。 SurfaceDock 以蛋白口袋作为条件&#xff0c;从 rdkit 生成的随机小分子构象开始&#xff0c;对平移、旋转、扭…