【C语言】三子棋的实现及AI化的一些小小改进(进攻,防守,占据有利地形)

前言:本篇博客针对的是C语言初学者,如电脑的AI化部分只是一些相对简单的改进(进攻,防守,占据有利地形),不涉及智能算法(如博弈树)。其中有部分代码是我仔细琢磨后反复改进写出的代码,包含了我对编程的理解,如有不足,请多多指教。还有,其实也可以用枚举法来实现完美走棋(因为三子棋走法的可能性非常少),类似棋类软件里的开局库,实现方法也非常简单,有兴趣的朋友可以试试。

首先我们定义一些会大量用到的符号,这么做的好处是改动起来会比较方便。这里需要强调的是,我们写代码时一定要保证代码的可复用性。比方说,假如我们把row和col这两个符号都改成5的话,相应的代码不需要做出太多的改动。

#define ROW 3 //行
#define COL 3 //列

定义一个数组来存储下棋的数据。

char board[ROW][COL] = { 0 };

由于刚开始下棋时数组里应该是全空格,我们需要一个函数来初始化这个数组。

init_board(board, ROW, COL);

接着实现这个函数。

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

我们还需要一个函数来打印棋盘。

display_board(board, ROW, COL);

接着来实现这个函数。这个函数的实现还是有点复杂的。棋盘的打印分为横向分割线,纵向分割线和数据。横向分割线用外层循环控制,纵向分割线和数据用内层循环来控制。需要注意的是,并不是每一次循环都要打印分割线,不管是横向还是纵向,最后一次循环是不需要打印的,这一点可以用if语句来控制。

void display_board(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 < row - 1)
			{
				printf("|");
			}
		}
		printf("\n");

		//打印分割行
		if (i < row - 1)
		{
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)
				{
					printf("|");
				}
			}
		}
		printf("\n");
	}
}

接下来就是玩家下棋,判断局面,电脑下棋,判断局面······这就需要一个循环。玩家先下棋,棋子是O,电脑接着下,棋子是X。(为什么用O和X?三子棋的英文是naughts and crosses,分别代表了“圈”和“叉”)玩家和电脑下棋的函数实现最后再说,先说说判断局面的函数。玩家赢则返回“O”,电脑赢返回“X”,平局返回“T”(tie),如果都不是则返回“C”(continue)。所以整体的框架就很简单了。

char ret = 0;

	while (1)
	{
		//玩家下棋
		player_move(board, ROW, COL);
		display_board(board, ROW, COL);
		ret = is_win(board, ROW, COL);
		if (ret != 'C')
		{
			break;
		}

		//电脑下棋
		computer_move(board, ROW, COL);
		display_board(board, ROW, COL);
		is_win(board, ROW, COL);
		ret = is_win(board, ROW, COL);
		if (ret != 'C')
		{
			break;
		}
	}
	if (ret == 'O')
	{
		printf("玩家赢\n");
	}
	else if (ret == 'X')
	{
		printf("电脑赢\n");
	}
	else
	{
		printf("平局\n");
	}
	display_board(board, ROW, COL);

先贴下game函数的完整代码再继续

void game()
{
	//存储下棋的数据
	char board[ROW][COL] = { 0 };

	//初始化棋盘为全空格
	init_board(board, ROW, COL);

	//打印棋盘
	display_board(board, ROW, COL);

	char ret = 0;

	while (1)
	{
		//玩家下棋
		player_move(board, ROW, COL);
		display_board(board, ROW, COL);
		ret = is_win(board, ROW, COL);
		if (ret != 'C')
		{
			break;
		}

		//电脑下棋
		computer_move(board, ROW, COL);
		display_board(board, ROW, COL);
		is_win(board, ROW, COL);
		ret = is_win(board, ROW, COL);
		if (ret != 'C')
		{
			break;
		}
	}
	if (ret == 'O')
	{
		printf("玩家赢\n");
	}
	else if (ret == 'X')
	{
		printf("电脑赢\n");
	}
	else
	{
		printf("平局\n");
	}
	display_board(board, ROW, COL);
}

接下来讲讲输赢的判断。只需判断每一行,每一列,对角线是否全为某方棋子即可。简单的方法是直接判断两两之间是否相等,但这样就不够通用(万一是五子棋呢?),所以我采取一种不太容易想到的方法:用计数器判断。

先定义两个计数器,分别对应玩家和电脑

int player_count = 0;//统计玩家棋子的个数
int computer_count = 0;//统计电脑棋子的个数

