【C语言】——三子棋游戏

news2024/11/25 0:55:27

目录

 Ⅰ.初始页面:

Ⅱ.游戏页面

Ⅲ.玩家下棋

 Ⅳ.电脑下棋

 Ⅴ.判断输赢

结果演示。

 代码整体实现

 1.test.c 

2.game.c

3.game.h 


前言

三子棋是一款非常经典的小游戏,三点一线即为成功,初学代码者,基本上都会接触这款小游戏的实现,本期,为大家献上保姆级实现过程。

游戏思路

1.初始页面:这个页面让用户选择玩或者不玩

2.游戏页面:当进入游戏后,显示初始棋盘

3.玩家下棋:输入下棋位置,打印出棋盘变化

4.电脑下棋:电脑随机在范围内下棋,且打印出棋盘

5.判断输赢每次不管是玩家下棋还是电脑下棋,都进行判断输赢,是否平局,是否满棋

6.回到初始棋盘:当第五步结束后,回到步骤一,是否选择 进入游戏 以及 退出游戏。

 Ⅰ.初始页面:

void menu()    //游戏选择菜单
{
	printf("<-*************************->\n");
	printf("<-******* 1 . play  *******->\n");
	printf("<-******* 0 . exit  *******->\n");
	printf("<-*************************->\n");
	printf("<-*******----------********->\n");

}

菜单是直接映入眼帘的所以我们用do...while()函数比较合适。

int main()
{
	int input = 0;
	do
	{
		menu();  //游戏菜单
		printf("请选择->\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("你已经退出游戏\n");
			break;
		default:
			printf("输入错误,重新选择\n");
			break;
		}
		
	} while (input);
	return 0;
}

Ⅱ.游戏页面

想要获得一个棋盘,首先创建一个相应二位数组,将其封装到头文件中

方便程序的修改,不需要对整个程序修改,提高了运行效率

#define ROW 3
#define COL 3

 接下来对棋盘初始化,最开始存放的是空格,便于初始化,后续的下子也便于观察

//初始化棋盘函数定义
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");
	}
}

Ⅲ.玩家下棋

玩家落子需要在棋盘范围内,玩家要在棋盘上空的地方落子,如果输入的坐标不满足要重新输入,而且玩家下棋的行&列位置和数组下标访问位置 0开始的所不同,所以我们要从1行1列为第一个进行打印。在程序实现就把输入坐标的值 - 1。玩家下棋以‘*’

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

	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; //当成功下棋后,才跳出循环
			}
			else
			{
				printf("该位置已被占有,请重新输入\n");
			}
		}
		else
		{
			printf("输入错误,请重新输入\n");
		}
	}
}

 Ⅳ.电脑下棋

电脑下棋主要是一个随机性,且不能超过棋盘大小。

需要用到rand(),而使用rand()又需要srand()。

因为:rand函数产生的随机数是伪随机数

  srand((unsigned int)time(NULL)); 放在主函数体即可

//电脑随机下棋
void Computerboard(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'
//游戏继续  'C

注意:返回结果的值是字符,所以我们这里要用到字符串 char 返回结果

思路:判断行以及列和对角线相不相等,排除掉空格相等即可。

char IsWin(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 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 (j = 0; j < row; j++)
	{
		if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[0][j] != ' ')
		{
			return board[0][j];
		}
	}
	//判断对角
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] !=' ')
	{
		return board[0][0];
	}

	if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
	{
		return board[0][2];
	}
		
	//判断平局
	if (IsFull(board, row, col))  //为真返回Q,游戏结束
	{
		return 'Q';
	}

	return 'C';	//棋盘没满,继续玩。
}

在判断输赢的时候,有一种情况是特殊的,就是棋盘满了,也需要进行判断,

上面编程中的函数 Isfull(),功能:判断是否平局。

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; //不能玩咯,略略略
}

判断输赢需要在一方下棋后就进行判断

结果演示。

 代码整体实现

 1.test.c 

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include"game.h"

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

}
void game()
{
	char ret;
	char board[ROW][COL];
	//初始化棋盘
	Initboard(board,ROW,COL);
	//展示棋盘
	Displayboard(board, ROW, COL);
	while (1) {
		//玩家下棋
		Playerboard(board, ROW, COL);
		Displayboard(board, ROW, COL);
		//判断输赢
		ret = IsWin(board, ROW, COL);
		if (ret != 'C')  //返回的值不是C为真,说明游戏结束了,
		{
			break;
		}
		//电脑下棋
		Computerboard(board, ROW, COL);
		Displayboard(board, ROW, COL);
		//判断输赢
		ret = IsWin(board, ROW, COL);
		if (ret != 'C')  //返回的值不是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("请选择->\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("你已经退出游戏\n");
			break;
		default:
			printf("输入错误,重新选择\n");
			break;
		}
		
	} while (input);
	return 0;
}

