三子棋(c语言)

前言:

三子棋是一种民间传统游戏,又叫九宫棋、圈圈叉叉棋、一条龙、井字棋等。游戏规则是双方对战,双方依次在9宫格棋盘上摆放棋子,率先将自己的三个棋子走成一条线就视为胜利。但因棋盘太小,三子棋在很多时候会出现和棋的局面。

设计思路:

先开一个test.c文件用来进行游戏的逻辑测试,再开一个game.h头文件和game.c文件分别用来进行函数声明和实现游戏的逻辑,然后就是打印菜单、生成棋盘、实现玩家下棋、实现电脑下棋、判断游戏的输赢、游戏优化。

1. 打印菜单

test.c

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

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");
		}
	} while (input);
	return 0;
}

2. 生成棋盘

2.1 初始化棋盘

我们可以用空格将每一个格子初始化。

test.c文件:

board[ROW][COL] = { 0 };
InitBoard(board, ROW, COL);

 game.c文件:

void InitBoard(char board[ROW][COL], int row, int col)
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			board[i][j] = " ";
		}
	}
}

其中的ROW和COL是两个宏定义。

 game.h

#define ROW 3
#define COL 3

2.2 打印棋盘

打印棋盘时我们可以一些符号隔开不同的空格,这样就会使我们的棋盘更加美观。比如我们可以使用“|”将同一行的空格分开,用“-”将不同行的空格分开,这样我们就可以得到一个如下的九宫格了。

 

 game.c文件:

void DisplayBoard(char board[ROW][COL], int row, int col)
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			printf("   ");
			if (j < col - 1)
			{
				printf("|");
			}
		}
		printf("\n");
		if (i < row - 1)
		{
			for (int j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)
					printf("|");
			}
			printf("\n");
		}
	}
}

 3. 实现玩家下棋和电脑下棋

为了游戏的可实行性,当玩家或电脑下完一个棋子后我们需要考虑以下两点:

1.玩家或电脑所下的坐标是否在棋盘的范围内。

2.玩家或电脑所下的位置是否已经被下过棋子了。

依据上面的两点条件的我们需要分别写一个条件语句,判断玩家是否合法下棋。

3.1 玩家下棋

game.c文件:

void PlayerMove(char board[ROW][COL], int row, int col)
{

	int x = 0, 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");
		}
	}
}

3.2 电脑下棋

思路: 

我们可以在让电脑生成随机数,这样就可以使其随机生成一个坐标下棋子,那么我们就可以简单的实现电脑下棋的效果了。

随机数的生成则可以使用rand函数、srand函数以及time函数。

game.c文件:

void ComputerMove(char board[ROW][COL], int row, int col)
{
	printf("电脑下棋:>\n");
	while (1)
	{
		int x = rand() % row;
		int y = rand() % row;
		if (x <= row && x >= 1 && y <= row && y >= 1)
		{
			if (board[x][y] == ' ')
			{
				board[x][y] = '#';
				break;
			}
		}
		
	}
}

test.c文件:

srand((unsigned int)time(UNLL))

game.h文件:

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

为了实现玩家下一个棋,然后电脑下一个棋的功能我们还需加上一个while循环。如下:

test.c文件:

while(1)
{
	//玩家下棋
	PlayerMove(board, ROW, COL);
	DisplayBoard(board, ROW, COL);
	//电脑下棋
	ComputerMove(board, ROW, COL);
	DisplayBoard(board, ROW, COL);
}

 4. 判断游戏的输赢

 思路:

此游戏无非只有三种结果:要么玩家赢,要么电脑赢,要么平局。所以我们可以写一个函数判断是这几种结果的哪一种,然后规定如果是玩家赢此函数返回“*”,如果是电脑赢则返回“#”,平局则返回“Q”,这几种都不是就说明游戏继续,那么就返回“C”.

要判断是否有赢的一方,无非就是判断是否出现了三个相同的棋子练成一条直线,而棋子连成的线无非就只有三种情况:竖线、横线、对角线。所以我们只需要判断是否出现了这三种情况的其中一种就可以了。而要判断是平局,则判断九宫格是否还有没有空格。

game.c文件:

