【C语言】三子棋(X子棋)的编写及解析

文章前言:

 本篇文章主要是介绍简单三子棋的编写。

通过本文章,我希望入门读者可以明白一段程序的编写,其逻辑是通过一个个函数分开且高效地耦合所实现的。这个是我认为程序员想要顺利编写程序时必须要完成的东西。

整体的框架:

对于三子棋的编写,我使用三个文件来完成:
1、san_borad.c 该文件中放的是程序的主体框架
2、game.h 这里包含的是自定义函数的声明以及宏定义和其它宏文件,其它文件需要包含它。
3、game.c 这里包含的是自定义函数的具体实现

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

}
int main()
{
	int input = 0;

	do
	{
		menu();
		printf("请选择:\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("已进入游戏:\n");
			game();
			break;
		case 0:
			printf("退出程序\n");
			break;
		default:
			printf("输入非法\n");
		}
	} while (1);
}

棋盘的样式及步骤分析:

我想象棋盘是这样的:

在这里插入图片描述
步骤分析:
1、最开始数组里面都是空格(初始化棋盘)
2、显示数组内的元素(棋盘的打印)
3、定义宏,以便实现X子棋
4、开始下棋(还要判断棋盘是否下满)
5、判断输赢

定义宏,以便实现X子棋:

//在game.h中定义宏
#define ROW 3
#define COL 3

显示数组内的元素(棋盘的打印):

这里存在一个比较难的点:
如果想要实现X子棋,棋盘的打印必须不能写死,要借助循环来灵活化。
思路如下:
1、将棋盘分为数据行和分割行
2、在数组的最后不需要分割行,所以在最后一次循环不需要打印分割行
3、每一行都只需打印 COL - 1 个 |

//打印棋盘
void Print(char arr[ROW][COL], int row, int col)
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			printf(" %c ", arr[i][j]);
			if (j < col - 1)
			{
				printf("|");
			}
		}
		printf("\n");
		if (i < row - 1)
		{
			for (int k = 0; k < col; k++)
			{
				printf("___");//这里就是三个下划线为一组
				if (k < col - 1)
				{
					printf("|");
				}
			}
			printf("\n");
		}
	}
}

下棋:

接下来到了下棋。
按照道理来说,在每一次下棋之前都需要先判断这一局有没有结束,但这里函数实现我想默认其可以将该局游戏进行下去。
下棋的主体无非两个:玩家以及电脑(这里不是玩家VS玩家)
总体上,在下每一步棋都要判断该处没有下过棋才能下。
玩家:棋盘的坐标默认是(1,1)而数组默认为(0,0),这个要注意,*表示玩家。
电脑:使用随机数来确认坐标,#表示电脑。
下面是具体实现:

//玩家下棋
void player(char arr[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	int flag = 1;
	do
	{
		printf("请输入坐标:\n");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (arr[x - 1][y - 1] == ' ')
			{
				arr[x - 1][y - 1] = '*';
				flag = 0;
			}
			else
			{
				printf("该处已下过\n");
			}
		}
		
	} while (flag);
}

//电脑下棋
void comper(char arr[ROW][COL], int row, int col)
{
	
	while (true)
	{
		int x = rand() % row;
		int y = rand() % col;
		if (arr[x][y] == ' ')
		{
			arr[x][y] = '#';
			break;
		}
	}
}

主体部分:
这里的主体不是最终版本,还需要改进,那就是引入对棋局的判断

void test()
{
	srand((unsigned int)time(NULL));
	char arr[ROW][COL] = { 0 };
	init(arr, ROW, COL);
	do
	{
		printf("请玩家下棋:\n");
		player(arr, ROW, COL);
		printf("电脑下棋:\n");
		comper(arr, ROW, COL);
		Print(arr, ROW, COL);
	} while (1);
}

判断棋局是否进行下去:

在每一步棋下完后,棋局下面的走向一共有四种:
1、继续下去
2、玩家赢
3、电脑赢
4、平局
对于此,我用1表示玩家赢,2表示电脑赢,3表示继续,0表示平局。
具体实现:

