三子棋——【保姆级C语言小游戏】

news2024/11/29 8:53:25

前言:今天七七为大家带来的是C语言中比较简单的小游戏“三子棋”
下面跟着七七一起来学习吧!

文章目录

  • 游戏整体思路
  • 游戏的实现流程
  • 游戏的实现
    • 菜单的打印
    • 创建与初始化棋盘
    • 玩家下棋
    • 电脑下棋
    • 判断输赢
  • 代码的整体运行

游戏整体思路

我们需要三个文件:

  1. test.c —— 测试游戏逻辑
  2. game.c —— 函数的实现
  3. game.h —— 函数的声明

游戏的实现流程

游戏分为五个部分:

  1. 构建游戏菜单,选择进入或退出游戏,选择错误可重新选择
  2. 打印棋盘,创建一个二维数组打印一个3*3的棋盘,并将其初始化
  3. 玩家下棋
  4. 电脑下棋(下过的地方不能继续下)
  5. 判断输赢

游戏的实现

菜单的打印

进入游戏首先要有一个菜单,让我们选择是否进入游戏
看代码:

#include <stdio.h>

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

	return 0;
}

代码运行结果
在这里插入图片描述

创建与初始化棋盘

创建一个棋盘并把它初始化,这里我们用InitBoard() 函数来初始化棋盘
在这里插入图片描述
但是我们发现这个棋盘的创建只能打印一个3*3的棋盘,当我们想打印更多棋盘格的棋盘时要怎么办呢?
我们可以在game.h里定义两个头文件 ROW定义行和COL列,这样我们需要打印多大的棋盘就写几就好了
在这里插入图片描述
注意: 在头文件中定义的ROW与COL在使用时要用 #include “game.h” 包含一下头文件(自己的头文件用" "来引用)

  • 我们可以把共同拥有的头文件例如#include <stdio.h>放在game.h中,这样我们只需要引用一个#include "game.h"文件就可以了
    所以创建棋盘如下:
    在这里插入图片描述
    初始化棋盘如下:
#include "game.h"
void InitBoard(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++)
		{
			board[i][j] = ' ';
		}
	}
}

棋盘的展现
棋盘初始化后就要把棋盘展现出来,展现棋盘我们用DisplayBoard() 函数打印

void DisplayBoard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 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)
		{
			for (j = 0; j < col; j++)//打印分割行
			{
				printf("---");
				if (j < col - 1)
					printf("|");
			}
		}
		printf("\n");
	}
}

棋盘展现结果:
在这里插入图片描述

玩家下棋

这里我们用PlayerMove() 表示玩家下棋
注:

  1. 接收玩家输入的地址(但是玩家不知道数组是从0开始,所以我们判断的数组元素应该是玩家输入的值-1)
  2. 判断玩家输入地方是否被占用,如果被占用重新输入
  3. 坐标超过棋盘大小也要重新输入
    代码如下:
void PlayerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("玩家下棋:>\n");

	while (1)
	{
		printf("请输入要下棋的坐标:>");
		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;
			}
			else
			{
				printf("坐标被占用,重新输入\n");
			}
		}
		else
		{
			printf("坐标非法,请重新输入\n");
		}
	}
}

运行结果如下
在这里插入图片描述

电脑下棋

电脑下棋我们用函数ComputerMove()表示,电脑为随机下棋
,设置随机数生成器,所以要包含以下头文件 #include <stdlib.h>
#include <time.h>

代码实现

void ComputerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("电脑下棋>:\n");

	while (1)
	{
		x = rand() % row;
		y = rand() % col;
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
}

运行结果如下:
在这里插入图片描述

判断输赢

设置IsWin()函数来判断输赢

通过返回值判断输赢
玩家赢 - ‘*’
电脑赢 - ‘#’
平局 - ‘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][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[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';
}

在IsWin()函数实现的过程中要设置一个IsFull() 函数来判断行,判断列,判断棋盘是不是满了
代码如下:

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;//满了
}

代码的整体运行

注: 代码有三个文件
game.h文件中

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define ROW 3
#define COL 3

//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col);

//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col);

//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col);

//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col);

//判断输赢
char IsWin(char board[ROW][COL], int row, int col);

game.c文件中

#include "game.h"
//棋盘初始化
void InitBoard(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++)
		{
			board[i][j] = ' ';
		}
	}
}

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

//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("玩家下棋:>\n");

	while (1)
	{
		printf("请输入要下棋的坐标:>");
		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;
			}
			else
			{
				printf("坐标被占用,重新输入\n");
			}
		}
		else
		{
			printf("坐标非法,请重新输入\n");
		}
	}
}


//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("电脑下棋>:\n");

	while (1)
	{
		x = rand() % row;
		y = rand() % col;
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
}


