C语言实现五子棋小游戏

C语言实现五子棋小游戏三子棋,五子棋,无论多少子棋,其原理都是一样的。下面我用五子棋为例讲解用C语言多文件编程实现五子棋。设计电脑和玩家两个作为下棋的两方,用键盘输入作为玩家的游戏操作。1.效果图:程序总的构架:我们只要输入坐标就可以和电脑对弈了。电脑的棋子用‘0’表示,玩家的棋子用‘x’表示。2.打印菜单可以根据自己的爱好设计各种风格的…

大家好,又见面了,我是你们的朋友全栈君。

       三子棋,五子棋,无论多少子棋,其原理都是一样的。下面我用五子棋为例讲解用C语言多文件编程实现五子棋。

       设计电脑和玩家两个作为下棋的两方,用键盘输入作为玩家的游戏操作。

1.效果图:

程序总的构架:

C语言实现五子棋小游戏

我们只要输入坐标就可以和电脑对弈了。

电脑的棋子用 ‘0’ 表示,玩家的棋子用 ‘x’ 表示。

C语言实现五子棋小游戏

C语言实现五子棋小游戏

 

2.打印菜单

可以根据自己的爱好设计各种风格的菜单,自己自然赏心悦目,让自己的游戏更加美观。

// 菜单
menu()
{
	printf("\n");
	printf("*******************************\n");
	printf("****  欢迎来到五子棋游戏!  ****\n");
	printf("****      1.进入游戏       ****\n");
	printf("****      0.退出游戏       ****\n");
	printf("*******************************\n");
}

 

3.初始化棋盘

ROW, COL 分别表示棋盘的宽度和高度(即是棋盘的 x 和 y)。

一开始先把棋盘初始化为 ‘  ‘  (空格)。

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

4.打印棋盘

用竖线和横线把棋盘封装起来,在棋盘外标上坐标的位置提示,以方便玩家。

//打印棋盘 
void DisplayBoard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;

	for (i = 0; i < row; i++)
	{
		printf("  %d ", i+1); //打印棋盘 x 轴坐标提示
	}
	printf("\n");

	for (j = 0; j < col; j++)
	{
		printf("---|"); //打印第一行棋盘
	}
	printf("\n");

	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			printf(" %c |", board[i][j]); //打印竖标
		}
		printf(" %d ", i+1); //打印棋盘 y 轴坐标提示
		printf("\n");

		for (j = 0; j < col; j++)
		{
			printf("---|"); //打印横标
		}
		printf("\n");
	}
}

5.电脑下棋

我是利用函数 strand() 函数和 rand() 函数让电脑在棋盘上空的地方随机下棋,用一个循环判断就可以实现。也可以设计电脑让电脑更加“聪明”,能够判断玩家已经下好的棋,并能够做出阻止(我没有做这一步,如果有兴趣的话,可以自己再研究一下哦 ^_^)。

//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("电脑走:>\n");

	while (1)
	{
		x = rand() % row;
		y = rand() % col;

		if (board[x][y] == ' ')
		{
			board[x][y] = '0';
			break;
		}
		else
		{
			continue;
		}
	}
}

6.玩家下棋

从键盘上输入下棋坐标,判断坐标正好是棋盘上空的地方,则成功下棋,若在棋盘上但非空位置,提示玩家该坐标已经被占用,要重新输入,若不在棋盘上,提示玩家该坐标非法,要重新输入。

//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;

	printf("玩家走:>\n");
	printf("请输入坐标(%d,%d): >",row,col);

	while (1)
	{
		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] = 'x';
				break;
			}
			// 输入坐标已被占用
			else
			{
				printf("该坐标已经被占用\n");
				printf("请重新输入:>");
				continue;
			}
		}
		// 输入坐标非法判断
		else
		{
			printf("坐标非法\n");
			printf("请重新输入:>");
			continue;
		}
	}
}

7.判断平局

不是平局返回 0 ,平局返回 1 。只要棋盘上有空位置则返回 0 表示不是平局。

//判断平局
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;
}

8.判断输赢

两方谁先把五颗棋子连成一线,就是赢家。判断输赢函数是一个重要的模块,其代码如下:

