三子棋作为一款经典的小游戏,对于初学C语言的我们如果 可以熟练了解并可以实现其游戏功能,则对于以后更系统的学习C语言有很好帮助。下来我分享一下我在编程时的感悟和代码

首先介绍一下三子棋规则:只要将自己的棋连成一条线(行,列,斜线),即为赢 如图:

先根据图和玩法大致有个思路:

1.我们可以将棋盘看做是一个三行三列的二维数组,且每行每列用线隔开以便区分 2.分为电脑下棋和玩家下棋(电脑先下和玩家先下) 3.判断输赢(玩家赢,电脑赢和平局)

大致思路即为上面分析,下面开始写代码:

创建tset.c,game.c和head.h三个文件

1.在test.c中编写主函数并写出游戏菜单

在这里我分为电脑先下和玩家先下,代码如下;

void menu()
{
	printf("***************************************\n");
	printf("*      1.play             0.exit      *\n");
	printf("***************************************\n");
}
void first_move()
{
	printf("***************************************\n");
	printf("*  1.computer first   2.player first  *\n");
	printf("***************************************\n");
}
void game()
{
   return 0;
}
int main()
{
	int choice;
	srand((unsigned int)time(NULL));//产生随机数
	do
	{
		menu();  
		printf("请选择:");
		scanf("%d", &choice);
		switch (choice)
		{
		case 1:
			game();
			break;
		case 0:
			break;
		default:
			printf("输入错误请重新输入.\n");
			break;
		}
	} while (choice);
	return 0;
}

2.下来逐步在game.c中实现所需功能并且在game函数中调用

先打印出棋盘,并将棋盘初始化为空格。代码如下;

void show_board(char board[ROWS][COLS], int rows, int cols)//打印棋盘
{
	int i;
	for (int i = 0; i < rows; i++)
	{
		printf("  %c | %c | %c  \n", board[i][0], board[i][1], board[i][2]);
		if (i != rows - 1)
			printf(" ---|---|--- \n");
	}
}

void init_board(char board[ROWS][COLS], int rows, int cols)//将数组初始化为空格
{
	int i, j;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			board[i][j] = ' ';
		}
	}
}

效果如图

3.编写玩家落子的代码

玩家数输入二维数组的坐标,这时需要判断玩家输入坐标是否合理以及在此坐标上是否有棋子,代码如下;

void player_move(char board[ROWS][COLS], int rows, int cols)//玩家落子
{
	int x, y;
	printf("玩家落子:\n");
	while (1)
	{
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= rows && y >= 1 && y <= cols)
		{
			if (board[x - 1][y - 1] == ' ')
			{
				board[x - 1][y - 1] = '*';
				break;
			}
			else printf("位置已被占用!请再试一次。\n");
		}
		else printf("输入错误!请重新输入.\n");
	}
}

4.玩成电脑落子

这里实现的是电脑在为空格的数组中随机落子。代码如下;

void computer_move(char board[ROWS][COLS], int rows, int cols)// 电脑落子
{

	int x, y;
	printf("电脑落子:\n");
	while (1)
	{
		x = rand() % rows;
		y = rand() % cols;
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
}

5.最后就只剩判断输赢

先讨论玩家或者电脑赢的情况;代码如下;

char check_win(char board[ROWS][COLS], int rows, int cols)//判断输赢
{
	int i;
	for (i = 0; i < rows; i++)
	{
		if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
			return board[i][1];
	}
	for (i = 0; i < cols; i++)
	{
		if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
			return board[1][i];
	}
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
		return board[1][1];
	else if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] != ' ')
		return board[1][1];
	else if (is_full(board, rows, cols))
		return 'q';
	return 0;
}

这是考虑是平局的情况,平局则为棋盘下满都没有输赢,可以遍历整个数组(棋盘)若没有空格就为平局。代码如下;

static int is_full(char board[ROWS][COLS], int rows, int cols)//检测是否为平局
{
	int i, j;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			if (board[i][j] == ' ')
				return 0;
		}
	}
	return 1;
}

初步测试结果如下

在图中我们可以看出电脑可以有赢的机会却在随机下子,这样的游戏是没有挑战的。因此应该修改下电脑下子的代码,使其智能化。我们可在电脑落子时判断如果有在同行,同列或者斜线上有相同棋子的,电脑则优先落子在其未成一条线的空格处,这样实现简单智能化

代码如下;