//判断棋盘是否占满
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;//满了
}


//判断输赢
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][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[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';
}

test.c文件中

#include "game.h"

void menu()
{
	printf("*******************************\n");
	printf("********    1. play      ******\n");
	printf("********    0. exit      ******\n");
	printf("*******************************\n");
}

void game()
{
	//存放数据需要一个3*3的二维数组
	char board[ROW][COL] = { 0 };
	//初始化棋盘
	InitBoard(board, ROW, COL);
	//显示棋盘
	DisplayBoard(board, ROW, COL);
	char ret = 0;
	while (1)
	{
		//玩家下棋
		PlayerMove(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		//判断输赢
		ret = IsWin(board, ROW, COL);
		if (ret != 'C')
		{
			break;
		}

		//电脑下棋
		ComputerMove(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		//判断输赢
		ret = IsWin(board, ROW, COL);
		if (ret != 'C')
		{
			break;
		}
	}
	if ('*' == ret)
	{
		printf("玩家赢\n");
	}
	else if ('#' == ret)
	{
		printf("电脑赢\n");
	}
	else if ('Q' == ret)
	{
		printf("平局\n");
	}
}

int main()
{
	int input = 0;
	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.coloradmin.cn/o/331198.html

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

相关文章

Nginx 配置文件详细介绍

1、大致说明 Nginx 包含很多配置文件&#xff0c;但是主要配置文件是&#xff1a;/usr/local/nginx/conf/nginx.conf。去掉全部注释后&#xff0c;配置文件的主体结构为&#xff1a; worker_processes 1;events {worker_connections 1024; }http {include mime.types…

勒索病毒整体攻击态势简单分析

声明 本文是学习2018勒索病毒白皮书政企篇. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 勒索病毒整体攻击态势 2018年&#xff0c;勒索病毒攻击特点也发生了变化&#xff1a;2017年&#xff0c;勒索病毒由过去撒网式无差别攻击逐步转向以服务器定…

python(14)--集合

前言 本篇文章学习的是 python 中集合的基础知识。 集合元素的内容是不可变的&#xff0c;常见的元素有整数、浮点数、字符串、元组等。至于可变内容列表、字典、集合等不可以是集合元素。虽然集合不可以是集合的元素&#xff0c;但是集合本身是可变的&#xff0c;可以去增加或…

代码随想录算法训练营第六十四天_第十章_单调栈 | 84. 柱状图中最大的矩形

LeetCode 84. 柱状图中最大的矩形 给定 n 个非负整数&#xff0c;用来表示柱状图中各个柱子的高度。每个柱子彼此相邻&#xff0c;且宽度为 1 。求在该柱状图中&#xff0c;能够勾勒出来的 矩形的最大面积。 视频讲解文章讲解https://programmercarl.com/0084.%E6%9F%B1%E7%8A%…

【MyBatis】| MyBatis的缓存

目录 一&#xff1a;MyBatis的缓存 1. ⼀级缓存 2. ⼆级缓存 3. MyBatis集成第三方缓存EhCache&#xff08;了解&#xff09; 一&#xff1a;MyBatis的缓存 &#xff08;1&#xff09;缓存(cache)&#xff1a;提前把数据存放到缓存当中&#xff0c;下一次使用的时候&#x…

谷歌浏览器无法自动更新怎么办

越来越多的小伙伴选择使用谷歌浏览器&#xff0c;近期有小伙伴发现谷歌浏览器突然无法自动升级更新了&#xff0c;这是怎么回事&#xff0c;遇到这种问题应该怎么解决呢&#xff0c;下面小编就给大家详细介绍一下谷歌浏览器无法自动更新的解决方法&#xff0c;大家感兴趣的话就…

「ChatGPT」一夜之间“火爆出圈“【杞人忧天 or 未雨绸缪】

&#x1f482;作者简介&#xff1a; THUNDER王&#xff0c;一名热爱财税和SAP ABAP编程以及热爱分享的博主。目前于江西师范大学会计学专业大二本科在读&#xff0c;同时任汉硕云&#xff08;广东&#xff09;科技有限公司ABAP开发顾问。在学习工作中&#xff0c;我通常使用偏后…

C语言-程序环境和预处理(14.1)

目录 1. 程序的翻译环境和执行环境 2. 详解编译链接 2.1 翻译环境 2.2 编译本身也分为几个阶段 2.2.1 预编译&#xff08;预处理&#xff09; 2.2.2 编译 2.2.3 汇编 2.2.4 链接 2.3 运行环境 写在最后&#xff1a; 1. 程序的翻译环境和执行环境 翻译环境&#xff1…

云借阅图书管理系统的测试项目实践

一、项目启动&#xff0c;介入了解需求二、需求分析三、制定测试方案&#xff08;计划 策略&#xff09;四、测试执行流程五、编写测试用例六、测试执行6.1 环境搭建6.2 准备工作6.3 执行6.4 缺陷管理七、输出测试报告八、版本发布九、项目总结一、项目启动&#xff0c;介入了…

CV【5】:Layer normalization

系列文章目录 Normalization 系列方法&#xff08;一&#xff09;&#xff1a;CV【4】&#xff1a;Batch normalization Normalization 系列方法&#xff08;二&#xff09;&#xff1a;CV【5】&#xff1a;Layer normalization 文章目录系列文章目录前言2. Layer normalizati…

【C++】多态详解

声明&#xff1a; 本节课件中的代码及解释都是在vs2013下的x86程序中&#xff0c;涉及的指针都是4bytes。如果要其他平台下&#xff0c;部分代码需要改动。比如&#xff1a;如果是x64程序&#xff0c;则需要考虑指针是8bytes问题等等 文章目录多态的概念多态的定义及实现多态的…

Javaweb之Http协议andTomcatandServelt的内容~

JavaWeb技术栈&#xff1a; B/S架构;Browser/server:浏览器/服务器架构模式&#xff0c;它的特点是&#xff0c;客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务器端&#xff0c;浏览器只需要请求服务器&#xff0c;获取Web资源&#xff0c;服务器把Web资源发…

2023全球市场份额排名前五的浏览器,国产的为何没上榜

数据研究机构statcounter发布了PC端浏览器在2023年1月份的最新数据统计。Chrome浏览器凭借66.39%的全球份额稳居第一&#xff0c;Edge第二&#xff0c;Safari第三&#xff0c;Firefox第四&#xff0c;Opera第五。不难看出&#xff0c;在浏览器市场全球占有率排名前5中&#xff…

LeetCode 刷题系列 -- 304. 二维区域和检索 - 矩阵不可变

给定一个二维矩阵 matrix&#xff0c;以下类型的多个请求&#xff1a;计算其子矩形范围内元素的总和&#xff0c;该子矩阵的 左上角 为 (row1, col1) &#xff0c;右下角 为 (row2, col2) 。实现 NumMatrix 类&#xff1a;NumMatrix(int[][] matrix) 给定整数矩阵 matrix 进行初…

我去,竟可直接用命令行操作ChatGPT

ChatGPT 确实杀疯了&#xff0c;已经有 1亿 月活用户了&#xff0c;毕竟它真的有智能的样子。 我前些年还开发过智能客服系统&#xff0c;要是早点遇到 ChatGPT&#xff0c;估计可以省了不少事。 我想接下来有许多业务场景都会使用到它&#xff0c;比如教学&#xff0c;内容创…

OpenCV-PyQT项目实战(5)项目案例01图像模糊

欢迎关注『OpenCV-PyQT项目实战 Youcans』系列&#xff0c;持续更新中 OpenCV-PyQT项目实战&#xff08;1&#xff09;安装与环境配置 OpenCV-PyQT项目实战&#xff08;2&#xff09;QtDesigner 和 PyUIC 快速入门 OpenCV-PyQT项目实战&#xff08;3&#xff09;信号与槽机制 …

毫米波雷达人体存在感应营造更智能的生活

毫米波雷达人体存在感应的工作原理基于多普勒效应&#xff0c;精准度高、稳定性强&#xff0c;其可以穿透非金属物质&#xff0c;比如薄木板、衣服、塑料等物质。 科技改变生活&#xff0c;营造更智能化的生活&#xff0c;最重要的是能够对人体存在进行精准检测&#xff0c;人体…

Git多人协同远程开发

1. 李四&#xff08;项目负责人&#xff09;操作步骤 在github中创建远程版本库testgit将基础代码上传⾄testgit远程库远程库中基于main分⽀创建dev分⽀将 githubleaflife/testgit 共享给组员李四继续在基础代码上添加⾃⼰负责的模块内容 2. 张三、王五&#xff08;组员&…

【树和二叉树】数据结构二叉树和树的概念认识

前言&#xff1a;在之前&#xff0c;我们已经把栈和队列的相关概念以及实现的方法进行了学习&#xff0c;今天我们将认识一个新的知识“树”&#xff01;&#xff01;&#xff01; 目录1.树概念及结构1.1树的概念1.2树的结构1.3树的相关概念1.4 树的表示1.5 树在实际中的运用&a…

SpringBoot:拦截器,过滤器,打包与运行

目录 一、拦截器 1、创建实现类实现HandlerInterceptor 接口 2、注册拦截器对象 二、过滤器 拦截器与过滤器区别 三、打包运行windows版&#xff08;jar包&#xff0c;war包&#xff09; 1、打包为jar包 2、打包为 war包 一、拦截器 拦截器(Interceptor )是一种动态拦截…