基于C语言的趣味游戏之五子棋

news2024/11/15 20:00:44

目录

 

趣味五子棋游戏

 第一步

text.c文件 

 第二步

game.h文件

第三步

初始化

 打印棋盘

玩家输入 

电脑输入

判断输赢 

game.c


趣味五子棋游戏

 第一步

先写菜单,然后在主函数里调用,由于这是一个可以重复的游戏所以将do while循环里调用menu函数。

  1. 当我们键盘输入1时开启游戏,调用game()函数。由于我们是一个五子棋游戏,那么可能需要一个5x5大小的棋盘,所以我们要定义一个字符型的棋盘char board[ROW][COL];
  2. 定义好棋盘之后就初始化棋盘,在game.c文件里初始化。
  3. 初始化完之后就要打印棋盘。
  4. 然后就是让玩家落子,在判输赢,接着电脑落子,接着判输赢,这是一个循环的操作,所以需要一个while循环让这个操作循环起来。

text.c文件 

//text.c文件
#define _CRT_SECURE_NO_WARNINGS
#include"game.h"

//五子棋

//菜单
void menu()
{
	printf("***********************\n");
	printf("******   1 paly  ******\n");
	printf("******   0 exit  ******\n");
	printf("***********************\n");
}
void game()
{
	char board[ROW][COL];
	//初始化棋盘
	InitBoard(board, ROW, COL);
	//打印棋盘
	displayBoard(board, ROW, COL);
	char ret = 0;
	while(1)
	{
		//玩家下棋
		playermove(board, ROW, COL);
		//打印棋盘
		displayBoard(board, ROW, COL);
		//判断输赢
		ret = inwin(board, ROW, COL);
		if (ret != 'C')
		{
			break;
		}
		//电脑下棋
		computermove(board, ROW, COL);
		//打印棋盘
		displayBoard(board, ROW, COL);
		//判断输赢
		ret = inwin(board, ROW, COL);
		if (ret != 'C')
		{
			break;
		}
	}

	if(ret=='*')
	{
		printf("玩家赢了\n");
	}else if(ret=='#')
	{
		printf("电脑赢了\n");
	}
	else {
		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");
		default:
			printf("请输入正确的数字\n");
			break;
		}
		


	} while (input);
	return 0;
}

 第二步

是去头文件里去声明函数以及将一些公共的头文件包含起来。在一些大型的开发都是声明和函数实现分离的。

game.h文件

#pragma once
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<time.h>
#include"game.h"


#define ROW 5
#define COL 5
//初始化棋盘
void InitBoard(char borad[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 inwin(char board[ROW][COL], int row, int col);

第三步

 去game.c文件里去实现函数的相关功能。

初始化

初始化棋盘,就是将5x5的数组具象化,将他形成5x5的空格。当用户在相应的坐标里输入时,就将对应的空格替换成特定的符号。

 打印棋盘

//初始化棋盘
void InitBoard(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] = ' ';
		}
	}
}

对于打印棋盘,我们可以观察一下棋盘,可以将棋盘划分成两个部分一个是要输入数值部分,一个是分割部分

这里绿色部分为数值部分是用户和电脑输入坐标的部分,数值部分由  空格 | 空格 | 空格组成

红色部分是分割部分,由 ..... | ..... | ..... 组成 。

在代码实现的时候可以分两部分,数值部分,循环打印数值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++)
	{
		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");
			
	}
}

玩家输入 

 由于数组的下标是从0开始到n-1的,但是玩家是不会考虑这些的,所以玩家的输入的下标,应该在要减一才是棋盘的下标

首先要判空,看玩家输入的下标是否不合法,收否不为空格,不为空格就是这个下标已经被占用了。

 最后在合法的下标下,将玩家输入的下标位置用 ‘ * ’替换空格。

//玩家下棋
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");
		}
	}
}

电脑输入

 我们设计电脑输入为随机的输入,用到了随机函数rand,用rand去%模row,col是为了随机值是在小于row和col的情况下。但是别忘了,在用rand之前要先使用srand随机数种子,为了确保随机数种子的唯一性,我们将随机数种子放在test.c文件的main()函数里,确保随机数种子只被调用一次

将电脑输入的合法下标下,用#号去替换原有的空格。

//电脑随机下棋
void computermove(char board[ROW][COL], int row, int col)
{
	printf("电脑下棋\n");
	int x = 0;
	int y = 0;
	while(1)
	{
		x = rand() % row;
		y = rand() % col;
		if(board[x][y]==' ')
		{
			board[x ][y ] = '#';
			break;
		}
	}

}

判断输赢 

 玩过五子棋的都知道,五子棋只有在五个棋子连在一起的情况才会赢。所以我们分三种情况。

第一种,用一个循环,判断所以行是否出现一样的情况。

第二种,所有列是否出现一样的情况。

第三种,正负对角线有没有出现一样的情况。

最后用他们一样的情况的一个点作为返回条件去判断谁赢了。

如果返回 * 则玩家赢;如果返回 # 则电脑赢了。如果返回Q则平局。