void computer_move(char board[ROWS][COLS], int rows, int cols)//智能化电脑落子
{
	int x, y, i;
	printf("电脑落子:\n");
	while (1)
	{
		x = rand() % rows;
		y = rand() % cols;
		for (i = 0; i < rows; i++)
		{
			if (board[i][0] == board[i][1] && board[i][0] == '#' && board[i][2] == ' ')
			{
				board[i][2] = '#';
				goto flag1;
			}
			else if (board[i][1] == board[i][2] && board[i][1] == '#' && board[i][0] == ' ')
			{
				board[i][0] = '#';
				goto flag1;
			}
			else if (board[i][0] == board[i][2] && board[i][2] == '#' && board[i][1] == ' ')
			{
				board[i][1] = '#';
				goto flag1;
			}
			else if (board[0][i] == board[1][i] && board[0][i] == '#' && board[2][i] == ' ')
			{
				board[2][i] = '#';
				goto flag1;
			}
			else if (board[1][i] == board[2][i] && board[1][i] == '#' && board[0][i] == ' ')
			{
				board[0][i] = '#';
				goto flag1;
			}
			else if (board[0][i] == board[2][i] && board[2][i] == '#' && board[1][i] == ' ')
			{
				board[1][i] = '#';
				goto flag1;
			}
			else if (board[0][0] == board[1][1] && board[0][0] == '#' && board[2][2] == ' ')
			{
				board[2][2] = '#';
				goto flag1;
			}
			else if (board[1][1] == board[2][2] && board[1][1] == '#' && board[0][0] == ' ')
			{
				board[0][0] = '#';
				goto flag1;
			}
			else if (board[0][0] == board[2][2] && board[0][0] == '#' && board[1][1] == ' ')
			{
				board[1][1] = '#';
				goto flag1;
			}
			else if (board[0][2] == board[1][1] && board[1][1] == '#' && board[2][0] == ' ')
			{
				board[2][0] = '#';
				goto flag1;
			}
			else if (board[1][1] == board[2][0] && board[1][1] == '#' && board[0][2] == ' ')
			{
				board[0][2] = '#';
				goto flag1;
			}
			else if (board[2][0] == board[0][2] && board[2][0] == '#' && board[1][1] == ' ')
			{
				board[1][1] = '#';
				goto flag1;
			}
		}
		for (i = 0; i < rows; i++)
		{
			if (board[i][0] == board[i][1] && board[i][0] == '*' && board[i][2] == ' ')
			{
				board[i][2] = '#';
				goto flag1;
			}
			else if (board[i][1] == board[i][2] && board[i][1] == '*' && board[i][0] == ' ')
			{
				board[i][0] = '#';
				goto flag1;
			}
			else if (board[i][0] == board[i][2] && board[i][2] == '*' && board[i][1] == ' ')
			{
				board[i][1] = '#';
				goto flag1;
			}
			else if (board[0][i] == board[1][i] && board[0][i] == '*' && board[2][i] == ' ')
			{
				board[2][i] = '#';
				goto flag1;
			}
			else if (board[1][i] == board[2][i] && board[1][i] == '*' && board[0][i] == ' ')
			{
				board[0][i] = '#';
				goto flag1;
			}
			else if (board[0][i] == board[2][i] && board[2][i] == '*' && board[1][i] == ' ')
			{
				board[1][i] = '#';
				goto flag1;
			}
			else if (board[0][0] == board[1][1] && board[0][0] == '*' && board[2][2] == ' ')
			{
				board[2][2] = '#';
				goto flag1;
			}
			else if (board[1][1] == board[2][2] && board[1][1] == '*' && board[0][0] == ' ')
			{
				board[0][0] = '#';
				goto flag1;
			}
			else if (board[0][0] == board[2][2] && board[0][0] == '*' && board[1][1] == ' ')
			{
				board[1][1] = '#';
				goto flag1;
			}
			else if (board[0][2] == board[1][1] && board[1][1] == '*' && board[2][0] == ' ')
			{
				board[2][0] = '#';
				goto flag1;
			}
			else if (board[1][1] == board[2][0] && board[1][1] == '*' && board[0][2] == ' ')
			{
				board[0][2] = '#';
				goto flag1;
			}
			else if (board[2][0] == board[0][2] && board[2][0] == '*' && board[1][1] == ' ')
			{
				board[1][1] = '#';
				goto flag1;
			}
		}
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			goto flag1;
		}
	}
flag1:;
}

效果如图;

检测所有结果

电脑赢 玩家赢 平局

全部代码

