c语言——三子棋

基本框架

三个文件:

其中.cpp文件用于游戏具体函数设计,.h文件为游戏的函数声明,test.cpp文件用于测试游戏运行。

 需要用到的头文件:

#include <stdio.h>
#include <stdlib.h>//rand&srand
#include <time.h>//时间相关

框架运行

#include"game.h"
void menu()
{printf("*********************************\n");printf("********      1. play    ********\n");printf("********      0. exit    ********\n");printf("*********************************\n");
}
void game()
{}
int main()
{int input;do{menu();printf("请选择:>");scanf("%d", &input);switch (input){case 1:game();break;case 0:printf("退出游戏\n");break;default:printf("选择错误,重新选择!\n");break;}} while (input);return 0;
}

运行结果:

棋盘

棋盘是一个3*3的平面,可以用二维数组接收,编译器不支持变长数组,我们可以用define定义数组的下标(行和列),之后有大用。

#define COL 3
#define ROW 3

打印:

 为什么没有对齐呢?这是因为字符数组初始化为0等价于\0,而\0是不会显示出来的,所以,我们再添加一个初始化函数。

 初始化函数

因为游戏可以反复游玩,我们不妨设置一个初始化函数,将棋子置于初始状态('  '字符)。

void init_board(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] = ' ';}}}

可以发现这次棋盘很标准了,但有点刻意的风味,如果想要一个10*10的棋盘,又要重新设计吗?应对此种情况,我们试着改进棋盘。

棋盘改进

void display_board(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)//末行不用分割{for (j = 0; j < col; j++){printf("---");if (j < col - 1){printf("|");}}printf("\n");}}
}

 看着挺复杂其实很简单,只要找出重复的部分再进行循环和判断就能打印出你想要的样子!

 玩家下棋

玩家下棋有两个注意点,判断坐标是否合法和坐标是否被占用。为此我们需要设计一个循环语句。坐标范围从1开始而不是从0开始是因为让玩家觉得合理。

void player_move(char board[ROW][COL], int row, int col)
{int x;int y;while (1){printf("请输入要下棋的坐标:>");scanf("%d %d", &x, &y);if (y <= col && x <= row){if (board[x-1][y-1] == ' '){board[x-1][y-1] = '*';break;}else{printf("该坐标被占用,请重新输入\n");}}else{printf("坐标非法,重新输入\n");}}
}

测试: 

 电脑下棋

需要用随机函数rand生成随机数和srand设置初始点使之电脑能随机在棋盘上下棋。

srand放在主函数里,循环体前,只需执行一次。 

void computer_move(char board[ROW][COL], int row, int col)
{while (1){int x = rand() % 3;//0~2int y = rand() % 3;if (board[x][y] == ' '){board[x][y] = '#';break;}}
}

胜负评判

接着需要我们评判双方获胜条件,即三子连成一条线的情况。

这里我们直接无脑评判就行,如果三处相同且不为空格则说明一方胜利

char is_win(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][0] != ' '){return board[i][1];}}//列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[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 (is_full(board, row, col) == 1){return 'Q';}//继续return 'C';
}

这里有个取巧的方法,可以直接用我们棋子所代表的字符作为返回值进行判断。

是否平局

平局需要单独判断,我们可以封装一个函数,遍历看棋盘是否已满就行了。