先检查每一行,如果是某一方的棋子则对应的计数器自增一下,再判断计数器是否与相应的行数(或者列数)相等,如三子棋就判断是否是3。

    int i = 0;
	int j = 0;

	int player_count = 0;//统计玩家棋子的个数
	int computer_count = 0;//统计电脑棋子的个数

	//判断每行是否全部是某方棋子
	for (i = 0; i < row; i++)
	{
		player_count = 0;
		computer_count = 0;
		for (j = 0; j < col; j++)
		{
			if (board[i][j] == 'O')
			{
				player_count++;
			}
			if (board[i][j] == 'X')
			{
				computer_count++;
			}
		}
		if (player_count == col)
		{
			return 'O';
		}
		if (computer_count == col)
		{
			return 'X';
		}
	}

同理判断每列

    //判断每列是否全部是某方棋子
	for (i = 0; i < col; i++)
	{
		player_count = 0;
		computer_count = 0;
		for (j = 0; j < row; j++)
		{
			if (board[j][i] == 'O')
			{
				player_count++;
			}
			if (board[j][i] == 'X')
			{
				computer_count++;
			}
		}
		if (player_count == col)
		{
			return 'O';
		}
		if (computer_count == col)
		{
			return 'X';
		}
	}

主对角线的行标和列标相等

    //
	//判断主对角线是否全部是某方棋子
	//  0 1 2
	//0 O
	//1   O
	//2     O
	//

	player_count = 0;
	computer_count = 0;
	for (i = 0; i < row; i++)
	{
		if (board[i][i] == 'O')
		{
			player_count++;
		}
		if (board[i][i] == 'X')
		{
			computer_count++;
		}
	}
	if (player_count == col)
	{
		return 'O';
	}
	if (computer_count == col)
	{
		return 'X';
	}

副对角线的行标和列标和为定值,如(0,2),(1,1),(2,0)行列标之和均为2。

    //
	//判断副对角线是否全部是某方棋子
	//  0 1 2
	//0     O  0,2
	//1   O    1,1
	//2 O      2,0
	//

	player_count = 0;
	computer_count = 0;
	for (i = 0; i < row; i++)
	{
		if (board[i][col - 1 - i] == 'O')
		{
			player_count++;
		}
		if (board[i][col - 1 - i] == 'X')
		{
			computer_count++;
		}
	}
	if (player_count == col)
	{
		return 'O';
	}
	if (computer_count == col)
	{
		return 'X';
	}

但是这么写的话代码就有些冗余了。我的想法是可以只用一个变量count来搞定。如果是玩家的棋子count就++,电脑的棋子就--,那么判断输赢的条件就是某一行(或某一列,对角线)的count达到了正负ROW(或者COL)就分胜负。还有就是,此时直接返回数组的元素即可,不需要分类讨论。改进后的代码如下

	int i = 0;
	int j = 0;

	int count = 0;//统计棋子的个数
	
	//判断每行是否全部是某方棋子
	for (i = 0; i < row; i++)
	{
		count = 0;
		for (j = 0; j < col; j++)
		{
			if (board[i][j] == 'O')
			{
				count++;
			}
			if (board[i][j] == 'X')
			{
				count--;
			}
			if (count == col || count == -col)
			{
				return board[i][j];
			}
		}

	}

	//判断每列是否全部是某方棋子
	for (i = 0; i < col; i++)
	{
		count = 0;
		for (j = 0; j < row; j++)
		{
			if (board[j][i] == 'O')
			{
				count++;
			}
			if (board[j][i] == 'X')
			{
				count--;
			}
			if (count == row || count == -row)
			{
				return board[j][i];
			}
		}
		
	}

	//
	//判断主对角线是否全部是某方棋子
	//  0 1 2
	//0 O
	//1   O
	//2     O
	//
	count = 0;
	for (i = 0; i < row; i++)
	{
		if (board[i][i] == 'O')
		{
			count++;
		}
		if (board[i][i] == 'X')
		{
			count--;
		}
		if (count == row || count == -row)
		{
			return board[i][i];
		}
	}

	//
	//判断副对角线是否全部是某方棋子
	//  0 1 2
	//0     O  0,2
	//1   O    1,1
	//2 O      2,0
	//
	count = 0;
	for (i = 0; i < row; i++)
	{
		if (board[i][col - 1 - i] == 'O')
		{
			count++;
		}
		if (board[i][col - 1 - i] == 'X')
		{
			count--;
		}
		if (count == col || count == -col)
		{
			return board[i][col - 1 - i];
		}
	}