//判断输赢
char IsWin(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 - 4; j++)
		{
			if (board[i][j] == board[i][j + 1]
				&& board[i][j + 1] == board[i][j + 2]
				&& board[i][j + 2] == board[i][j + 3]
				&& board[i][j + 3] == board[i][j + 4]
				&& board[i][j] != ' ')
			{
				return board[i][j];
			}
		}
	}

	// 竖线上五子连成一线,赢家产生
	for (j = 0; j < col; j++)
	{
		for (i = 0; i < row - 4; i++)
		{
			if (board[i][j] == board[i+1][j]
				&& board[i+1][j] == board[i+2][j] 
				&&board[i+2][j] == board[i+3][j]
				&& board[i+3][j] == board[i+4][j] 
				&& board[i][j] != ' ')
			{
				return board[i][j];
			}
		}
	}

	// 斜线上五子连成一线,赢家产生
	for (i = 0; i < row - 4; i++)
	{
		if (board[i][i] == board[i+1][i+1]
			&& board[i+1][i+1] == board[i+2][i+2]
			&& board[i + 2][i + 2] == board[i + 3][i + 3]
			&& board[i + 3][i + 3] == board[i + 4][i + 4]
			&& board[i][i] != ' ')
		{
			return board[i][i];
		}

		if (board[i][i+4] == board[i+1][i+3]
			&& board[i+1][i+3] == board[i+2][i+2]
			&& board[i + 2][i + 2] == board[i + 3][i + 1]
			&& board[i + 3][i + 1] == board[i + 4][i]
			&& board[i][i + 4] != ' ')
		{
			return board[i][i+4];
		}
	}

	//游戏平局
	if (IsFull(board, row, col))
	{
		return 'p';
	}

	//游戏结束
	return ' ';

}

9.游戏执行

以上就是我们要实现扫雷的模块,要想把这些模块整合起来运行,就需要一个游戏执行函数来调用这些模块,定义个game()函数实现,代码如下:

// 游戏开始执行
void game()
{
	int ret = 0;
	char board[ROW][COL] = { 0 };
	InitBoard(board, ROW, COL);

	// 下棋
	while (1)
	{
		ComputerMove(board, ROW, COL); //电脑走
		ret = IsWin(board, ROW, COL);
		if (ret != ' ')
		{
			break;
		}
		system("CLS"); //清屏,优化界面
		DisplayBoard(board, ROW, COL); //打印棋盘
		printf("\n");

		PlayerMove(board, ROW, COL); //玩家走
		ret = IsWin(board, ROW, COL);
		if (ret != ' ')
		{
			break;
		}
		DisplayBoard(board, ROW, COL); //打印棋盘
		printf("\n");
	}

	// 判断输赢或平局
	if (ret == 'p')
	{
		printf("平局\n"); 
		DisplayBoard(board, ROW, COL); //打印棋盘
	}
	else if (ret == 'x')
	{
		printf("玩家赢\n");
		DisplayBoard(board, ROW, COL); //打印棋盘
	}
	else if (ret == '0')
	{
		printf("电脑赢\n");
		DisplayBoard(board, ROW, COL); //打印棋盘
	}
}

10.头文件

在头文件 game.h 中声明各种函数,并将头文件 game.h 放在 main.c 文件中。

#ifndef __GAME_H__
#define __GAME_H__

# define _CRT_SECURE_NO_WARNINGS

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

#define ROW 10
#define COL 10

void InitBoard(char board[ROW][COL], int row, int col);
void DisplayBoard(char board[ROW][COL], int row, int col);
void ComputerMove(char board[ROW][COL], int row, int col);
void PlayerMove(char board[ROW][COL], int row, int col);
char IsWin(char board[ROW][COL], int row, int col);

#endif  __GAME_H__

11.测试

可以将棋盘的 x 和 y 轴长度更改多个值进行测试,已确保代码的稳定性。

void test()
{
	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");
		}
	} while (input);
}

12.附:game.c 的源码

#include "game.h"

// 菜单
menu()
{
	printf("\n");
	printf("*******************************\n");
	printf("****  欢迎来到五子棋游戏! ****\n");
	printf("****      1.进入游戏       ****\n");
	printf("****      0.退出游戏       ****\n");
	printf("*******************************\n");
}

//初始化
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++)
	{
		printf("  %d ", i+1); //打印棋盘 x 轴坐标提示
	}
	printf("\n");

	for (j = 0; j < col; j++)
	{
		printf("---|"); //打印第一行棋盘
	}
	printf("\n");

	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			printf(" %c |", board[i][j]); //打印竖标
		}
		printf(" %d ", i+1); //打印棋盘 y 轴坐标提示
		printf("\n");

		for (j = 0; j < col; j++)
		{
			printf("---|"); //打印横标
		}
		printf("\n");
	}
}

//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("电脑走:>\n");

	while (1)
	{
		x = rand() % row;
		y = rand() % col;

		if (board[x][y] == ' ')
		{
			board[x][y] = '0';
			break;
		}
		else
		{
			continue;
		}
	}
}