//判平局
static 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 inwin(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][2] == board[i][3]&&board[i][3] == board[i][4]&& 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][1] && board[2][i] == board[3][i] && board[3][i] == board[4][i] && board[0][i] != ' ')
		{
			return board[0][i];
		}
	}
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[2][2] == board[3][3] &&board[3][3] == board[4][4] && board[1][1] != ' ')
	{
		return board[0][0];
	}

	if (board[0][4] == board[1][3] && board[1][3] == board[2][2] && board[2][2] == board[3][1]&&board[3][1] == board[4][0] && board[0][4] != ' ')
	{
		return board[0][4];
	}
	//判断平局
	if (IsFull(board, row, col))
	{
		return 'Q';
	}

	return 'C';
}

game.c

//game.c
#define _CRT_SECURE_NO_WARNINGS
#include"game.h"
//初始化棋盘
void InitBoard(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 displayBoard(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++)
		{
			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)
{
	printf("电脑下棋\n");
	int x = 0;
	int y = 0;
	while(1)
	{
		x = rand() % row;
		y = rand() % col;
		if(board[x][y]==' ')
		{
			board[x ][y ] = '#';
			break;
		}
	}

}
//判平局
static 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 inwin(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][2] == board[i][3]&&board[i][3] == board[i][4]&& 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][1] && board[2][i] == board[3][i] && board[3][i] == board[4][i] && board[0][i] != ' ')
		{
			return board[0][i];
		}
	}
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[2][2] == board[3][3] &&board[3][3] == board[4][4] && board[1][1] != ' ')
	{
		return board[0][0];
	}

	if (board[0][4] == board[1][3] && board[1][3] == board[2][2] && board[2][2] == board[3][1]&&board[3][1] == board[4][0] && board[0][4] != ' ')
	{
		return board[0][4];
	}
	//判断平局
	if (IsFull(board, row, col))
	{
		return 'Q';
	}

	return 'C';
}


代码压缩包

https://download.csdn.net/download/qq_62830324/88779627icon-default.png?t=N7T8https://download.csdn.net/download/qq_62830324/88779627 

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

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

相关文章

C/C++ - 类的封装特性

目录 类的封装 语法格式 声明定义 分文件 访问权限 类作用域 对象模型 构造函数 默认构造函数 带参构造函数 拷贝构造函数 构造函数重载 委托构造函数 初始数据列表 构造默认参数 构造函数删除 析构函数 析构函数概念 析构函数特性 析构函数示例 析构调用…

【Unity】【游戏开发】Pico打包后项目出现运行时错误如何Debug

【背景】 开发过程中的报错可以通过控制台查看&#xff0c;但是PICO项目这类依赖特定设备环境的应用往往存在打包后在设备端发生运行时错误。这时如何能查看到Debug信息呢&#xff1f; 【分析】 Pico也是安卓系统&#xff0c;所以这个问题就可以泛化为Unity有哪些在安卓端运…

dnSpy调试工具二次开发2-输出日志到控制台

本文在上一篇文章的基础上继续操作&#xff1a; dnSpy调试工具二次开发1-新增菜单-CSDN博客 经过阅读dnSpy的源码&#xff0c;发现dnSpy使用到的依赖注入用了MEF框架&#xff0c;所以在源码中可以看到接口服务类的上面都打上了Export的特性或在构造方法上面打上ImportingConst…

力扣hot100 最小栈 变种栈

Problem: 155. 最小栈 文章目录 思路&#x1f496; Stack 自定义 Node&#x1f37b; Code 思路 &#x1f469;‍&#x1f3eb; 甜姨 &#x1f496; Stack 自定义 Node 时间复杂度: O ( 1 ) O(1) O(1) 空间复杂度: O ( n ) O(n) O(n) &#x1f37b; Code class MinS…

数据结构-顺序表的实现 [王道]