但事实上每次返回时只需在内层循环外头返回即可,这样判断次数就会少一些,改进代码如下

	int i = 0;
	int j = 0;

	int count = 0;//统计棋子的个数
	
	//判断每行是否全部是某方棋子
	for (i = 0; i < row; i++)
	{
		count = 0;
		for (j = 0; j < col; j++)
		{
			if (board[i][j] == 'O')
			{
				count++;
			}
			if (board[i][j] == 'X')
			{
				count--;
			}
		}
		if (count == col || count == -col)
		{
			return board[i][0];
		}
	}

	//判断每列是否全部是某方棋子
	for (i = 0; i < col; i++)
	{
		count = 0;
		for (j = 0; j < row; j++)
		{
			if (board[j][i] == 'O')
			{
				count++;
			}
			if (board[j][i] == 'X')
			{
				count--;
			}
		}
		if (count == row || count == -row)
		{
			return board[0][i];
		}
	}

	//
	//判断主对角线是否全部是某方棋子
	//  0 1 2
	//0 O
	//1   O
	//2     O
	//
	count = 0;
	for (i = 0; i < row; i++)
	{
		if (board[i][i] == 'O')
		{
			count++;
		}
		if (board[i][i] == 'X')
		{
			count--;
		}
	}
	if (count == row || count == -row)
	{
		return board[0][0];
	}

	//
	//判断副对角线是否全部是某方棋子
	//  0 1 2
	//0     O  0,2
	//1   O    1,1
	//2 O      2,0
	//
	count = 0;
	for (i = 0; i < row; i++)
	{
		if (board[i][col - 1 - i] == 'O')
		{
			count++;
		}
		if (board[i][col - 1 - i] == 'X')
		{
			count--;
		}
	}
	if (count == col || count == -col)
	{
		return board[0][col - 1];
	}

判断平局只需判断棋盘是否填满,为此我们专门写一个函数is_full来实现。这里的static是因为我们只在is_win所在的源文件内使用(因为is_full是专门为is_win写的一个函数)。,

static int is_full(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;//满了
}

然后调用is_full判断平局。

    //判断平局
	if (is_full(board, row, col) == 1)
	{
		return 'T';//tie 平局
	}

如果不分胜负还不是平局,就继续游戏。判断输赢的函数完整代码如下(包括is_full)

static int is_full(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 is_win(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;

	int count = 0;//统计棋子的个数
	
	//判断每行是否全部是某方棋子
	for (i = 0; i < row; i++)
	{
		count = 0;
		for (j = 0; j < col; j++)
		{
			if (board[i][j] == 'O')
			{
				count++;
			}
			if (board[i][j] == 'X')
			{
				count--;
			}
		}
		if (count == col || count == -col)
		{
			return board[i][0];
		}
	}

	//判断每列是否全部是某方棋子
	for (i = 0; i < col; i++)
	{
		count = 0;
		for (j = 0; j < row; j++)
		{
			if (board[j][i] == 'O')
			{
				count++;
			}
			if (board[j][i] == 'X')
			{
				count--;
			}
		}
		if (count == row || count == -row)
		{
			return board[0][i];
		}
	}

	//
	//判断主对角线是否全部是某方棋子
	//  0 1 2
	//0 O
	//1   O
	//2     O
	//
	count = 0;
	for (i = 0; i < row; i++)
	{
		if (board[i][i] == 'O')
		{
			count++;
		}
		if (board[i][i] == 'X')
		{
			count--;
		}
	}
	if (count == row || count == -row)
	{
		return board[0][0];
	}

	//
	//判断副对角线是否全部是某方棋子
	//  0 1 2
	//0     O  0,2
	//1   O    1,1
	//2 O      2,0
	//
	count = 0;
	for (i = 0; i < row; i++)
	{
		if (board[i][col - 1 - i] == 'O')
		{
			count++;
		}
		if (board[i][col - 1 - i] == 'X')
		{
			count--;
		}
	}
	if (count == col || count == -col)
	{
		return board[0][col - 1];
	}

	//判断平局
	if (is_full(board, row, col) == 1)
	{
		return 'T';//tie 平局
	}

	return 'C';//continue
}

前面我们还有玩家和电脑下棋的函数没写。先说玩家下棋的函数。我们需要判断坐标是否被占用以及坐标是否合法。很简单就能实现。

void player_move(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] = 'O';
				break;
			}
			else
			{
				printf("坐标已占用,请重新输入\n");
			}
		}
		else
		{
			printf("坐标非法,请重新输入\n");
		}
	}
}