//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;

	printf("玩家走:>\n");
	printf("请输入坐标(%d,%d): >",row,col);

	while (1)
	{
		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] = 'x';
				break;
			}
			// 输入坐标已被占用
			else
			{
				printf("该坐标已经被占用\n");
				printf("请重新输入:>");
				continue;
			}
		}
		// 输入坐标非法判断
		else
		{
			printf("坐标非法\n");
			printf("请重新输入:>");
			continue;
		}
	}
}

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

	// 竖线上五子连成一线,赢家产生
	for (j = 0; j < col; j++)
	{
		for (i = 0; i < row - 4; i++)
		{
			if (board[i][j] == board[i+1][j]
				&& board[i+1][j] == board[i+2][j] 
				&&board[i+2][j] == board[i+3][j]
				&& board[i+3][j] == board[i+4][j] 
				&& board[i][j] != ' ')
			{
				return board[i][j];
			}
		}
	}

	// 斜线上五子连成一线,赢家产生
	for (i = 0; i < row - 4; i++)
	{
		if (board[i][i] == board[i+1][i+1]
			&& board[i+1][i+1] == board[i+2][i+2]
			&& board[i + 2][i + 2] == board[i + 3][i + 3]
			&& board[i + 3][i + 3] == board[i + 4][i + 4]
			&& board[i][i] != ' ')
		{
			return board[i][i];
		}

		if (board[i][i+4] == board[i+1][i+3]
			&& board[i+1][i+3] == board[i+2][i+2]
			&& board[i + 2][i + 2] == board[i + 3][i + 1]
			&& board[i + 3][i + 1] == board[i + 4][i]
			&& board[i][i + 4] != ' ')
		{
			return board[i][i+4];
		}
	}

	//游戏平局
	if (IsFull(board, row, col))
	{
		return 'p';
	}

	//游戏结束
	return ' ';

}

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/144642.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • jvm面试题目及答案_jvm原理面试题

    jvm面试题目及答案_jvm原理面试题Jvm面试题及答案整理965道(2021最新版)这是我收集的《Jvm最常见的965道面试题》高级Java面试问题列表。这些问题主要来自JVM核心部分,你可能知道这些棘手的JVM问题的答案,或者觉得这些不足以挑战你的Java知识,但这些问题都是容易在各种JVM面试中被问到的,而且包括我的朋友和同事在内的许多程序员都觉得很难回答。Jvm最新2021年面试题及答案,汇总版01、JAVA弱引用02、什么是堆03、什么是程序计数器04、各种回收器,各自优缺点,重点CMS、G1…

  • 大学四年,从小白到大神,全网最硬核算法学习攻略,不接受反驳

    大学四年,从小白到大神,全网最硬核算法学习攻略,不接受反驳一道题做半天,另外半天看这道题的题解,一台电脑一包烟,一道题解整一天,是我智商有问题吗?刷了两年题之后,我可以负责任跟你说,刷题吃力很正常,学算法,刷leetcode不是一朝一夕的事情,需要一个过程。而且新手学算法,还很容易陷入一些误区,例如一上来就抱着《算法导论》这种天书,啥数据结构还没学,就去刷leetcode,这其实不好,只会让自己放弃算法。学习算法,应该要一步一步来,要有规划,下面给大家分享下我的算法学习经验吧,觉得有帮助给我点个赞就行了。一、刷题前的一些准备如果你连最基本的数据结

  • Python 二进制,十进制,十六进制转换「建议收藏」

    Python 二进制,十进制,十六进制转换「建议收藏」十六进制到十进制使用int()函数,第一个参数是字符串’0Xff’,第二个参数是说明,这个字符串是几进制的数。 转化的结果是一个十进制数。>>>int(‘0xf’,16) 15二进制到十进制>>>int(‘10100111110′,2)   1342八进制到十进制>>>int(’17’,8)  15其实可以

  • navicat破解激活码2022【中文破解版】

    (navicat破解激活码2022)2021最新分享一个能用的的激活码出来,希望能帮到需要激活的朋友。目前这个是能用的,但是用的人多了之后也会失效,会不定时更新的,大家持续关注此网站~https://javaforall.cn/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~4K…

  • 一个示例让你明白适配器模式

    一个示例让你明白适配器模式本文讨论适配器模式。适配器模式是23中设计模式之一,它的主要作用是在新接口和老接口之间进行适配。它非常像我们出国旅行时带的电源转换器。为了举这个例子,我还特意去京东上搜了一下电源转换器,确实看到了很多地方的标准不一样。我们国家的电器使用普通的扁平两项或三项插头,而去外国的话,使用的标准就不一样了,比如德国,使用的是德国标准,是两项圆头的插头。

  • deepfacelab第七步换脸失败_CUBASE AI

    deepfacelab第七步换脸失败_CUBASE AI首先需要选择合适的DeepFaceLab下载(https://www.deepfacelabs.com/list-5-1.html),然后安装相应的显卡驱动,如果已经准备好这些工作,那么恭喜你,终于开

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号