//判断谁赢
int judge(char arr[ROW][COL], int row, int col)
{
	int num = -1;
	char sign = ' ';

	//行
	for (int i = 0; i < row; i++)
	{
		sign = arr[i][0];
		for (int j = 0; j < col; j++)
		{
		
			if (arr[i][j] == ' ' || arr[i][j] != sign)
			{
				break;
			}

			if (j == col - 1)
			{
				if (sign == '*')
				{
					return 1;
				}
				else if (sign == '#')
				{
					return 2;
				}
			}
		}
	}

	for (int i = 0; i < col; i++)
	{
		sign = arr[0][i];
		for (int j = 0; j < row; j++)
		{

			if (arr[j][i] == ' ' || arr[j][i] != sign)
			{
				break;
			}

			if (j == row - 1)
			{
				if (sign == '*')
				{
					return 1;
				}
				else if (sign == '#')
				{
					return 2;
				}
			}
		}
	}

	//正对角线
	for (int i = 0; i < row; i++)
	{
		sign = arr[0][0];
		if (arr[i][i] == ' ' || sign != arr[i][i])
		{
			break;
		}

		if (i == row - 1)
		{
			if (sign == '*')
			{
				return 1;
			}
			else if (sign == '#')
			{
				return 2;
			}
		}
	}

	//副对角线
	sign = arr[row - 1][0];
	int k = 0;
	for (int i = row - 1; i >= 0; i--)
	{
		if (arr[i][k] == ' ' || arr[i][k] != sign)
		{
			break;
		}
		k--;
		if (i == 0)
		{
			if (sign == '*')
			{
				return 1;
			}
			else if (sign == '#')
			{
				return 2;
			}
		}
	}

	//平局
	int flag = 1;
	for (int i = 0; i < row && flag == 1; i++)
	{
		for (int j = 0; j < col; j++)
		{
			if (arr[i][j] == ' ')
			{
				flag = 0;
				break;
			}
		}
	}
	if (flag == 1)
	{
		return 0;
	}

	//什么都不是,那就继续
	return 3;
}

至此,可以说已经完成了三子棋的创建了,下面是主体部分:

void test()
{
	srand((unsigned int)time(NULL));
	char arr[ROW][COL] = { 0 };
	init(arr, ROW, COL);
	while(true)
	{
		int judgement = -1;
		printf("请玩家下棋:\n");
		player(arr, ROW, COL);
		judgement = judge(arr, ROW, COL);
		Print(arr, ROW, COL);
		if (judgement == 0)
		{
			printf("平局\n");
			break;
		}
		else if (judgement == 1)
		{
			printf("玩家赢\n");
			break;
		}
		else if(judgement == 2)
		{
			printf("电脑赢\n");
			break;
		}
		printf("电脑下棋:\n");
		comper(arr, ROW, COL);
		judgement = judge(arr, ROW, COL);
		Print(arr, ROW, COL);
		if (judgement == 0)
		{
			printf("平局\n");
			break;
		}
		else if (judgement == 1)
		{
			printf("玩家赢\n");
			break;
		}
		else if (judgement == 2)
		{
			printf("电脑赢\n");
			break;
		}
	}
}

全部整合:

//game.h
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

//在game.h中定义宏
#define ROW 3
#define COL 3


void init(char arr[ROW][COL], int row, int col);

void Print(char arr[ROW][COL], int row, int col);

void player(char arr[ROW][COL], int row, int col);

void comper(char arr[ROW][COL], int row, int col);

int judge(char arr[ROW][COL], int row, int col);
//game.c
#define _CRT_SECURE_NO_WARNINGS 1

#include "game.h"

//初始化数组都为空格
void init(char arr[ROW][COL], int row, int col)
{
	for (int i = 0; i < ROW; i++)
	{
		for (int j = 0; j < COL; j++)
		{
			arr[i][j] = ' ';
		}
	}
}

//打印棋盘
void Print(char arr[ROW][COL], int row, int col)
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			printf(" %c ", arr[i][j]);
			if (j < col - 1)
			{
				printf("|");
			}
		}
		printf("\n");
		if (i < row - 1)
		{
			for (int k = 0; k < col; k++)
			{
				printf("___");
				if (k < col - 1)
				{
					printf("|");
				}
			}
			printf("\n");
		}
	}
}

