三子棋(超详解+完整码源)

三子棋

    • 前言
    • 一,游戏规则
    • 二,所需文件
    • 三,创建菜单
    • 四,游戏核心内容实现
      • 1.棋盘初始化
      • 1.棋盘展示
      • 3.玩家下棋
      • 4.电脑下棋
      • 5.游戏胜负判断
      • 6.game()函数内部具体实现
    • 四,游戏运行实操

前言

C语言实现三子棋是对大家对数组,函数,循环与分支等内容的考察。通过本篇文章你将学会如何制作出三子棋,坚持一段时间的复习相信你肯定能够掌握三子棋**(文末附三子棋全部代码).**
在这里插入图片描述

一,游戏规则

设计游戏前先了解三子棋基本规则,以围绕规则用C语言实现

1、人机双方轮流在格子里落子棋子,先连成三棋一线者视为胜利

2、棋盘被摆满棋子仍未分出胜利,视为平局
在这里插入图片描述

二,所需文件

三子棋并不是一项容易的代码,需要我们进行分文件编写。
什么是分文件编写?

就是把我们的程序代码划分成多个文件,这样就不会把所有的代码都放在main.c里面,采用分模块的编程思想,进行功能划分,把每个功能不一样的单独放在一个c文件里,然后写头文件把它封装成可调用的一个函数,在主函数调用这个封装好的函数,编译的时候一起编译即可

好处:

a.功能责任划分
b.方便调试
c.主程序简洁

来让给我们看看具体操作如下:
头文件中创建game.h ----用来声明函数
源文件中创建game.c—函数具体实现 / test.c—主题流程
在这里插入图片描述

三,创建菜单

先创建一个菜单以展示进入退出游戏功能:

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

用do…while循环实现菜单使用,switch语句进行菜单选择

int main()
{
	int input = 0;
	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;
}

四,游戏核心内容实现

game()函数中实现整个游戏,先数组棋盘


char board[ROW][COL];

1.棋盘初始化

在game.h中定义行和列为3

#define ROW 3
#define COL 3

在game.h中声明初始化函数Initboard

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

在game.c中实现初始化函数,创造三行三列的空格

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

期盼初始化完成。

1.棋盘展示

初始化完棋盘需要将棋盘打印在键盘上
在game.文件中声明打印棋盘

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

在game.c文件中实现棋盘打印函数

void DisplayBoard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 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");
	}
}

棋盘打印完成

3.玩家下棋

在game.h声明玩家下棋函数

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

在game.h中实现玩家下棋函数。玩家所在下棋子不能出棋盘否则坐标非法重新下,所下棋子必须在无棋子格子中否则坐标备占有重新下,while实现玩家下错棋子重新下直到下正确退出循环

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] == ' ')//数组下标从0开始所以横纵坐标各减一
			{
				board[x - 1][y - 1] = '*';
				break;
			}
			else
			{
				printf("该坐标被占有,请输入其他坐标\n");
			}
		}
		else
		{
			printf("坐标非法,请重新输入\n");
		}
	}
}

玩家下棋完成。

4.电脑下棋

在game.h声明电脑下棋函数

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

在game.c文件中实现电脑下棋函数。电脑随机下棋需要随机坐标引头文件#include <stdlib.h>,随机数生成需要头文件#include <time.h>。将电脑所下棋控制在棋盘内然后判断是否下在空棋盘内否则重下,while实现玩家下错棋子重新下直到下正确退出循环

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;
		}
	}
}

5.游戏胜负判断

在game.h中声明胜负判断函数。

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

在game.c中实现胜负判断函数。每次下棋结果共有四种1.玩家嬴2.电脑嬴3.平局4.继续游戏,
for循环实现行列三点成直线,if判断玩家或电脑三点成直线打印‘ * ’或‘ # ’

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] == board[i][0] && board[i][2] != ' ')//行连成线
		{
			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] == board[2][i] && board[0][i] != ' ')//列连成线
		{
			return board[i][0];
		}
	}
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] == board[2][2] && board[0][0] != ' ')//斜方连成线
	{
		return board[0][0];
	}
	if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[0][2] == board[2][0] && board[1][1] != ' ')//斜方连成线
	{
		return board[1][1];
	}
	if (isFull(board, ROW, COL))
	{
		return 'Q';
	}
	return 'C';
}

嵌套平局函数在game.h中。若所有坐标被占满(坐标都不为空)平局函数返回真,判断胜负函数返回Q平局。若坐标有空,平局函数返回假,在判断胜负函数中返回C继续游戏

static 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;
}

6.game()函数内部具体实现

