[C语言]连子棋游戏

文章目录

  • 一、前言
  • 二、游戏思路
  • 三、游戏方法
    • 1、初始化
    • 2、判断胜利
    • 3、交互
    • 4、电脑下棋
  • 四、核心方法说明
    • 1、初始化游戏
    • 2、销毁棋盘
    • 3、显示游戏
    • 4、电脑下棋
    • 5、用户下棋
    • 6、判断游戏状态
    • 7、游戏交互
  • 五、游戏效果展示与源码分享
    • 1、游戏效果
    • 2、源代码

一、前言

对于指针和数组理解尚不深入的读者,我们强烈建议您先通过以下链接进行学习,以便更好地理解和参与后续的连子棋游戏讨论:传送门。这些基础知识将为您搭建连子棋游戏框架提供坚实的支撑。


二、游戏思路

我们的连子棋游戏将基于经典的五子棋规则进行开发:传送门。

  • 游戏中,玩家和电脑将分别使用黑色和白色的棋子进行轮流下棋。
  • 当某一方的棋子能够在横向、纵向或斜向上连成连续的指定个数棋子时,该方即获得胜利。
  • 用户可以在前面选择游戏连子数量(四子以上)。

三、游戏方法

1、初始化

在游戏开始前,我们需要进行一系列初始化操作,包括创建游戏棋盘(通常使用二维数组表示),并初始化棋盘上的每个位置为空(表示尚未放置棋子)。此外,还需要设置当前玩家为黑方,并准备接收玩家的输入。

2、判断胜利

每当玩家在棋盘上放置一枚棋子后,我们需要遍历棋盘以检查是否存在已经连成了胜利所需的棋子串。这通常涉及到对棋盘进行多次遍历,分别检查横向、纵向和斜向上的棋子连续性。

3、交互

游戏过程中,玩家将通过标准输入(如键盘)来输入棋子的放置位置(通常是棋盘的行列坐标)。程序需要接收这些输入,并验证其有效性(确保坐标在棋盘范围内且该位置尚未放置棋子)。然后,程序将根据输入更新棋盘状态,并再次检查是否获得胜利。

4、电脑下棋

为了实现单人游戏模式,我们还需要为电脑玩家实现一个下棋算法。这通常涉及到一些人工智能算法的应用,如随机下棋、简单策略判断或更复杂的搜索算法(如蒙特卡洛树搜索)。在实现时,我们可以根据游戏复杂度和性能要求来选择合适的算法。


四、核心方法说明

1、初始化游戏

/*
 * 初始化连子棋游戏
 * @param board 指向存储游戏棋盘的指针的指针
 * @param row 棋盘的行数
 * @param col 棋盘的列数
 */
void init_board(char*** board, int row, int col)
{
    //开辟棋盘
	*board = (char**)malloc(sizeof(char*) * row);
	if (!(*board))
	{
		fprintf(stderr, "内存分配失败\n");
		exit(EXIT_FAILURE);
	}

	for (int i = 0; i < row; i++)
	{
		(*board)[i] = (char*)malloc((col + 2) * sizeof(char));
		if ((*board)[i] == NULL)
		{
			fprintf(stderr, "内存分配失败\n");
			//释放之前已分配的内存
			for (int j = 0; j < i; j++)
			{
				free((*board)[j]);
			}
			free(*board);
			exit(EXIT_FAILURE);
		}
	}

    //初始化棋盘
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
            (*board)[i][j] = ' ';
		}
	}
}

2、销毁棋盘

/*
 * 销毁连子棋棋盘
 * @param board 指向存储游戏棋盘的指针的指针
 * @param row 棋盘的行数
 * @param col 棋盘的列数
 */
void free_board(char*** board, int row, int col)
{
	assert(board != NULL);

    //销毁每一行
	for (int i = 0; i < row; i++)
	{
        free((*board)[i]);
	}
	//销毁指针数组
	free(*board);
    *board = NULL;
}

3、显示游戏

/*
 * 显示连子棋游戏
 * @param board 游戏棋盘
 * @param row 棋盘的行数
 * @param col 棋盘的列数
 */
void show_board(char** board, int row, int col)
{
	assert(board != NULL);

    //打印列标
	for (int i = 0; i <= col; i++)
		printf("%d ", i);
	printf("\n");

	for (int i = 0; i < row; i++)
	{
		printf("%d ", i + 1);//打印行标

		for (int j = 0; j < col; j++)
		{
		    //不同颜色显示棋子
            if (board[i][j] == '*')
                printf("\033[1;31m*\033[0m ");
			else if (board[i][j] == '#')
                printf("\033[1;33m*\033[0m ");
            else
				printf("%c ", board[i][j]);
		}
		printf("\n");
	}
}