接着是电脑下棋的函数。如果是随机下棋的话非常简单,只需要产生随机的坐标即可。

        //随机下棋
		x = rand() % row;
		y = rand() % col;

		if (board[x][y] == ' ')
		{
			board[x][y] = 'X';
			return;
		}

但在此之前要进行一些判断(因为有一些明显不错的着法)。分述如下:

第一:抢占兵家必争之地(中间位置)

	//占据中间位置
	x = (row - 1) / 2;
	y = (col - 1) / 2;
	if (board[x][y] == ' ')
	{
		board[x][y] = 'X';
		return;
	}

第二:一击必杀位置,不能憨憨的错过(进攻是最好的防守)

具体实现的时候需要假设下某个位置,然后调用判断输赢的函数,如果发现下了就赢了,那就下这里,如果下了没赢就当什么事情都没发生。

	//电脑连成2个
	for (x = 0; x < row; x++)
	{
		for (y = 0; y < col; y++)
		{
			if (board[x][y] == ' ')
			{
				board[x][y] = 'X';
				if (IsWin(board, row, col) == 'X')
				{
					return;
				}
				board[x][y] = ' ';
			}
		}
	}

第三:感知危险,堵住对手的棋(防守反击)

有了第二点,这里就很简单了,只不过是假设玩家下了一步棋。

	//玩家连成2个
	for (x = 0; x < row; x++)
	{
		for (y = 0; y < col; y++)
		{
			if (board[x][y] == ' ')
			{
				board[x][y] = 'O';
				if (IsWin(board, row, col) == 'O')
				{
					board[x][y] = 'X';
					return;
				}
				board[x][y] = ' ';
			}
		}
	}

电脑下棋函数完整的代码如下

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

	//占据中间位置
	x = (row - 1) / 2;
	y = (col - 1) / 2;
	if (board[x][y] == ' ')
	{
		board[x][y] = 'X';
		return;
	}

	//电脑连成2个
	for (x = 0; x < row; x++)
	{
		for (y = 0; y < col; y++)
		{
			if (board[x][y] == ' ')
			{
				board[x][y] = 'X';
				if (IsWin(board, row, col) == 'X')
				{
					return;
				}
				board[x][y] = ' ';
			}
		}
	}

	//玩家连成2个
	for (x = 0; x < row; x++)
	{
		for (y = 0; y < col; y++)
		{
			if (board[x][y] == ' ')
			{
				board[x][y] = 'O';
				if (IsWin(board, row, col) == 'O')
				{
					board[x][y] = 'X';
					return;
				}
				board[x][y] = ' ';
			}
		}
	}

	//随机下棋
	while (1)
	{
		x = rand() % row;
		y = rand() % col;

		if (board[x][y] == ' ')
		{
			board[x][y] = 'X';
			return;
		}
	}
}

补充一下:这个算法已经比随机下棋要强上很多了,但是仍然有一些缺陷,赢电脑其实并不难。如果要想实现完美走棋,可以使用枚举法(但代码的适用性会下降,比如五子棋你就很难枚举了),或者用更高阶的算法(比如博弈树),但那样就相对比较复杂了,我后面会单独写一篇博客来讲解。

最后说明一下,这个项目可以分为三个文件来写,分别是game.h(符号的定义和函数的声明),game.c(游戏函数的具体实现),test.c(游戏函数的测试)。代码如下:

game.h

#pragma once

#include 
#include 
#include 

#define ROW 3 //行
#define COL 3 //列

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

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

//玩家下棋
void player_move(char board[ROW][COL], int row, int col);

//电脑下棋
void computer_move(char board[ROW][COL], int row, int col);

//判断输赢
char is_win(char board[ROW][COL], int row, int col);

game.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "game.h"