本博客记录个人寒假学习内容。此篇博客内容为 顺序表的定义。 博客中截图来自王道数据结构公开课 目录 顺序表的定义 顺序表的特点 顺序表的实现--静态分配 顺序表的实现--动态分配 顺序表的定义--知识结构框架 顺序表的定义 >线性表是具有相同(每个数据元素所占的空间…

Spring Boot使用AOP

一、为什么需要面向切面编程&#xff1f; 面向对象编程&#xff08;OOP&#xff09;的好处是显而易见的&#xff0c;缺点也同样明显。当需要为多个不具有继承关系的对象添加一个公共的方法的时候&#xff0c;例如日志记录、性能监控等&#xff0c;如果采用面向对象编程的方法&…

CSS优先级内容

定义CSS样式时&#xff0c;经常出现两个或多个样式规则应用在同一元素的情况&#xff0c;这时就会出现优先级的情况&#xff0c;那么应用的元素应该显示哪一个样式呢&#xff1f; 一.下面举例对优先级进行具体讲解。 p{color:red;} .blue{color:orange;} #header{color:blu…

OpenCV-27 Canny边缘检测

一、概念 Canny边缘检测算法是John F.Canny与1986年开发出来的一个多级边缘检测算法&#xff0c;也被很多人认为是边缘检测的最优算法。最优边缘检测的三个主要评价标准是&#xff1a; 低错频率&#xff1a;表示出尽可能多的实际边缘&#xff0c;同时尽可能的减小噪声产生的误…

Spring源码分析:refresh()

refresh()中共有13个方法&#xff0c;分别为 1.prepareRefresh() 容器刷新前的准备&#xff0c;设置上下文状态&#xff0c;获取属性&#xff0c;验证必要的属性等 protected void prepareRefresh() {//spring启动时间this.startupDate System.currentTimeMillis();//spring…

01 Redis的特性+下载安装启动+Redis自动启动+客户端连接

1.1 NoSQL NoSQL&#xff08;“non-relational”&#xff0c; “Not Only SQL”&#xff09;&#xff0c;泛指非关系型的数据库。 键值存储数据库 &#xff1a; 就像 Map 一样的 key-value 对。如Redis文档数据库 &#xff1a; NoSQL 与关系型数据的结合&#xff0c;最像关系…

Python如何获取程序打包后的目录,如何获取管理员权限

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 实现步骤 📒📝 获取程序打包后所在目录📝 获取管理员权限⚓️ 相关链接 ⚓️📖 介绍 📖 Python 是一种功能强大的编程语言,本篇文章将介绍Python如何获取程序打包后所在目录,以及如何获取管理员权限并执行需要管理…

【深度学习】sdxl中的 tokenizer tokenizer_2 区别

代码仓库&#xff1a; https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0/tree/main 截图&#xff1a; 为什么有两个分词器 tokenizer 和 tokenizer_2&#xff1f; 在仔细阅读这些代码后&#xff0c;我们了解到 tokenizer_2 主要是用于 refiner 模型的。 #…

javax.servlet.http包

javax.servlet.http包 javax.srvlet.http包是对javax.servlet包的扩展。该包的类和接口处理使用HTTP进行通信的servlet。这些servlet也称为HTTP Servlet。您需要扩展HttpServlet类来开发HTTP Servlet。javax.servlet.http包经常使用的接口包括: HttpServletRequest接口HttpSe…

Windows10上通过MSYS2编译FFmpeg 6.1.1源码操作步骤

1.从github上clone代码&#xff0c;并切换到n6.1.1版本&#xff1a;clone到D:\DownLoad目录下 git clone https://github.com/FFmpeg/FFmpeg.git git checkout n6.1.1 2.安装MSYS2并编译FFmpeg源码: (1).从https://www.msys2.org/ 下载msys2-x86_64-20240113.exe &#…

x-cmd pkg | shtris - 命令行俄罗斯方块游戏

目录 简介首次用户技术特点竞品和相关作品进一步阅读 简介 shtris 是一个由 shell 脚本&#xff0c;参考 俄罗斯方块指南 (2009) 实现的俄罗斯方块游戏。 首次用户 使用 x shtris 即可自动下载并使用 在终端运行 eval "$(curl https://get.x-cmd.com)" 即可完成 x …

[TCP协议]基于TCP协议的字典服务器

目录 1.TCP协议简介: 2.TCP协议在Java中封装的类以及方法 3.字典服务器 3.1服务器代码: 3.2客户端代码: 1.TCP协议简介: TCP协议是一种有连接,面向字节流,全双工,可靠的网络通信协议.它相对于UDP协议来说有以下几点好处: 1.它是可靠传输,相比于UDP协议,传输的数据更加可靠…

在ubuntu上在安装Squid代理服务器

Squid 是一个代理和缓存服务器&#xff0c;它将请求转发到所需的目的地&#xff0c;同时保存请求的内容&#xff0c;当你再次请求相同内容时&#xff0c;他可以向你提供缓冲内容&#xff0c;从而提高访问速度。Squid代理服务器目前支持的协议有&#xff1a;http、SSL、DNS、FTP…

【机组】单元模块的软件简介和安装

​&#x1f308;个人主页&#xff1a;Sarapines Programmer&#x1f525; 系列专栏&#xff1a;《机组 | 模块单元实验》⏰诗赋清音&#xff1a;云生高巅梦远游&#xff0c; 星光点缀碧海愁。 山川深邃情难晤&#xff0c; 剑气凌云志自修。 目录 【软件简介和安装】 1 性能特…

JVM篇:垃圾回收算法

标记清除 通过遍历GC Root后得到不再被引用的对象&#xff0c;对没被引用的对象做一个标记处理&#xff0c;然后对其进行清除。 优点&#xff1a;速度快 缺点&#xff1a;会产生内存碎片&#xff0c;可能会导致空闲的内存足够保存对象&#xff0c;但由于不连续而保存失败。 标…

Linux操作系统运维-用户与用户组管理

Linux操作系统运维-用户与用户组管理 用户种类与标识查看 超级用户&#xff08;root&#xff09;&#xff1a;可以不受限制地执行所有操作&#xff0c;拥有系统最高权限&#xff0c;修改系统设置与管理用户均需要root权限系统用户&#xff08;system&#xff09;&#xff1a;…