4、电脑下棋

/*
 * 电脑下棋
 * @param board 指向存储游戏棋盘的指针的指针
 * @param row 棋盘的行数
 * @param col 棋盘的列数
 * @param sum 连子个数
 * @return 游戏状态
 */
int computer_play(char*** board, int row, int col, int sum)
{
start:
	assert(board != NULL);
	//电脑随机下棋
    int x = rand() % row + 1;
    int y = rand() % col + 1;

	if ((*board)[x - 1][y - 1] == ' ')
	{
        (*board)[x - 1][y - 1] = '*';
	}
	else
	{
		goto start;
	}

	return is_win(*board, row, col, sum, x, y);
}

5、用户下棋

/*
 * 用户下棋
 * @param board 指向存储游戏棋盘的指针的指针
 * @param row 棋盘的行数
 * @param col 棋盘的列数
 * @param sum 连子个数
 * @return 游戏状态
 */
int user_play(char*** board, int row, int col, int sum)
{
start:
	assert(board != NULL);
	int x = -1, y = -1;

	printf("请选择下棋点(x,y):");
	scanf("%d,%d", &x, &y);

	if (clear_input())
	{
		x = -1, y = -1;
	}

	if ((x < 1 || x > row || y < 1 || y > col) || (*board)[x - 1][y - 1] != ' ')
	{
		system("cls");
		printf("输入错误!\n");
		getchar();
		system("cls");
		show_board(*board, row, col);
		goto start;
	}

	(*board)[x - 1][y - 1] = '#';

	return is_win(*board, row, col, sum, x, y);
}

6、判断游戏状态

/*
 * 判断是否连续sum个
 * @param board 游戏棋盘
 * @param row 棋盘的行数
 * @param col 棋盘的列数
 * @param sum 连子个数
 * @param x 当前下棋的行
 * @param y 当前下棋的列
 * @param dx 判断偏移x方向
 * @param dy 判断偏移y方向
 * @return 是否连续sum个
 */
int is_sum(char** board, int row, int col, int sum, int x, int y, int dx, int dy)
{
	assert(board != NULL);
	assert(x >= 1 && x <= row && y >= 1 && y <= col);

	char flag = board[x - 1][y - 1];
	int count = 0;

	for (int i = -(sum - 1); i < sum; i++)
	{
		int nx = x + dx * i;
		int ny = y + dy * i;
		if (nx >= 1 && nx <= row && ny >= 1 && ny <= col)
		{
			if (board[nx - 1][ny - 1] == flag)
			{
				count++;
				if (count == sum)
                    return 1;
			}
			else
			{
				count = 0;
			}
		}
	}

	return 0;
}

/*
 * 判断是否结束
 * @param board 游戏棋盘
 * @param row 棋盘的行数
 * @param col 棋盘的列数
 * @param sum 连子个数
 * @param x 当前下棋的行
 * @param y 当前下棋的列
 * @return 游戏状态
 */
int is_win(char** board, int row, int col, int sum, int x, int y)
{
	assert(board != NULL);
	assert(x >= 1 && x <= row && y >= 1 && y <= col);

	int direxction[4][2] = { {-1, 0}, {-1, 1}, {0, 1}, {1, 1} };
	for (int i = 0; i < 4; i++)
	{
		if (is_sum(board, row, col, sum, x, y, direxction[i][0], direxction[i][1]))
		{
			return board[x - 1][y - 1] == '*' ? -1 : 1;
		}
	}

	//是否平局
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
            if (board[i][j] == ' ')
                return sum;
		}
	}
	return 0;
}

7、游戏交互

/*
 * 清除标准输入缓冲区中直到换行符的所有字符,并返回一个标志位。
 * @return 如果缓冲区中有字符被清除,则返回1;否则返回0。
 */
int clear_stdin(void)
{
    int flag = 0;
    while (getchar() != '\n')
        flag = 1;
    return flag;
}

/*
 * 连子棋游戏交互
 * @param board 指向存储游戏棋盘的指针的指针
 * @param row 棋盘的行数
 * @param col 棋盘的列数
 * @param sum 连子个数
 */