2.game.c

#define _CRT_SECURE_NO_WARNINGS 1
#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 Playerboard(char board[ROW][COL], int row, int col)
{
	printf("请玩家下棋>\n");
	int x = 0;
	int y = 0;

	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; //当成功下棋后,才跳出循环
			}
			else
			{
				printf("该位置已被占有,请重新输入\n");
			}
		}
		else
		{
			printf("输入错误,请重新输入\n");
		}
	}
}

//电脑随机下棋
void Computerboard(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'
//游戏继续  'C

//判断棋盘是否满了
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 IsWin(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 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 (j = 0; j < row; j++)
	{
		if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[0][j] != ' ')
		{
			return board[0][j];
		}
	}
	//判断对角
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] !=' ')
	{
		return board[0][0];
	}

	if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
	{
		return board[0][2];
	}
		
	//判断平局
	if (IsFull(board, row, col))  //为真返回Q,游戏结束
	{
		return 'Q';
	}

	return 'C';	//棋盘没满,继续玩。
}

3.game.h 

#pragma once
#include<time.h>
#include<stdlib.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 Playerboard(char board[ROW][COL], int row, int col);

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

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

以上是我对三子棋游戏代码实现理解,身为初学者,有很多不足,愿得到指点和改善,感激不尽!! 

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

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

相关文章

在项目管理中,项目经理需要了解哪些内容?

在项目管理中&#xff0c;没有绝对的完美&#xff0c;每个项目和项目经理都有可以改进的空间。即使在项目交付时&#xff0c;也会面临各种问题和关系&#xff0c;使得项目经理难以充分应用最佳实践。 项目经理接触项目的第一步是沟通项目的目标&#xff0c;通过与利益相关者的…

论文研读|生成式跨模态隐写发展综述

前言&#xff1a;本文介绍近5年来生成式跨模态隐写领域的相关工作。 相关阅读&#xff1a;生成式文本隐写发展综述 不同于文本隐写&#xff0c;跨模态隐写需要考虑不同模态间的相关性&#xff0c;常见的跨模态场景有&#xff1a;Image-to-Text&#xff08;如图像描述&#xff…

【校招VIP】测试计划之loadrunner分析

考点介绍&#xff1a; LoadRunner&#xff0c;是一种预测系统行为和性能的负载测试工具。通过以模拟上千万用户实施并发负载及实时性能监测的方式来确认和查找问题&#xff0c;LoadRunner能够对整个企业架构进行测试。企业使用LoadRunner能优化性能和加速应用系统的发布周期。校…

C语言 数据结构与算法 I

C语言-数据结构与算法 C语言基础 因为之前写算法都是用C&#xff0c;也有了些C基础&#xff0c;变量常量数据类型就跳过去吧。 首先是环境&#xff0c;学C时候用Clion&#xff0c;C语言也用它写吧~ 新建项目&#xff0c;选C执行文件&#xff0c;语言标准。。。就先默认C99吧…

你折腾一天都装不上的插件,函数计算部署 Stable Diffusion 都内置了

在进行函数计算 Stable Diffusion 答疑的过程中&#xff0c;遇到很多同学在装一些插件的过程中遇到了难题&#xff0c;有一些需要安装一些依赖&#xff0c;有一些需要写一些代码&#xff0c;很多时候安装一个插件就能折腾几天&#xff0c;我们收集了很多同学需要的插件&#xf…

OpenWrt通过终端查询版本

一、cat /etc/banner 二、cat /proc/version 三、cat /etc/openwrt_release 四、uname -a 五、opkg --version

从事网络安全行业 35岁会被淘汰吗?

根据我国信息部门统计显示&#xff1a;今后5年&#xff0c;我国从事网络建设、网络应用和网络服务的新型网络人才&#xff0c;尤其是网络工程师需求将达到60—100万人&#xff0c;而现有符合新型网络人才要求的人还不足20万人。不饱和度高达80%&#xff0c;人才需求量大。 这说…

1065 A+B and C (64bit)