创建数组char board[ROW][COL];,调用初始化棋盘(Initboard(board, ROW, COL))和打印棋盘(Displayboard(board, ROW, COL))函数,while循环实现电脑和玩家相互下棋用ret接受胜负结果,如果不是继续游戏(C)则跳出循环。若结果为玩家(*)则玩家嬴,若结果为电脑(#)则电脑应,否则结果为平局。

void game()
{
	int ret = 0;
	char board[ROW][COL];
	Initboard(board, ROW, COL);
	Displayboard(board, ROW, COL);
	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
	{
		printf("平局\n");
	}
}

四,游戏运行实操

1.运行程序,出现菜单
在这里插入图片描述
1.选择1开始玩游戏,出现棋盘
在这里插入图片描述
2.输入下棋位置开始下棋:
在这里插入图片描述
3.棋子没有落在空位置,重新下棋
在这里插入图片描述
4出现三点成直线,获得胜利
在这里插入图片描述
5若棋盘下满,则平局
在这里插入图片描述
6.选择0,退出游戏
在这里插入图片描述

完整代码:

game.h

#pragma once

#include <stdio.h>
#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 Playermove(char board[ROW][COL], int row, int col);
//电脑下棋
void Computermove(char board[ROW][COL], int row, int col);
//判断输赢
char IsWin(char board[ROW], int row, int col);

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 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 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] == board[i][0] && board[i][2] != ' ')
		{
			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] == board[2][i] && board[0][i] != ' ')
		{
			return board[i][0];
		}
	}
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] == board[2][2] && board[0][0] != ' ')
	{
		return board[0][0];
	}
	if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[0][2] == board[2][0] && board[1][1] != ' ')
	{
		return board[1][1];
	}
	if (isFull(board, ROW, COL))
	{
		return 'Q';
	}
	return 'C';
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
//创建菜单
void menu()
{
	printf("**********************\n");
	printf("******  1.play  ******\n");
	printf("******  0.exit  ******\n");
	printf("**********************\n");
}
//创建游戏
void game()
{
	int ret = 0;
	char board[ROW][COL];
	Initboard(board, ROW, COL);
	Displayboard(board, ROW, COL);
	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
	{
		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;
}

本次三子棋学习告一段落,三子棋详解+完整代码,反复阅读,坚持打码,相信你在不久的将来就会拿下三子棋,以扩展更高级代码。期待下次作品与大家见面!!!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

maven

一、为什么需要使用maven 如今我们构建一个项目需要用到很多第三方的类库 &#xff0c;例如我们在开发项目中 需要引入 这些依赖jar包 一个项目Jar包的数量之多往往让我们瞠目结舌&#xff0c;并且Jar包之间的关系非常复杂&#xff0c;一个Jar包往往又会引用其他Jar包&#x…

安全学习DAY07_其他协议抓包技术

协议抓包技术-全局-APP&小程序&PC应用 抓包工具-Wireshark&科来分析&封包 TCPDump&#xff1a; 是可以将网络中传送的数据包完全截获下来提供分析。它支持针对网络层、协议、主机、网络或端口的过滤&#xff0c;并提供and、or、not等逻辑语句来帮助你去掉无用…

stable diffusion如何确保每张图的面部一致?

可以使用roop插件&#xff0c;确定好脸部图片后&#xff0c;使用roop固定&#xff0c;然后生成的所有图片都使用同一张脸。 这款插件的功能简单粗暴&#xff1a;一键换脸。 如图所示&#xff1a; 任意上传一张脸部清晰的图片&#xff0c;点击启用。 在其他提示词不变的情况下…

赛多利斯Sartorius天平java后端对接

业务场景 要将赛多利斯天平的数据读出来解析并且显示到对应的数字框,支持一台设备连接多种精度的天平 后端实现 通过协议解析数据,然后将数据存储 详细代码就不贴了,感兴趣的可以私聊我

GPT-AI 使用的技术概览

ChatGPT 使用的技术概览 智心AI-3.5/4模型&#xff0c;联网对话&#xff0c;MJ快速绘画 从去年 OpenAI 发布 ChatGPT 以来&#xff0c;AI 的能力再次惊艳了世人。在这样的一个时间节点&#xff0c;重新去学习相关技术显得很有必要。 ChatGPT 的内容很多&#xff0c;我计划采用…

3ds Max图文教程: 创建致命的冠状病毒动画

推荐&#xff1a; NSDT场景编辑器助你快速搭建可二次开发的3D应用场景 1. 病毒建模 步骤 1 打开 3ds Max。 打开 3ds Max 步骤 2 在透视视口中创建一个半径为 50&#xff0c;线段为 20 的 GeoSphere。 创建地球 步骤 3 打开修改器列表并将置换修改器应用于地理 球。 置换…

Linux系统MySQL中用户的权限管理

本节主要学习用户权限管理的概述&#xff0c;用户权限类型&#xff0c;用户赋权&#xff0c;权限删除&#xff0c;用户删除等。 目录 一、概述 二、用户权限类型 三、用户赋权 四、权限删除 五、用户删除 一、概述 数据库用户权限管理是数据库系统中非常重要的一个方面&am…

Dockerfile 创建镜像,构建LNMP+wordpress架构

目录 一、Dockerfile 构建镜像 1.Dockerfile 构建 nginx镜像 1.1创建 nginx Dockerfile 目录 1.2编写 Dockerfile 文件 1.3构建nginx镜像 2.Dockerfile 构建 mysql 镜像 2.1创建 mysql Dockerfile 目录 2.2修改mysql配置文件 2.3编写 Dockerfile 文件 2.4构建mysql镜…

ChatGPT伦理挑战:人工智能的权利与责任

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

全志F1C200S嵌入式驱动开发(触摸屏驱动)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 触摸屏一般有两种,一种是电阻触摸屏,一种是电容触摸屏。前者需要自己买一颗i2c的信号读取芯片,用的比较多的是ns2009。后者自身集成了读取芯片,用的比较多的是gt911。正好之前测…

(十三)定时任务

以下内容来自 尚硅谷&#xff0c;写这一系列的文章&#xff0c;主要是为了方便后续自己的查看&#xff0c;不用带着个PDF找来找去的&#xff0c;太麻烦&#xff01; 第 13 章 定时任务 13.1 什么是定时任务 1、InfluxDB任务是一个定时执行的FLUX脚本&#xff0c;它先查询数据…

Docker啥是数据持久化?

文章目录 数据持久化数据卷相关命令创建读写数据卷创建只读数据卷数据卷共享数据卷容器实现数据卷共享nginx实现数据卷共享nfs总结 Dockerfile持久化Dockerfile方式docker run总结 数据持久化 ​ 在容器层的 UnionFS&#xff08;联合文件系统&#xff09;中对文件/目录的任何修…

SRC | 逻辑漏洞原理及实战

前言 作者简介&#xff1a;不知名白帽&#xff0c;网络安全学习者。 博客主页&#xff1a;不知名白帽_网络安全,CTF,内网渗透-CSDN博客 网络安全交流社区&#xff1a;https://bbs.csdn.net/forums/angluoanquan 目录 逻辑漏洞基础 概述 分类 URL跳转漏洞 概述 危害 漏洞…

Android:RecyclerView封装,打造列表极简加载

前言 mBinding.recycler.linear().divider().set<OrdinaryListBean> {addLayout(R.layout.layout_ordinary_item)}.setList(getList()) 如果我要说&#xff0c;除了数据和布局之外&#xff0c;以上的几行代码&#xff0c;就实现了一个列表加载&#xff0c;有老铁会相信…

Django学习笔记-表单(forms)的使用

在Django中提供了了form表单&#xff0c;可以更为简单的创建表单模板信息&#xff0c;简化html的表单。 一、网页应用程序中表单的应用 表单通常用来作为提交数据时候使用。 1.1 创建表单模板文件夹 在项目文件夹下创建一个template文件夹&#xff0c;用于存储所有的html模…

XCP详解「总目录」

目录 XCP详解「总目录」 1 概览 2 理论 3 实践 4 其他 XCP详解「总目录」 基础学习&#xff0c;慢慢补充 1 概览 2 理论 3 实践 XCP详解「3.1ASAP2新建A2L文件」 XCP详解「3.2CANape新建工程导入A2L」 XCP详解「3.3A2L信号添加和更新」 XCP详解「3.4CANape中新建A2L文…

学习 C语言第二天 :C语言数据类型和变量(下)

目录&#xff1a; 1.变量的介绍以及存储 2.算术操作符、赋值操作符、单目操作符 3.scanf和printf的介绍 1.变量的介绍以及存储 1.1.变量的创建 了解了什么是类型了&#xff0c;类型是用来创建变量的。 变量是什么呢&#xff1f;在C语言当中不经常变的量称为常量&#xff0c;经常…

Qt : day1

1.聊天界面 #include "widget.h"Widget::Widget(QWidget *parent): QWidget(parent) {qDebug() << this->size(); //获取当前页面尺寸this->setFixedSize(500, 600); //设置固定尺寸this->setWindowTitle("聊天框"); //设置窗口…

OpenAI Code Interpreter 的开源实现:GPT Code UI

本篇文章聊聊 OpenAI Code Interpreter 的一众开源实现方案中&#xff0c;获得较多支持者&#xff0c;但暂时还比较早期的项目&#xff1a;GPT Code UI。 写在前面 这篇文章本该更早的时候发布&#xff0c;但是 LLaMA2 发布后实在心痒难忍&#xff0c;于是就拖了一阵。结合 L…

mybatisPlus入门篇

文章目录 初窥门径1.1 初识MybatisPlus1.2 MybatisPlus的特性1.3 MybatisPlus的架构模型 入门案例2.1 准备相关开发环境2.2 搭建springboot工程2.3 创建数据库2.4 引入相关依赖2.5 创建实体类2.6 集成MybatisPlus2.7 单元测试2.8 springboot日志优化 初窥门径 1.1 初识Mybatis…