static int is_full(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 is_win(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;

	int count = 0;//统计棋子的个数
	
	//判断每行是否全部是某方棋子
	for (i = 0; i < row; i++)
	{
		count = 0;
		for (j = 0; j < col; j++)
		{
			if (board[i][j] == 'O')
			{
				count++;
			}
			if (board[i][j] == 'X')
			{
				count--;
			}
		}
		if (count == col || count == -col)
		{
			return board[i][0];
		}
	}

	//判断每列是否全部是某方棋子
	for (i = 0; i < col; i++)
	{
		count = 0;
		for (j = 0; j < row; j++)
		{
			if (board[j][i] == 'O')
			{
				count++;
			}
			if (board[j][i] == 'X')
			{
				count--;
			}
		}
		if (count == row || count == -row)
		{
			return board[0][i];
		}
	}

	//
	//判断主对角线是否全部是某方棋子
	//  0 1 2
	//0 O
	//1   O
	//2     O
	//
	count = 0;
	for (i = 0; i < row; i++)
	{
		if (board[i][i] == 'O')
		{
			count++;
		}
		if (board[i][i] == 'X')
		{
			count--;
		}
	}
	if (count == row || count == -row)
	{
		return board[0][0];
	}

	//
	//判断副对角线是否全部是某方棋子
	//  0 1 2
	//0     O  0,2
	//1   O    1,1
	//2 O      2,0
	//
	count = 0;
	for (i = 0; i < row; i++)
	{
		if (board[i][col - 1 - i] == 'O')
		{
			count++;
		}
		if (board[i][col - 1 - i] == 'X')
		{
			count--;
		}
	}
	if (count == col || count == -col)
	{
		return board[0][col - 1];
	}

	//判断平局
	if (is_full(board, row, col) == 1)
	{
		return 'T';//tie 平局
	}

	return 'C';//continue
}

void init_board(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 display_board(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 < row - 1)
			{
				printf("|");
			}
		}
		printf("\n");

		//打印分割行
		if (i < row - 1)
		{
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)
				{
					printf("|");
				}
			}
		}
		printf("\n");
	}
}

void player_move(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] = 'O';
				break;
			}
			else
			{
				printf("坐标已占用,请重新输入\n");
			}
		}
		else
		{
			printf("坐标非法,请重新输入\n");
		}
	}
}

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

	//占据中间位置
	x = (row - 1) / 2;
	y = (col - 1) / 2;
	if (board[x][y] == ' ')
	{
		board[x][y] = 'X';
		return;
	}

	//电脑连成2个
	for (x = 0; x < row; x++)
	{
		for (y = 0; y < col; y++)
		{
			if (board[x][y] == ' ')
			{
				board[x][y] = 'X';
				if (IsWin(board, row, col) == 'X')
				{
					return;
				}
				board[x][y] = ' ';
			}
		}
	}

	//玩家连成2个
	for (x = 0; x < row; x++)
	{
		for (y = 0; y < col; y++)
		{
			if (board[x][y] == ' ')
			{
				board[x][y] = 'O';
				if (IsWin(board, row, col) == 'O')
				{
					board[x][y] = 'X';
					return;
				}
				board[x][y] = ' ';
			}
		}
	}

	//随机下棋
	while (1)
	{
		x = rand() % row;
		y = rand() % col;

		if (board[x][y] == ' ')
		{
			board[x][y] = 'X';
			return;
		}
	}
}

test.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 game()
{
	//存储下棋的数据
	char board[ROW][COL] = { 0 };

	//初始化棋盘为全空格
	init_board(board, ROW, COL);

	//打印棋盘
	display_board(board, ROW, COL);

	char ret = 0;

	while (1)
	{
		//玩家下棋
		player_move(board, ROW, COL);
		display_board(board, ROW, COL);
		ret = is_win(board, ROW, COL);
		if (ret != 'C')
		{
			break;
		}

		//电脑下棋
		computer_move(board, ROW, COL);
		display_board(board, ROW, COL);
		is_win(board, ROW, COL);
		ret = is_win(board, ROW, COL);
		if (ret != 'C')
		{
			break;
		}
	}
	if (ret == 'O')
	{
		printf("玩家赢\n");
	}
	else if (ret == 'X')
	{
		printf("电脑赢\n");
	}
	else
	{
		printf("平局\n");
	}
	display_board(board, ROW, COL);
}

void test()
{
	int input = 0;
	srand((unsigned int)time(NULL));

	do
	{
		menu();
		printf("请输入:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			//printf("三子棋\n");
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误,重新选择\n");
			break;
		}
	} while (input);
}

int main()
{
	test();

	return 0;
}

其中game.h的第一行是防止头文件被重复引用,可以省略。game.c和test.c的第一行是因为我在VS编译器里测试代码,为了解决scanf函数报错问题而写的。如果不是VS系列编译器可以省略掉这行代码。

创作不易,如果你觉得这篇博客对你有帮助的话,麻烦点个免费的赞,谢啦。

你可能感兴趣的:(c语言,开发语言,后端,算法,蓝桥杯)