//玩家下棋
void player(char arr[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	int flag = 1;
	do
	{
		printf("请输入坐标:\n");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (arr[x - 1][y - 1] == ' ')
			{
				arr[x - 1][y - 1] = '*';
				flag = 0;
			}
			else
			{
				printf("该处已下过\n");
			}
		}
		
	} while (flag);
}

//电脑下棋
void comper(char arr[ROW][COL], int row, int col)
{
	
	while (true)
	{
		int x = rand() % row;
		int y = rand() % col;
		if (arr[x][y] == ' ')
		{
			arr[x][y] = '#';
			break;
		}
	}
}

//判断谁赢
int judge(char arr[ROW][COL], int row, int col)
{
	int num = -1;
	char sign = ' ';

	//行
	for (int i = 0; i < row; i++)
	{
		sign = arr[i][0];
		for (int j = 0; j < col; j++)
		{
		
			if (arr[i][j] == ' ' || arr[i][j] != sign)
			{
				break;
			}

			if (j == col - 1)
			{
				if (sign == '*')
				{
					return 1;
				}
				else if (sign == '#')
				{
					return 2;
				}
			}
		}
	}

	//列
	for (int i = 0; i < col; i++)
	{
		sign = arr[0][i];
		for (int j = 0; j < row; j++)
		{

			if (arr[j][i] == ' ' || arr[j][i] != sign)
			{
				break;
			}

			if (j == row - 1)
			{
				if (sign == '*')
				{
					return 1;
				}
				else if (sign == '#')
				{
					return 2;
				}
			}
		}
	}
	//正对角线
	for (int i = 0; i < row; i++)
	{
		sign = arr[0][0];
		if (arr[i][i] == ' ' || sign != arr[i][i])
		{
			break;
		}

		if (i == row - 1)
		{
			if (sign == '*')
			{
				return 1;
			}
			else if (sign == '#')
			{
				return 2;
			}
		}
	}

	//副对角线
	sign = arr[row - 1][0];
	int k = 0;
	for (int i = row - 1; i >= 0; i--)
	{
		if (arr[i][k] == ' ' || arr[i][k] != sign)
		{
			break;
		}
		k--;
		if (i == 0)
		{
			if (sign == '*')
			{
				return 1;
			}
			else if (sign == '#')
			{
				return 2;
			}
		}
	}

	//平局
	int flag = 1;
	for (int i = 0; i < row && flag == 1; i++)
	{
		for (int j = 0; j < col; j++)
		{
			if (arr[i][j] == ' ')
			{
				flag = 0;
				break;
			}
		}
	}
	if (flag == 1)
	{
		return 0;
	}

	//什么都不是,那就继续
	return 3;
}

//san_borad.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 test()
{
	srand((unsigned int)time(NULL));
	char arr[ROW][COL] = { 0 };
	init(arr, ROW, COL);
	while(true)
	{
		int judgement = -1;
		printf("请玩家下棋:\n");
		player(arr, ROW, COL);
		judgement = judge(arr, ROW, COL);
		Print(arr, ROW, COL);
		if (judgement == 0)
		{
			printf("平局\n");
			break;
		}
		else if (judgement == 1)
		{
			printf("玩家赢\n");
			break;
		}
		else if(judgement == 2)
		{
			printf("电脑赢\n");
			break;
		}
		printf("电脑下棋:\n");
		comper(arr, ROW, COL);
		judgement = judge(arr, ROW, COL);
		Print(arr, ROW, COL);
		if (judgement == 0)
		{
			printf("平局\n");
			break;
		}
		else if (judgement == 1)
		{
			printf("玩家赢\n");
			break;
		}
		else if (judgement == 2)
		{
			printf("电脑赢\n");
			break;
		}
	}
}

int main()
{
	int input = 0;

	do
	{
		menu();
		printf("请选择:\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("已进入游戏:\n");
			test();
			break;
		case 0:
			printf("退出程序\n");
			break;
		default:
			printf("输入非法\n");
		}
	} while (input);

	return 0;
}

结语:

通过一块块函数将功能逐步实现是完成一段程序的重要思想。这里不只是三子棋,将宏改一下数值就可以实现不同的棋。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值