int ItFull(char board[ROW][COL], int row, int col)
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0;j < col; j++)
		{
			if (board[i][j] == ' ')
			{
				return 0;
			}
		}
	}
	return 1;
}
char ItWin(char board[ROW][COL], int row, int col)
{
	//行
	for (int i = 0; i < row; i++)
	{
		if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][2] != ' ')
			return board[i][1];
	}
	//列
	for (int j = 0; j < col; j++)
	{
		if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[2][j] != ' ')
			return board[1][j];
	}
	//对角线
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[2][2] != 0)
	{
		return board[1][1];
	}
	if (ItFull(board, row, col))
	{
		return 'Q';
	}
	return 'C';
}

test.c文件:

	//玩家下棋
	PlayerMove(board, ROW, COL);

	DisplayBoard(board, ROW, COL);
	//判断输赢
	char ret = ItWin(board, ROW, COL);
	if (ret != 'C')
	{
		if (ret == '*')
		{
			printf("玩家赢了!!!\n");
		}
		break;
	}
	//电脑下棋
	ComputerMove(board, ROW, COL);

	DisplayBoard(board, ROW, COL);
	//判断输赢
	ItWin(board, ROW, COL);
	if (ret != 'C')
	{
		if (ret == '#')
		{
			printf("电脑赢了!!!\n");
		}
		break;
	}

完整代码:

game.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 ItWin(char board[ROW][COL], int row, int col);

test.c文件:

#include"game.h"

void menu()
{
	printf("***************************\n");
	printf("********   1.play  ********\n");
	printf("********   2.exit  ********\n");
	printf("***************************\n");
}
void game()
{
	//第一步打印棋盘。
	char board[ROW][COL] = { 0 };
	//初始化棋盘
	InitBoard(board, ROW, COL);
	//打印棋盘
	DisplayBoard(board, ROW, COL);
	char ret;
	while(1)
	{
		
		//玩家下棋
		PlayerMove(board, ROW, COL);

		DisplayBoard(board, ROW, COL);
		//判断输赢
		char ret = ItWin(board, ROW, COL);
		if (ret != 'C')
		{
			if (ret == '*')
			{
				printf("玩家赢了!!!\n");
			}
			break;
		}
		//电脑下棋
		ComputerMove(board, ROW, COL);

		DisplayBoard(board, ROW, COL);
		//判断输赢
		ItWin(board, ROW, COL);
		if (ret != 'C')
		{
			if (ret == '#')
			{
				printf("电脑赢了!!!\n");
			}
			break;
		}
	}
}
int main()
{
	srand((unsigned int)time(NULL));
	int input = 0;
	
	do
	{
		menu();
		printf("请选择>:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏.\n");
			break;
		default:
			printf("输入有误,请重新输入.\n");
		}
	} while (input);
	return 0;
}

game.c文件:

#include"game.h"

void InitBoard(char board[ROW][COL], int row, int col)
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			board[i][j] = ' ';
		}
	}
}

void DisplayBoard(char board[ROW][COL], int row, int col)
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			printf(" %c ",board[i][j]);
			if (j < col - 1)
				printf("|");
		}
		printf("\n");
		if (i < row - 1)
		{
			for (int 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, 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");
	while (1)
	{
		int x = rand() % row;
		int y = rand() % row;
		if (x <= row && x >= 1 && y <= row && y >= 1)
		{
			if (board[x][y] == ' ')
			{
				board[x][y] = '#';
				break;
			}
		}
		
	}
}

int ItFull(char board[ROW][COL], int row, int col)
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0;j < col; j++)
		{
			if (board[i][j] == ' ')
			{
				return 0;
			}
		}
	}
	return 1;
}
char ItWin(char board[ROW][COL], int row, int col)
{
	//行
	for (int i = 0; i < row; i++)
	{
		if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][2] != ' ')
			return board[i][1];
	}
	//列
	for (int j = 0; j < col; j++)
	{
		if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[2][j] != ' ')
			return board[1][j];
	}
	//对角线
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[2][2] != 0)
	{
		return board[1][1];
	}
	if (ItFull(board, row, col))
	{
		return 'Q';
	}
	return 'C';
}

运行图:

游戏优化: 

让电脑生成一个数的方式来实现一个电脑下棋的效果,肯定是没有什么可玩性的,等后面学习算法之后,我们就加入一些算法将其变为一个棋艺高超的棋手了。

