C语言P4外传五子棋游戏

学完了二维数组,为了加深我们对于二维数组的理解,这次我给大家带来了一个有趣得小程序,五子棋游戏。下面我们来看看吧。

五子棋游戏实现

程序分文件实现

一般情况下,在实际开发中,我们得一个项目都是要分很多文件的。比如函数的实现放在.c文件之中。函数的声明,全局变量的声明和头文件的包含。一般都放在.h文件中。

那么这样子做的优势是什么呢?试想一下如果我们把所有代码都写在一个文件之中。一个文件有上万行代码,这时候维护起来会变得极为困难。并且,多人协同开发也是个问题,总不能几十个人在一个文件里面写代码把。这时候就体现了分文件的优点了。代码便于管理。并且利于多人开发。

下面的这个五子棋小程序我们会分为三个文件。
主文件 main.c
函数实现文件 game.c
头文件 game.h

代码实现

//这是我们的主文件
//main.c
#include"game.h"//引用了自己创建的头文件。

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

}

void game()
{
	char arr[COL][ROW];
	Init_board(arr, COL, ROW);
	Print(arr, COL, ROW);

	while (1)
	{
		Player_move(arr, COL, ROW);//创建数组用来生成棋盘
		Print(arr, COL, ROW);//打印函数,用来打印棋盘
		//判断玩家赢了没有
		char is_win = Is_winner(arr, COL, ROW);//判断是否有人获胜
        //这个函数我们规定。
        //返回'*'则为玩家获胜
        //返回'#'则为计算机获胜
        //若是棋盘满了无人胜出则返回'Q'平局
        //若是棋盘没满,且无人获胜就返回'C'游戏继续
		if (is_win == '*')
		{
			printf("玩家赢了\n");
			break;
		}
		else if (is_win == '#')
		{
			printf("计算机赢了\n");
			break;
		}
		else if (is_win == 'Q')
		{
			printf("平局\n");
			break;
		}

		Computer_move(arr, COL, ROW);//此函数是控制计算机落子的函数(当然我们这里设计的是随机落子)具体优化各位可以自行发挥超能力。
		Print(arr, COL, ROW);
		//判断电脑赢了没有
		is_win = Is_winner(arr, COL, ROW);

		if (is_win == '*')
		{
			printf("玩家赢了\n");
			break;
		}
		else if (is_win == '#')
		{
			printf("计算机赢了\n");
			break;
		}
		else if (is_win == 'Q')
		{
			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");
			break;
		}
	} while (input);

	

	return 0;
}

关于那个头文件为啥不用<>而是用""这里简单说一下,使用<>会优先从库中寻找该头文件,找不到的话再去项目路径下面去寻找。而如果使用自定义的头文件一般用双引号,这样可以先从项目路径下面寻找。

下面来看头文件

//game.h
#pragma once//这句代码可以防止头文件被重复包含

#define COL 5//行
#define ROW 5//列

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

void Init_board(char arr[COL][ROW], int col, int row);//初始化棋盘

void Print(char arr[COL][ROW], int col, int row);//打印棋盘

void Player_move(char arr[COL][ROW], int col, int row);//玩家落子

void Computer_move(char arr[COL][ROW], int col, int row);//计算机落子

//规定
//玩家赢返回 *
//计算机赢返回 #
//平局返回 Q
//没有结束继续游戏返回 C
char Is_winner(char arr[COL][ROW], int col, int row);//判断胜负

```头文件中包含了函数声明和宏定义  
>下面是函数实现的.c文件
```c
//game.c
#include"game.h"//包含所有要引用的头文件和函数声明
//这是初始化函数,将二维数组的每个元素都初始化为' '空格
void Init_board(char arr[COL][ROW], int col, int row)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < col; i++)
	{
		for (j = 0; j < row; j++)
		{
			arr[i][j] = ' ';
		}
	}

}

//这是打印函数,可以让打印出来的棋盘更好看。主要都是循环,循环掌握了看起来应该不复杂。
void Print(char arr[COL][ROW], int col, int row)
{
	int i = 0;
	for (i = 0; i < col; i++)
	{
		for (int j = 0; j < row; j++)//打印棋盘内容
		{
			printf(" %c ", arr[i][j]);
			if (j < row - 1)
				printf("|");
		}
		printf("\n");

		for (int k = 0; k < row; k++)//打印棋盘分隔符
		{
			printf("---");
			if (k < row - 1)
			{
				printf("|");
			}
		}
		printf("\n");
	}


}


void Player_move(char arr[COL][ROW], int col, int row)//玩家落子
{
	int x, y;
	
	
	while (1)
	{
		printf("请玩家落子\n");
		printf("请输入:> ");
		scanf("%d %d", &x, &y);
		//判断输入坐标是否合法(就是看输入的坐标是不是在数组的范围之内)
		if (x-1 < col && y-1 < row && x-1 >= 0 && y-1 >= 0)
		{
			//判断该坐标点是否被占用
			if (arr[x-1][y-1] == ' ')
			{
				arr[x-1][y-1] = '*';
				break;//死循环直到有输入正确的坐标
			}
			else
				printf("该点已有棋子,请重新输入\n");
		}
		else
		{
			printf("输入非法坐标 请重新输入\n");
		}
	}

}


void Computer_move(char arr[COL][ROW], int col, int row)//计算机落子
{
	printf("计算机落子\n");
	printf("Thinking \n");
	Sleep(1000);
	while (1)
	{
		int x = rand() % col;//生成合法范围内的随机数
		int y = rand() % row;

		//判断该点是否被占用
		if (arr[x][y] == ' ')
		{
			arr[x][y] = '#';
			break;
		}
	}



}


char Is_winner(char arr[COL][ROW], int col, int row)//判断胜负
{
	//判断行
    //外层循环,行。内层循环,列
	for (int i = 0; i < col; i++)
	{
		char tmp = arr[i][0];
		int flag = 0;
		for (int j = 1; j < row; j++)
		{
			if (arr[i][j] == tmp&&tmp!=' ')
				flag++;//用来标记,如果这一行都是一样的字符,就返回这个字符。
			if (flag == row-1)
				return tmp;
		}

	}

	//判断列
	for (int j = 0; j < row; j++)
	{
		char tmp = arr[0][j];
		int count = 0;
		for (int k = 1; k < col; k++)
		{
			if (tmp == arr[k][j]&&tmp!=' ')
				count++;
			if (count == col - 1)
			{
				return tmp;
			}
		}
	}
	//判断对角线
    //这里判断的是主对角线
	char cmp = arr[0][0];
	int count = 0;
	for (int i = 1; i < col; i++)
	{
		if (arr[i][i] == cmp)
			count++;
		if (count == col - 1)
		{
			return cmp;
		}
	}

	//这里判断的是副对角线
	cmp = arr[col-1][0];
	count = 0;
	for (int k = 1; k < row; k++)
	{
		if (cmp == arr[row - 1 - k][k])
			count++;
		if (count == row - 1)
			return cmp;
	}



	//判断是否是平局,是则返回Q,不是则返回C继续游戏
	for (int i = 0; i < col; i++)
	{
		for (int j = 0; j < row; j++)
		{
			if (arr[i][j] == ' ')
			{
				return 'C';
			}
		}
	}
	return 'Q';
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KissKernel

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值