C语言之简易三子棋小游戏

书摘文案:尽最大的努力,留最小的遗憾。

png?=700x

在前面的几篇文章中详细的介绍了,分支与循环语句,函数,数组的基础知识,现在我们利用他们来做一个三子棋的小游戏吧!

1.游戏描述

三子棋游戏规则: 电脑(随机)和玩家一次下一子,双方轮流交替下子,直到电脑和玩家任意一方获胜,或者棋盘满了,结束游戏。
获胜判定: 只要电脑或者玩家任意一方的棋子有三子连在一起, 可以为横连、纵连、斜连,则该方获胜,游戏结束。若棋盘满了,则判定为平局。
程序需求:游戏的框架,游戏菜单,棋盘打印,玩家下棋,电脑下棋,输赢判断。

2.实现思路

前提条件:先创建3个文件实现不同的功能。

test.c文件:实现游戏的整体框架,执行流程。
game.c文件:实现游戏中出现的游戏函数:棋盘打印,玩家下棋等等。
game.h文件:声明函数。

3.讲解思路

3.1菜单的打印以及整体框架

当我们想要玩这个游戏的时候,运行时一般开始时都会有游戏菜单的显现(让玩家可以做出选择),所以我们需要一个菜单。

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

在这里我们打印菜单,让玩家输入1玩游戏,输入0退出游戏。
1.在玩家一运行程序这个菜单就会出现,我们需要在主函数中使用 do while 语句。
2.玩家在菜单出现后需要做出选择,我们不妨使用switch case 语句。
代码展现:

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

注意:我们这里定义了一个变量 input 我们将它同时放置在了 switch(),while()语句项中,首先进入 do while语句时,做出选择。
输入1:
进入switch语句,并进入case1,游戏结束后,break语句跳出 switch 语句到 while 语句中进行判断,我们一开始是输入1会再次进入do语句中。
输入0:
进入switch语句,并进入case0中,break语句跳出switch语句到while语句中进行判断,我们输入的是0为假不会再次进入do语句中,游戏结束,
输入其他数字:
进入switch语句,并进入default语句中,break语句跳出switch语句到while语句中进行判断,我们输入的是非零数字,会再次进入do语句中。

3.2game函数中的游戏思路

在玩家做出选择想要玩游戏,进入case1进入game函数(游戏开始)。
这里先展示一下游戏。
png?=500x
game函数的代码流程:

void game()
{
	char board[ROW][COL] = { 0 };
	//初始化棋盘
	Initboard(board, ROW, COL);
	//打印棋盘
	Displayboard(board, ROW, COL);
	char ret = 0;
	while (1)
	{
		//玩家下棋
		Playerboard(board, ROW, COL);
		//打印棋盘
		Displayboard(board, ROW, COL);
		//判断输赢
		ret = Iswin(board, ROW, COL);
		if (ret != 'C')
			break;
		//电脑下棋
		Computerboard(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");
}

关于game函数中所出现的各种函数我们都写入game,c函数中,然后在game.h文件中声明。
但是想要使用这些函数,我们就需要在 test.c和game.c文件中引用 game.h 文件即可。
因为是我们创建的一个头文件所以我们以“ ”来引用,#Include "game.h"

3.4 game.h文件中游戏函数实现

初始化棋盘

//初始化棋盘
void Initboard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < col; j++)
		{
			board[i][j] = ' ';
		}
	}
}

这里的ROW,COL是我们在game.h文件中#define定义的宏,只要修改宏我们就可以实现多行多列的棋盘。

#define ROW 3
#define COL 3

打印棋盘

void Displayboard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	//打印数据
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < row; j++)
		{
			printf(" %c ", board[i][j]);
			if (j < col-1)
			{
				printf("|");
			}
		}
		printf("\n");
		if (i < row - 1)
		{
			for (j = 0; j < row; j++)
			{
				printf("---");
				if (j < col - 1)
				{
					printf("|");
				}
			}
			printf("\n");
		}

	}
}

玩家下棋

void Playerboard(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");
		}


	}
}

注意:
1.在玩家下棋的输入的坐标时我们首先是要判断它是否合法的。因为如果坐标被占用的话,玩家就不可以下棋。
2.下棋我们要考虑所输入的坐标是否会超过所定义的范围。
3.我们使用while语句是防止玩家下棋超过定义范围,以及输入的棋盘坐标非法能够重新下棋。
4.因为玩家输入的坐标(x,y)肯定是除0以外的数字,但是访问数组是从下标0开始的,所以需要(x-1,y-1)来符合 条件。

电脑下棋

//电脑下棋
void Computerboard(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] = '#';
			break;
		}
	}

}