以上就是使用c语言写三子棋的全部内容啦,如果上述内容对你有帮助的话不要忘记点上一个小小的赞和关注呦,期待我们下次再见。

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

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

相关文章

Linux xxd命令分析视频文件Box教程(box分析box、视频box、分析atom分析)(xdd指令)

文章目录 Linux xxd命令分析视频文件Box教程一、理解MP4格式二、xxd命令简介三、使用xxd命令分析MP4文件四、解析MP4文件的疑难点1. Box的嵌套结构2. 长度和类型字段的字节序3. 非文本类型的数据 五、python代码解析box嵌套结构的示例 Linux xxd命令分析视频文件Box教程 本文主…

AlignBench:量身打造的中文大语言模型对齐评测

对齐&#xff08;Alignment&#xff09;&#xff0c;是指大语言模型&#xff08;LLM&#xff09;与人类意图的一致性。换言之&#xff0c;就是让LLM生成的结果更加符合人类的预期&#xff0c;包括遵循人类的指令&#xff0c;理解人类的意图&#xff0c;进而能产生有帮助的回答等…

2023博客年终总结、你好2024

2023博客年终总结、你好2024 1、2023博客年终总结2、你好2024 1、2023博客年终总结 2023写了100篇博客&#xff0c;祝愿我们的人生都能圆满达到100分。 2023行将结束&#xff0c;有幸接触了一本书 《你怎样过一天&#xff0c;就怎样过一生》 作者 七纤 2、你好2024 你好2024…

如何修改Anaconda的Jupyter notebook的默认启动路径

1.打开Anaconda控制台 2.输入下面的命令 jupyter notebook --generate-config 这个命令的作用是生成 Jupyter notebook 的配置文件。如果你是第一次运行&#xff0c;会直接生成这个文件。如果曾经运行过这个命令&#xff0c;就会像下图一样问你时候要覆盖原来的文件。这个时候…

状态模式-概述

在软件系统中&#xff0c;有些对象也像水一样具有多种状态&#xff0c;这些状态在某些情况下能够相互转换&#xff0c; 而且对象在不同的状态下也将具有不同的行为。相同的方法在不同的状态中可能会有不同的实现。 为了实现不同状态下对象的各种行为以及对象状态之间的相互转换…

PHP序列化总结3--反序列化的简单利用及案例分析

反序列化中生成对象里面的值&#xff0c;是由反序列化里面的值决定&#xff0c;与原类中预定义的值的值无关&#xff0c;穷反序列化的对象可以使用类中的变量和方法 案例分析 反序列化中的值可以覆盖原类中的值 我们创建一个对象&#xff0c;对象创建的时候触发了construct方…

Java多线程<三>常见的多线程设计模式

多线程的设计模式 两阶段线程终止 park方法 interrupted() 会让他失效。 使用volatile关键字进行改写 单例模式 双锁检测 保护性暂停 实现1&#xff1a; package threadBase.model;/*** author: Zekun Fu* date: 2022/5/29 19:01* Description:* 保护性暂停&#xff0c;* …

HarmonyOS4.0系统性深入开发09卡片使用动效能力

卡片使用动效能力 ArkTS卡片开放了使用动画效果的能力&#xff0c;支持显式动画、属性动画、组件内转场能力。需要注意的是&#xff0c;ArkTS卡片使用动画效果时具有以下限制&#xff1a; 名称参数说明限制描述duration动画播放时长限制最长的动效播放时长为1秒&#xff0c;当…

5天一更新的卫星影像数据来自哪里?

这里我们就来分享一下&#xff0c;5天一更新的卫星影像源来自哪里。 哥白尼计划 在开始讲卫星影像数据源时&#xff0c;我们先来了解一下什么是哥白尼计划。 哥白尼计划&#xff08;Copernicus Programme&#xff09;&#xff0c;又称全球环境与安全监测计划&#xff08;Glo…

用通俗易懂的方式讲解大模型:LangChain Agent 原理解析

LangChain 是一个基于 LLM&#xff08;大型语言模型&#xff09;的编程框架&#xff0c;旨在帮助开发人员使用 LLM 构建端到端的应用程序。它提供了一套工具、组件和接口&#xff0c;可以简化创建由 LLM 和聊天模型提供支持的应用程序的过程。 LangChain 由几大组件构成&#…