void game(char*** board, int row, int col, int sum)
{
	init_board(board, row, col);
	srand((unsigned)time(NULL));
	int win = 0;

	while (1)
	{
		system("cls");
        show_board(*board, row, col);
		win = user_play(board, row, col, sum);
		if (win == 1)
		{
			system("cls");
			show_board(*board, row, col);
			free_board(board, row, col);
			printf("游戏胜利!\n");
			getchar();
			system("cls");
			break;
		}
		if (win == 0)
		{
			system("cls");
			show_board(*board, row, col);
			free_board(board, row, col);
			printf("游戏平局!\n");
			getchar();
			system("cls");
			break;
		}

		win = computer_play(board, row, col, sum);
		if (win == -1)
		{
			system("cls");
			show_board(*board, row, col);
			free_board(board, row, col);
			printf("游戏失败!\n");
			getchar();
			system("cls");
			break;
		}
		if (win == 0)
		{
			system("cls");
			show_board(*board, row, col);
			free_board(board, row, col);
			printf("游戏平局!\n");
			getchar();
			system("cls");
			break;
		}
	}
}

五、游戏效果展示与源码分享

1、游戏效果

请添加图片描述

上图所展示的是我们精心打造的游戏效果,动态的画面、流畅的操作,是否已经让你跃跃欲试了呢?

2、源代码

为了让更多爱好者能够深入学习和交流,我们已将本游戏的源代码开源至Gitee平台。你可以通过以下传送门轻松获取,一起探索游戏的奥秘,共同进步。
已经在Gitee上开源:传送门


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

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

相关文章

DataGrip在Windows和MacOS平台上的快捷键

0. 背景信息 No.说明1测试DataGrip版本号 : 2024.2.2 1. Windows下快捷键 2. MacOS下快捷键

基于波特图的控制系统设计算法

波特图&#xff08;Bode Plot&#xff09;是一种用于描述线性控制系统频率响应的图形表示方法&#xff0c;通常用于分析和设计控制系统。它以控制系统的传递函数&#xff08;或频域传递函数&#xff09;为基础&#xff0c;将系统的幅频特性&#xff08;振幅-频率响应&#xff0…

PyCharm与Anaconda超详细安装配置教程

1、安装Anaconda&#xff08;过程&#xff09;-CSDN博客 2.创建虚拟环境conda create -n pytorch20 python3.9并输入conda activate pytorch20进入 3.更改镜像源conda/pip(只添加三个pip源和conda源即可) 4.安装PyTorch&#xff08;CPU版&#xff09; 5.安装Pycharm并破解&…

LED灯、蜂鸣器、继电器的控制

LED灯的控制 该专栏所有文章都默认使用STM32F103ZET6开发板 目录 LED灯的控制 一、简单的LED灯控制 1、初始化函数 led灯 2、应用函数 2、蜂鸣器 3、继电器 一、简单的LED灯控制 编程框架&#xff1a;初始化函数和应用函数 1、初始化函数 初始化函数一般包括&#xf…

SVTR文字识别

论文地址&#xff1a;https://arxiv.org/abs/2205.00159 notes&#xff1a; 论文2.5中说的N nodes&#xff0c;就是输出的类别数量&#xff0c;英文37&#xff0c;中文6625&#xff0c;英文37说的是最简单的英文文字识别任务&#xff0c;不区分大小写&#xff0c;就是26个字母…

软件测试 BUG 篇

目录 一、软件测试的生命周期 二、BUG 1. bug的概念 2. 描述bug的要素 3. bug的级别 4. bug的生命周期 5. 与开发产生争执怎么办&#xff1f;&#xff08;面试高频考题&#xff09; 5.1 先检查自身&#xff0c;是否bug描述不清楚 5.2 站在用户角度考虑并抛出问题 5.3 …

nginx架构篇(三)

文章目录 一、Nginx实现服务器端集群搭建1.1 Nginx与Tomcat部署1. 环境准备(Tomcat)2. 环境准备(Nginx) 1.2. Nginx实现动静分离1.2.1. 需求分析1.2.2. 动静实现步骤 1.3. Nginx实现Tomcat集群搭建1.4. Nginx高可用解决方案1.4.1. Keepalived1.4.2. VRRP介绍1.4.3. 环境搭建环境…

【已解决】SpringBoot3项目整合Druid依赖:Druid监控页面404报错