这里我们先介绍一下rand函数。
rand()函数: 随机数生成器,执行时生成一个随机数,但是多次调用时随机数都是相同的,所以也称它为伪随机数,若想要不同我们就要调用 srand() 函数。
srand()函数: 初始化随机数生成器,设置供rand()函数使用的随机数生成种子,使每次调用rand函数时生成的随机数不同。如果你在第一次调用rand()之前没有调用srand(),那么系统会为你自动调用srand()。而使用同种子相同的数调用 rand()会导致相同的随机数序列被生成。使用方法:

srand((unsigned int)time(NULL));

注意需要引用头文件> #include <stdlib.h> 和 #include<time.h>(在头文件game.h中引用即可)

玩家下棋

玩家赢返回 ’*‘ 字符
电脑赢返回 '#‘ 字符
平局返回 ’Q‘ 字符
继续返回 ’C‘ 字符

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] != ' ')
		{
			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] != ' ')
		{
			return board[0][i];
		}
	}
	//对角线(三子连成对角线)
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
		return board[1][1];
	if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
		return board[1][1];

	//平局
	if (Isfull(board, row, col) == 1)
	{
		return 'Q';
	}
	//继续
	return 'C';
}

注意:
因为判断输赢时候时连成3子就获得胜利,但以空格初始化的棋盘也会造成连成3子,所以我们就需要排除3子都是空格的情况。

平局

int Isfull(char board[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < col; j++)
		{
			if (board[i][j] == ' ')
			{
				return 0;
			}
		}
	}
	return 1;
}

上面这些函数实现都是定义在game.c文件中,然后我们在game.中声明函数。

3.5game.c中函数的声明

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
//初始化棋盘
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);

小细节:因为不仅仅是test.c文件中需要 #include<stdio.h>,game.c文件中各种函数的实现(有使用printf函数等),所以我们将#include<stdio.h>放在game.h文件中即可。

4.最终效果

玩家赢:
png?=500x

一个技巧

当我们运行程序时我们玩完一个游戏时,上一局的游戏痕迹依旧存在,我们想要玩完一局后屏幕可以清空,可以调用系统命令system(”cls")来清屏, 但相应的需要使用引用头文件#include < Windows > .

5.整体代码

test.c文件

#include"game.h"
void menu()
{
	Sleep(1000);
	system("cls");
	//这两句代码时等待1秒钟,清屏。
	printf("***********************\n");
	printf("***********************\n");
	printf("****1.play  0.exit*****\n");
	printf("***********************\n");
	printf("***********************\n");
}

void game()
{
	char board[ROW][COL] = { 0 };
	//初始化棋盘
	Initboard(board, ROW, COL);
	//打印棋盘
	Displayboard(board, ROW, COL);
	char ret = 0;
	while (1)
	{
		//玩家下棋
		Playerboard(board, ROW, COL);
		//打印棋盘
		Displayboard(board, ROW, COL);
		//判断输赢
		ret = Iswin(board, ROW, COL);
		if (ret != 'C')
			break;
		//电脑下棋
		Computerboard(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;
}

game.c文件

#include"game.h"


//初始化棋盘
void Initboard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < col; j++)
		{
			board[i][j] = ' ';
		}
	}
}


void Displayboard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	//打印数据
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < row; j++)
		{
			printf(" %c ", board[i][j]);
			if (j < col-1)
			{
				printf("|");
			}
		}
		printf("\n");
		if (i < row - 1)
		{
			for (j = 0; j < row; j++)
			{
				printf("---");
				if (j < col - 1)
				{
					printf("|");
				}
			}
			printf("\n");
		}

	}
}


//玩家下棋
void Playerboard(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 Computerboard(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] = '#';
			break;
		}
	}

}



//判断是否平局
int Isfull(char board[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		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][2] == board[i][0] != ' ');
//		return board[i][0];
//	}
//	//列
//
//	for (i = 0; i < col; i++)
//	{
//		if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[2][i] == board[0][i] != ' ');
//		return board[0][i];
//	}
//
//	//对角线
//	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
//		return board[1][1];
//	if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
//		return board[1][1];
//
//	//平局
//	if (Isfull(board, row, col) == 1)
//	{
//		return 'Q';
//	}
//
//	//继续
//	return 'C';
//
//}

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] != ' ')
		{
			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] != ' ')
		{
			return board[0][i];
		}
	}
	//对角线
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
		return board[1][1];
	if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
		return board[1][1];

	//平局
	if (Isfull(board, row, col) == 1)
	{
		return 'Q';
	}
	//继续
	return 'C';
}

game.h文件:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<Windows.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);

结语:这次讲的是很适合新手练习的一个小游戏三子棋,可以综合练习前文所学习的知识,当然这里还有很多可以改进的地方,比如多子棋的实现,或者改进电脑下棋的代码(因为这里赢电脑太简单了😂😂😂),大家都可以去尝试去努力实现一下,后续中我也会改进的。如果文章中有什么错误或者疑惑都欢迎大家在评论区提出,谢谢。

  • 20
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 14
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值