题&#xff1a;点我 题目大意&#xff1a; 这题虽然看着像签到&#xff0c;然鹅签不过去。 因为我最初写的沙雕代码是&#xff1a; #include<iostream> #include<cstdio> using namespace std; int main(void) {int t;scanf("%d", &t);for (int i …

【C++从0到王者】第二十七站:搜索二叉树

文章目录 前言一、二叉搜索树的概念二、二叉搜索树的实现1.二叉树的结点定义2.二叉搜索树的结构3.二叉搜索树的构造函数4.二叉搜索树的插入&#xff08;非递归&#xff09;5.二叉搜索树的中序遍历&#xff08;排序&#xff09;6.二叉搜索树的查找&#xff08;非递归&#xff09…

Excel VSTO开发5 -Excel对象结构

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 5 Excel对象结构 Excel提供了几个比较重要的对象&#xff1a; Application、Workbooks、Workbook、Worksheets、Worksheet 为了便…

for循环命名

for循环命名 一、需求背景二、基本语法三、具体使用 一、需求背景 当我们使用双重循环查找某个目标&#xff0c;找到后想要在内循环跳出整个双重循环&#xff0c;我们可能想到用一个标志位&#xff0c;在外层循环判断到标志位为true时&#xff0c;跳出外层循环。 例如&#xf…

MySQL数据库和表的操作

数据库基础 存储数据用文件就可以了&#xff0c;为什么还要弄个数据库? 文件保存数据有以下几个缺点&#xff1a; 1、文件的安全性问题 2、文件不利于数据查询和管理 3、文件不利于存储海量数据 4、文件在程序中控制不方便 数据库存储介质&#xff1a; 磁盘 内存 为了解决上…

【Spring面试】一、SpringBoot启动优化与最大连接数

文章目录 Q1、SpringBoot可以同时处理多少请求Q2、SpringBoot如何优化启动速度Q3、谈谈对Spring的理解Q4、Spring的优缺点 Q1、SpringBoot可以同时处理多少请求 调试&#xff1a; 写一个测试接口&#xff1a; RestController Slf4j public class RequestController{GetMapping…

找短视频音效、BGM,就上这5个网站

找视频剪辑音效、BGM就上这5个网站下载&#xff0c;免费、付费、商用的全都有&#xff0c;赶紧收藏起来~ 1、菜鸟图库 https://www.sucai999.com/audio.html?vNTYwNDUx 菜鸟图库是一个综合性素材网站&#xff0c;站内涵盖设计、图片、办公、视频、音效等素材。其中音效素材就…

javaee spring整合mybatis spring帮我们创建dao层

项目结构 pom依赖 <?xml version"1.0" encoding"UTF-8"?><project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/P…

Excel VSTO开发4 -其他事件

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 4 其他事件 针对插件的事件主要有Startup、Shutdown这两个事件&#xff0c;在第2节中已经讲解。在开发窗口中&#xff0c;选择对象…

线程的6种状态

线程的6种状态 状态说明new初始状态&#xff1a;线程被创建&#xff0c;但还没有调用start()方法runnable运行状态&#xff1a;Java线程将操作系统中的就绪和运行两种状态笼统的称作“运行”blocked阻塞状态&#xff1a;表示线程阻塞于锁waiting等待状态&#xff1a;表示线程进…

Direct3D颜色

在Direct3D中颜色用RGB三元组来表示&#xff0c;RGB数据可用俩种不同的结构来保存&#xff0c;第一种是D3DCOLOR&#xff0c;它实际上与DWORD类型完全相同&#xff0c;共有32位&#xff0c;D3DCOLOR类型种的各位被分成四个8位项&#xff0c;每项存储了一种颜色分量的亮度值。 由…

U2Net使用方法和实现多类别语义分割模型改造

作者的碎碎念&#xff1a;U2Net是用来实现SOD的语义分割&#xff0c;本篇论文会介绍算法内容、主要代码、使用方法&#xff0c;以及如何将二分类语义分割修改为多类别语义模型。如果只想知道怎么训练自己的数据集&#xff0c;或者如何修改网络&#xff0c;可以通过目录进行跳转…

【C语言】错题本(2)

题目: 将题目代码粘贴在下面便于分析: #define MAX_SIZE AB struct _Record_Struct {unsigned char Env_Alarm_ID : 4;unsigned char Para1 : 2;unsigned char state;unsigned char avail : 1;}*Env_Alarm_Record;struct _Record_Struct *pointer (struct _Record_Struct*)m…