文章标题 问题描述原因分析解决方案参考资料 问题描述 最近&#xff0c;笔者在SpringBoot3项目中整合Druid连接池时&#xff0c;偶然翻到一条介绍Druid监控的短视频&#xff0c;兴致盎然之下尝试设置了一下Druid监控。 But&#xff0c;按照视频中提供的yml参数对照设置&#x…

【全网最全】2024华为杯数学建模C题高质量成品查看论文!【附带全套代码+数据】

题 目&#xff1a; ___基于数据驱动下磁性元件的磁芯损耗建模 完整版获取&#xff1a; 点击链接加入群聊【2024华为杯数学建模助攻资料】&#xff1a;http://qm.qq.com/cgi-bin/qm/qr?_wv1027&kxtS4vwn3gcv8oCYYyrqd0BvFc7tNfhV7&authKeyedQFZne%2BzvEfLEVg2v8FOm%…

山体滑坡检测系统源码分享

山体滑坡检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…

使用vue创建项目

一、安装环境 二、创建vue框架&#xff08;创建文件夹&#xff0c;摁shift鼠标右键 打开&#xff09; 1、项目配置 2、新增目录 三、路径别名配置 输入/ ,VSCode会联想出src下的所有子目录和文件&#xff0c;统一文件路径访问时不容易出错 四、ElementPlus配置 1、组件分为…

华为全联接大会HC2024 观会感

9/19-21于上海&#xff0c;华为举办了他一年一届也是最重要的华为系展会-Huawei Connect 华为全联接大会&#xff0c;今天有幸赶在展会最后一天来参观一下 上午照常是keynote&#xff0c;由华为计算线总裁进行了今天的KN开场&#xff0c;介绍了华为在“算”方面的进展&#x…

web基础—dvwa靶场(九)Weak Session IDs

Weak Session IDs&#xff08;弱会话&#xff09; Weak Session IDs&#xff08;弱会话&#xff09;&#xff0c;用户访问服务器的时候&#xff0c;一般服务器都会分配一个身份证 session id 给用户&#xff0c;用于标识。用户拿到 session id 后就会保存到 cookies 上&#x…

某花顺爬虫逆向分析

目标网站&#xff1a; aHR0cHM6Ly9xLjEwanFrYS5jb20uY24v 一、抓包分析 携带了cookie&#xff0c;每次请求的cookie都不一样&#xff0c;且不携带cookie不能成功返回数据 hook Cookie代码 _cookie document.cookie Object.defineProperty(document, cookie, {get(){con…

camtasia2024绿色免费安装包win+mac下载含2024最新激活密钥

Hey, hey, hey&#xff01;亲爱的各位小伙伴&#xff0c;今天我要给大家带来的是Camtasia2024中文版本&#xff0c;这款软件简直是视频制作爱好者的福音啊&#xff01; camtasia2024绿色免费安装包winmac下载&#xff0c;点击链接即可保存。 先说说这个版本新加的功能吧&#…

[JavaEE] UDP协议

目录 再谈端口号 一、端口号的划分 二、UDP协议 三、UDP的特点 再谈端口号 一、端口号的划分 0-1023&#xff1a;知名端口号&#xff0c;端口号固定&#xff0c;其中包括HTTP&#xff0c;FTP&#xff0c;SSH等广为使用的应用层协议。 1024-65535&#xff1a;操作系统动态分…

微软AI核电计划

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

AtCoder ABC370 A-D题解

比赛链接:ABC370 AT 上 400 分寄。 Problem A: Code #include <bits/stdc.h> using namespace std; int main(){int L,R;cin>>L>>R;if(LR)cout<<"Invalid"<<endl;else if(L1)cout<<"YES"<<endl;elsecout<…

Java | Leetcode Java题解之第413题等差数列划分

题目&#xff1a; 题解&#xff1a; class Solution {public int numberOfArithmeticSlices(int[] nums) {int n nums.length;if (n 1) {return 0;}int d nums[0] - nums[1], t 0;int ans 0;// 因为等差数列的长度至少为 3&#xff0c;所以可以从 i2 开始枚举for (int i …

TinkerTool System for Mac实用软件系统维护工具

TinkerTool System 是一款功能全面且强大的 Mac 实用软件&#xff0c;具有以下特点和功能&#xff1a; 软件下载地址 维护功能&#xff1a; 磁盘清理&#xff1a;能够快速扫描并清理系统中的垃圾文件、临时文件以及其他无用文件&#xff0c;释放宝贵的磁盘空间&#xff0c;保…