static int is_full(char board[ROW][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;
}

这里的static是只对本文件可见,因为它只用于我们的胜负评判。

接下来我们对主函数的game函数再增添胜负评判,每次落子之后进行评判,根据对应的返回值输出相应的结果。

运行结果:

完整代码

//game.c
#include "game.h"
void display_board(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)//末行不用分割{for (j = 0; j < col; j++){printf("---");if (j < col - 1){printf("|");}}printf("\n");}}printf("\n");
}
void init_board(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 player_move(char board[ROW][COL], int row, int col)
{int x;int y;while (1){printf("请输入要下棋的坐标:>");scanf("%d %d", &x, &y);if (y <= col && x <= row){if (board[x-1][y-1] == ' '){board[x-1][y-1] = '*';break;}else{printf("该坐标被占用,请重新输入\n");}}else{printf("坐标非法,重新输入\n");}}
}
void computer_move(char board[ROW][COL], int row, int col)
{while (1){int x = rand() % 3;int y = rand() % 3;if (board[x][y] == ' '){board[x][y] = '#';break;}}
}static int is_full(char board[ROW][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 is_win(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][0] != ' '){return board[i][1];}}//列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[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 (is_full(board, row, col) == 1){return 'Q';}//继续return 'C';
}
//.h
#define _CRT_SECURE_NO_WARNINGS 1
#pragma once#include <stdio.h>
#include <stdlib.h>
#include <time.h>#define ROW 3
#define COL 3//初始化棋盘
void init_board(char board[ROW][COL], int row, int col);
//打印棋盘
void display_board(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 is_win(char board[ROW][COL], int row, int col);
//test.c
#include"game.h"
void menu()
{printf("*********************************\n");printf("********      1. play    ********\n");printf("********      0. exit    ********\n");printf("*********************************\n");
}
void game()
{char board[ROW][COL] = { 0 };init_board(board, ROW, COL);display_board(board, ROW, COL);char ret;while (1){player_move(board, ROW, COL);display_board(board, ROW, COL);ret = is_win(board, ROW, COL);if (ret != 'C')break;computer_move(board, ROW, COL);display_board(board, ROW, COL);ret = is_win(board, ROW, COL);if (ret != 'C')break;}if (ret == 'Q'){printf("平局\n");}if (ret == '*'){printf("玩家胜\n");}if (ret == '#'){printf("电脑胜\n");}
}
int main()
{int input;srand((unsigned int)time(NULL));do{menu();printf("请选择:>");scanf("%d", &input);switch (input){case 1:game();break;case 0:printf("退出游戏\n");break;default:printf("选择错误,重新选择!\n");break;}} while (input);return 0;
}

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

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

相关文章

【linux】ssh 和adb connect区别

问&#xff1a;ssh 与ping的区别 答&#xff1a;SSH&#xff08;Secure Shell&#xff09;和Ping是两种完全不同的网络工具。 SSH是一种加密的网络协议&#xff0c;用于安全地远程管理或访问远程计算机。它提供了一种安全的通信方式&#xff0c;可以在不安全的网络上进行远程登…

03.利用Redis实现缓存功能---解决缓存穿透版

学习目标&#xff1a; 提示&#xff1a;学习如何利用Redis实现添加缓存功能解决缓存穿透版 学习产出&#xff1a; 缓存穿透讲解图&#xff1a; 解决方案&#xff1a; 采用缓存空对象采用布隆过滤器 解决方案流程图&#xff1a; 1. 准备pom环境 <dependency><gro…

【css】textarea-通过resize:none 禁止拖动设置大小

使用 resize 属性可防止调整 textareas 的大小&#xff08;禁用右下角的“抓取器”&#xff09;&#xff1a; 没有设置resize:none 代码&#xff1a; <!DOCTYPE html> <html> <head> <style> textarea {width: 100%;height: 150px;padding: 12px 20p…

【MySQL】sql字段约束

在MySQL中&#xff0c;我们需要存储的数据在特定的场景中需要不同的约束。当新插入的数据违背了该字段的约束字段&#xff0c;MySQL会直接禁止插入。 数据类型也是一种约束&#xff0c;但数据类型这个约束太过单一&#xff1b;比如我需要存储的是一个序号&#xff0c;那就不可…

页面的滚动及scrollIntoView的穿透效果和解决

朋友今天遇到一个奇怪的问题&#xff0c;我觉得很有意思就记录一下。现象是这样的&#xff0c;页面有一个按钮&#xff0c;点击按钮以后会请求一个接口拿到一个iframe的地址然后创建一个iframe并渲染到页面上&#xff0c;iframe的页面加载完毕后会滑动到对应的某一个元素的位置…

Transformer学习笔记

Transformer学习笔记 前言前提条件相关介绍Transformer总体架构编码器&#xff08;Encoder&#xff09;位置编码&#xff08;Positional Encoding&#xff09;get_attn_pad_mask函数&#xff08;Padding Mask&#xff09;EncoderLayerMultiHeadAttentionScaledDotProductAttent…

前端开发常见效果

目录 css实现图像填充文字 css实现手风琴效果 css实现网站变灰色 elementUi的导航栏效果 css实现滚动吸附效果 鼠标经过&#xff0c;元素内部放大 css实现图像填充文字 效果图&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html><head><meta c…

day17 enum abstract interface 枚举 抽象 接口

一、枚举 enum 枚举本来的面目 创建Season类&#xff0c; 所有类都默认继承Object&#xff0c;写不写都一样 声明属性 &#xff1a;季节的名字、 季节的描述&#xff0c; 因为枚举的对象是看的见的客观事物&#xff0c; 想让它的属性不可修改 使用 final修饰表示最终的 &am…

4.DNS和负载均衡

文章目录 coreDNS概念部署croeDNS测试 kubernetes多master集群结构master节点部署 负载均衡配置部署nginx做四层反向代理安装高可用 keepalivednginx监控脚本修改k8s中组件的配置文件 coreDNS 概念 coreDNS是kubernetes的默认DNS实现。可以为集群中的service资源创建一个资源名…

SQL Server 查询数据并汇总相关技巧 23.08.08

GROUPING 是一个聚合函数,它产生一个附加的列&#xff0c;当用 CUBE 或 ROLLUP 运算符添加行时&#xff0c;附加的列输出值为1&#xff0c;当所添加的行不是由 CUBE 或 ROLLUP 产生时&#xff0c;附加列值为0。 仅在与包含 CUBE 或 ROLLUP 运算符的 GROUP BY 子句相联系的选择…

安卓证书生成教程

1.下载安装JDK文件&#xff08;如已安装请跳过&#xff09; 根据电脑系统版本下载JDK版本文件 下载地址&#xff1a;[https://www.oracle.com/java/technologies/downloads/](https://www.oracle.com/java/technologies/downloads/) 如果电脑上安装过JDK文件可以跳过2.生成密钥…

怎么制作gif动态图?gif图片在线制作攻略分享

现在许多品牌和营销活动也使用gif动态图来吸引用户注意力、提升品牌形象或传递特定的信息&#xff0c;那么gif制作的过程到底难不难呢&#xff1f;其实只需要使用gif图片在线制作工具就非常简单了&#xff0c;下面以图片制作gif&#xff08;https://www.gif.cn&#xff09;为例…

Unity游戏源码分享-塔防游戏保卫兔子的食物CarrotFantasy

Unity游戏源码分享-塔防游戏保卫兔子的食物CarrotFantasy 经典塔防游戏&#xff0c;可发布PC、Andoid、IOS、Web等 下载地址&#xff1a;https://download.csdn.net/download/Highning0007/88189987

计算机网络体系结构

计算机网络体系结构 常用的网络体系结构 OSI体系结构 为了使不同体系结构的计算机网络都能互连&#xff0c;国际标准化组织于1977年成立了专门机构研究该问题&#xff0c;不就他们就提出了一个试图使各种计算机在世界范围内互连成网的标准框架&#xff0c;也就是著名的开放系…

rancher + k3s + docker私有仓库搭建K8环境(百分之百成功)

1.环境准备&#xff08;4台机器&#xff09; 文档准备了4台虚拟机&#xff0c;系统是ubuntu server: ubuntu-22.04.1-live-server-amd64.iso 然后进行安装4台虚拟机&#xff0c;如图&#xff1a; 其中一台用于rancher、其余三台跑K8&#xff0c;一台master&#xff0c;两台工作…

代谢组学市场分析,制药及生物制药行业正在推动全球代谢组学产业的发展

代谢组学是对某一生物或细胞所有小分子量代谢产物进行定性和定量分析的一门新兴学科&#xff0c;其揭示的小分子代谢产物变化是机体内基因、蛋白质/酶等功能变化的一系列事件的最终结果&#xff0c;直接反映了生物体系的最终状态&#xff0c;可以反映机体特定病理生理状态下整体…

面试热题(反转链表)

给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 。 链表的题&#xff0c;大部分都可以用指针或者递归可以做&#xff0c;指针如果做不出来的话&#xff0c;…

JMeter 查看 TPS 数据,详细指南

TPS 是软件测试结果的测量单位。一个事务是指一个客户机向服务器发送请求然后服务器做出反应的过程。客户机在发送请求时开始计时&#xff0c;收到服务器响应后结束计时&#xff0c;以此来计算使用的时间和完成的事务个数。在 JMeter 中&#xff0c;我们可以使用以下方法查看 T…

【腾讯云Cloud Studio实战训练营】React 快速构建点餐页面

前言&#xff1a; Cloud Studio是一个在线的云集成开发环境&#xff08;IDE&#xff09;&#xff0c;可以让开发人员在浏览器中轻松地开发、测试、调试和部署应用程序。它提供了基于云的计算资源和工具&#xff0c;例如代码编辑器、编译器、调试器、版本控制系统和项目管理工具…

最大子数组和【力扣53】

一、解题思路 Max[i]表示&#xff1a;以nums[i]为开头的所有连续子数组和的最大值。 由此可以推出Max[i-1]和Max[i]的关系&#xff1a; 若Max[i]>0&#xff1a;Max[i-1]nums[i-1]Max[i]&#xff1b; 否则&#xff1a;Max[i-1]nums[i-1]&#xff1b; 则ansMAX&#xff0…