tese.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"head.h"
void menu()
{
	printf("***************************************\n");
	printf("*      1.play             0.exit      *\n");
	printf("***************************************\n");
}
void first_move()
{
	printf("***************************************\n");
	printf("*  1.computer first   2.player first  *\n");
	printf("***************************************\n");
}
void game()
{
	int choice, win;
	char board[ROWS][COLS];
	init_board(board, ROWS, COLS);
	first_move();
flag:
	printf("请选择");
	scanf("%d", &choice);
	switch (choice)
	{
	case 1: //电脑先落子
		do
		{
			computer_move(board, ROWS, COLS);   //电脑落子
			show_board(board, ROWS, COLS);      //打印棋盘
			win = check_win(board, ROWS, COLS); 
			if (win != 0)  //没赢
				break;
			player_move(board, ROWS, COLS);     //玩家落子
			show_board(board, ROWS, COLS);      // 打印棋盘
			win = check_win(board, ROWS, COLS);
		} while (win == 0);
		if (win == '#')
			printf("很遗憾,你输了!\n");
		if (win == '*')
			printf("恭喜,你赢了!\n");
		if (win == 'q')
			printf("平局\n");
		break;
	case 2: //玩家先落子
		show_board(board, ROWS, COLS);
		do
		{
			player_move(board, ROWS, COLS);
			show_board(board, ROWS, COLS);
			win = check_win(board, ROWS, COLS);
			if (win != 0)
				break;
			computer_move(board, ROWS, COLS);
			show_board(board, ROWS, COLS);
			win = check_win(board, ROWS, COLS);
		} while (win == 0);
		if (win == '#')
			printf("很遗憾,你输了!\n");
		if (win == '*')
			printf("恭喜,你赢了!\n");
		if (win == 'q')
			printf("平局\n");
		break;
	default:
		printf("输入错误,请重新输入\n");
		goto flag;
	}
}
int main()
{
	int choice;
	srand((unsigned int)time(NULL));//产生随机数
	do
	{
		menu();  
		printf("请选择:");
		scanf("%d", &choice);
		switch (choice)
		{
		case 1:
			game();
			break;
		case 0:
			break;
		default:
			printf("输入错误请重新输入.\n");
			break;
		}
	} while (choice);
	return 0;
}

** game.c**

#define _CRT_SECURE_NO_WARNINGS 1
#include"head.h"

void show_board(char board[ROWS][COLS], int rows, int cols)//打印棋盘
{
	int i;
	for (int i = 0; i < rows; i++)
	{
		printf("  %c | %c | %c  \n", board[i][0], board[i][1], board[i][2]);
		if (i != rows - 1)
			printf(" ---|---|--- \n");
	}
}

void init_board(char board[ROWS][COLS], int rows, int cols)//将数组初始化为空格
{
	int i, j;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			board[i][j] = ' ';
		}
	}
}