【前端技术】LocalForage数据存储

✨专栏介绍 在当今数字化时代&#xff0c;Web应用程序已经成为了人们生活和工作中不可或缺的一部分。而要构建出令人印象深刻且功能强大的Web应用程序&#xff0c;就需要掌握一系列前端技术。前端技术涵盖了HTML、CSS和JavaScript等核心技术&#xff0c;以及各种框架、库和工具…

pytorch01:概念、张量操作、线性回归与逻辑回归

目录 一、pytorch介绍1.1pytorch简介1.2发展历史1.3pytorch优点 二、张量简介与创建2.1什么是张量&#xff1f;2.2Tensor与Variable2.3张量的创建2.3.1 直接创建torch.tensor()2.3.2 从numpy创建tensor 2.4根据数值创建2.4.1 torch.zeros()2.4.2 torch.zeros_like()2.4.3 torch…

windTerm 连接一段时间之后自动断开

默认是关闭会话空闲保活功能的&#xff0c;如所连接的SSH服务没做连接保活&#xff0c; 就很可能超时自动断开 开启会话保活 在 会话 -> 首选项 -> Default Session Settings -> SSH -> 连接 -> 发送空包以保持会话活动 设置15&#xff0c;即15秒自动发空包保…

YOLOv8改进 添加可变形注意力机制DAttention

一、Deformable Attention Transformer论文 论文地址&#xff1a;arxiv.org/pdf/2201.00520.pdf 二、Deformable Attention Transformer注意力结构 Deformable Attention Transformer包含可变形注意力机制&#xff0c;允许模型根据输入的内容动态调整注意力权重。在传统的Tra…

pytorch03:transforms常见数据增强操作

目录 一、数据增强二、transforms--Crop裁剪2.1 transforms.CenterCrop2.2 transforms.RandomCrop2.3 RandomResizedCrop2.4 FiveCrop和TenCrop 三、transforms—Flip翻转、旋转3.1RandomHorizontalFlip和RandomVerticalFlip3.2 RandomRotation 四、transforms —图像变换4.1 t…

[Angular] 笔记 23:Renderer2 - ElementRef 的生产版本

chatgpt: Renderer2 简介 在 Angular 中&#xff0c;Renderer2 是一个服务&#xff0c;用于处理 DOM 操作的抽象层。它提供了一种安全的方式来操作 DOM&#xff0c;同时与平台无关&#xff0c;有助于维护应用程序的跨浏览器兼容性和安全性。 Renderer2 的作用是在 Angular 组…

【vim 学习系列文章 3.1 -- vim 删除 ^M】

请阅读【嵌入式开发学习必备专栏 之 VIM 专栏】 文章目录 ^M 来源^M 删除 ^M 来源 在 Vim 中打开文件时&#xff0c;您可能会遇到行尾的 ^M 字符&#xff0c;这通常是因为文件使用了 Windows 风格的回车换行符&#xff08;CRLF&#xff09;&#xff0c;而不是 Unix/Linux 风格…

集合基础知识点

集合基础 1. 集合的由来 当 Java 程序中需要存放数据的时候&#xff0c;通常会定义变量来实现数据的存储&#xff0c;但是&#xff0c;当需要存储大量数据的时候该怎么办呢&#xff1f;这时首先想到的是数组&#xff0c;但是&#xff01;数组只能存放同一类型的数据&#xff…

【计算机网络】第五,六章摘要重点

1.运输层协议概述 运输层提供的是进程之间的通信 2. 3.套接字指的是什么 ip地址端口号 4.每一条TCP语句唯一地被通信两端连接的两个端点 5.TCP传输如何实现 以字节为单位的滑动窗口 超时重传 选择确认 6.TCP流量控制和拥塞控制的区别 流量控制&#xff1a;点对点通信…

Android Studio如何创建尺寸大小及API通用的模拟器

目录 前言 一、操作步骤 二、总结 三、更多资源 前言 在开发移动应用程序的过程中&#xff0c;使用模拟器进行测试是一种常见和方便的方式。Android Studio是一款功能强大的集成开发环境&#xff0c;它提供了创建和管理模拟器的功能。在本文中&#xff0c;我们将介绍如何创…