//void computer_move(char board[ROWS][COLS], int rows, int cols)// 电脑落子
//{
//
//	int x, y;
//	printf("电脑落子:\n");
//	while (1)
//	{
//		x = rand() % rows;
//		y = rand() % cols;
//		if (board[x][y] == ' ')
//		{
//			board[x][y] = '#';
//			break;
//		}
//	}
//}
void computer_move(char board[ROWS][COLS], int rows, int cols)//智能化电脑落子
{
	int x, y, i;
	printf("电脑落子:\n");
	while (1)
	{
		x = rand() % rows;
		y = rand() % cols;
		for (i = 0; i < rows; i++)
		{
			if (board[i][0] == board[i][1] && board[i][0] == '#' && board[i][2] == ' ')
			{
				board[i][2] = '#';
				goto flag1;
			}
			else if (board[i][1] == board[i][2] && board[i][1] == '#' && board[i][0] == ' ')
			{
				board[i][0] = '#';
				goto flag1;
			}
			else if (board[i][0] == board[i][2] && board[i][2] == '#' && board[i][1] == ' ')
			{
				board[i][1] = '#';
				goto flag1;
			}
			else if (board[0][i] == board[1][i] && board[0][i] == '#' && board[2][i] == ' ')
			{
				board[2][i] = '#';
				goto flag1;
			}
			else if (board[1][i] == board[2][i] && board[1][i] == '#' && board[0][i] == ' ')
			{
				board[0][i] = '#';
				goto flag1;
			}
			else if (board[0][i] == board[2][i] && board[2][i] == '#' && board[1][i] == ' ')
			{
				board[1][i] = '#';
				goto flag1;
			}
			else if (board[0][0] == board[1][1] && board[0][0] == '#' && board[2][2] == ' ')
			{
				board[2][2] = '#';
				goto flag1;
			}
			else if (board[1][1] == board[2][2] && board[1][1] == '#' && board[0][0] == ' ')
			{
				board[0][0] = '#';
				goto flag1;
			}
			else if (board[0][0] == board[2][2] && board[0][0] == '#' && board[1][1] == ' ')
			{
				board[1][1] = '#';
				goto flag1;
			}
			else if (board[0][2] == board[1][1] && board[1][1] == '#' && board[2][0] == ' ')
			{
				board[2][0] = '#';
				goto flag1;
			}
			else if (board[1][1] == board[2][0] && board[1][1] == '#' && board[0][2] == ' ')
			{
				board[0][2] = '#';
				goto flag1;
			}
			else if (board[2][0] == board[0][2] && board[2][0] == '#' && board[1][1] == ' ')
			{
				board[1][1] = '#';
				goto flag1;
			}
		}
		for (i = 0; i < rows; i++)
		{
			if (board[i][0] == board[i][1] && board[i][0] == '*' && board[i][2] == ' ')
			{
				board[i][2] = '#';
				goto flag1;
			}
			else if (board[i][1] == board[i][2] && board[i][1] == '*' && board[i][0] == ' ')
			{
				board[i][0] = '#';
				goto flag1;
			}
			else if (board[i][0] == board[i][2] && board[i][2] == '*' && board[i][1] == ' ')
			{
				board[i][1] = '#';
				goto flag1;
			}
			else if (board[0][i] == board[1][i] && board[0][i] == '*' && board[2][i] == ' ')
			{
				board[2][i] = '#';
				goto flag1;
			}
			else if (board[1][i] == board[2][i] && board[1][i] == '*' && board[0][i] == ' ')
			{
				board[0][i] = '#';
				goto flag1;
			}
			else if (board[0][i] == board[2][i] && board[2][i] == '*' && board[1][i] == ' ')
			{
				board[1][i] = '#';
				goto flag1;
			}
			else if (board[0][0] == board[1][1] && board[0][0] == '*' && board[2][2] == ' ')
			{
				board[2][2] = '#';
				goto flag1;
			}
			else if (board[1][1] == board[2][2] && board[1][1] == '*' && board[0][0] == ' ')
			{
				board[0][0] = '#';
				goto flag1;
			}
			else if (board[0][0] == board[2][2] && board[0][0] == '*' && board[1][1] == ' ')
			{
				board[1][1] = '#';
				goto flag1;
			}
			else if (board[0][2] == board[1][1] && board[1][1] == '*' && board[2][0] == ' ')
			{
				board[2][0] = '#';
				goto flag1;
			}
			else if (board[1][1] == board[2][0] && board[1][1] == '*' && board[0][2] == ' ')
			{
				board[0][2] = '#';
				goto flag1;
			}
			else if (board[2][0] == board[0][2] && board[2][0] == '*' && board[1][1] == ' ')
			{
				board[1][1] = '#';
				goto flag1;
			}
		}
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			goto flag1;
		}
	}
flag1:;
}

void player_move(char board[ROWS][COLS], int rows, int cols)//玩家落子
{
	int x, y;
	printf("玩家落子:\n");
	while (1)
	{
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= rows && y >= 1 && y <= cols)
		{
			if (board[x - 1][y - 1] == ' ')
			{
				board[x - 1][y - 1] = '*';
				break;
			}
			else printf("位置已被占用!请再试一次。\n");
		}
		else printf("输入错误!请重新输入.\n");
	}
}

static int is_full(char board[ROWS][COLS], int rows, int cols)//检测是否为平局
{
	int i, j;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			if (board[i][j] == ' ')
				return 0;
		}
	}
	return 1;
}

char check_win(char board[ROWS][COLS], int rows, int cols)//判断输赢
{
	int i;
	for (i = 0; i < rows; i++)
	{
		if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
			return board[i][1];
	}
	for (i = 0; i < cols; i++)
	{
		if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
			return board[1][i];
	}
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
		return board[1][1];
	else if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] != ' ')
		return board[1][1];
	else if (is_full(board, rows, cols))
		return 'q';
	return 0;
}

head.h

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

#define ROWS 3
#define COLS 3

void show_board(char board[ROWS][COLS], int rows, int cols);//打印棋盘
void init_board(char board[ROWS][COLS], int rows, int cols);//初始化棋盘为空格
void computer_move(char board[ROWS][COLS], int rows, int cols);//电脑落子
void player_move(char board[ROWS][COLS], int rows, int cols);//玩家落子
char check_win(char board[ROWS][COLS], int rows, int cols);//判断输赢