C语言三子棋(超详细注释+完整代码)

专业:电子信息 工科男
有一点思考,有一点想法,有一点理性!

文章目录

  • 前言
  • 一、基本流程
  • 二、具体步骤
    • 1. 创建test.c和game.c源文件以及 game.h头文件
    • 2. 创建菜单
    • 3. 创建棋盘并初始化
      • 3.1 创建棋盘
      • 3.2 初始化棋盘
    • 4. 打印菜单
    • 5. 玩家下棋
    • 6. 电脑下棋
    • 7. 判断输赢
  • 三、程序源码


前言

用C语言实现三子棋小游戏


一、基本流程

1:创建菜单,通过菜单界面选择开始游戏或退出游戏
2:创建棋盘并且初始化
3:打印棋盘
4:玩家下棋
5:电脑下棋
6:判输输赢

二、具体步骤

1. 创建test.c和game.c源文件以及 game.h头文件

注:各文件作用解释如下
1:test.c代码为整个程序的主题实现逻辑
2:game.c代码为游戏函数的定义
3:game.h代码为游戏函数的声明

2. 创建菜单

在test.c文件中创建菜单函数。
代码如下(示例):

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

注:玩家选择1进入游戏,0退出游戏

3. 创建棋盘并初始化

棋盘示例如下:
C语言三子棋(超详细注释+完整代码)_第1张图片

3.1 创建棋盘

char board[ROW][COL] = { 0 };
#define ROW 3
#define COL 3

使用宏定义的原因
1.推高代码可读性,后续代码中遇到3,方便理解含义。
2.提高扩展性,如果将来要修改棋盘尺寸,代码修改会很方便。

3.2 初始化棋盘

如上图可知:棋盘初始化数据应为空格
代码如下:

//初始化棋盘,将其打印成空格
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] = ' ';
		}
	}
}

4. 打印菜单

注:
1:先打印数据和 |(最后一列不打印)
2:再打印 -----(最后一行不打印) 和 |(最后一列不打印)

代码如下:

//打印棋盘
void display_board(char board[ROW][COL], int row, int col)
{
	//1:打印数据和 |(最后一列不打印)
	//2:再打印 -----(最后一行不打印) 和 |(最后一列不打印)
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < col; j++)
		{
			printf(" %c ", board[i][j]);
			if (j < col - 1)
			{
				printf("|");
			}
		}
		printf("\n");

		if (i < row - 1)
		{
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)
				{
					printf("|");
				}
			}
			printf("\n");
		}
	}
}

5. 玩家下棋

注:玩家下棋代码需要考虑因数如下
1:输入的合法性,即必须输入棋盘的有效范围才行,即1-row,1-col。
2:该位置是否被占用
3:玩家输入坐标是1-3,棋盘坐标是0-2

代码如下:

//玩家下棋
void player_move(char board[ROW][COL], int row, int col)
{
	//1:输入坐标的合法性
	//2:该位置是否被占用
	int x = 0;
	int y = 0;
	printf("-----------------------------------\n");   //分割每次下棋的棋盘,便于观察
	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");
		}
	}
}

6. 电脑下棋

注:电脑下棋代码需要考虑因数如下
1:随机生成两个数,横坐标x,纵坐标y.
2:该位置是否被占用

//电脑下棋
void computer_move(char board[ROW][COL], int row, int col)
{
	printf("电脑下棋\n");
	int x = rand() % row;
	int y = rand() % col;
	while (1)
	{
		if (board[x][y] == ' ')   
		{
			board[x][y] = '#';
			break;
		}
	}
}

注:生成随机数需要用到rand()函数,但是多次运行代码会发现rand()函数会生成的随机数一样。故需要在使用前调用前采用如下代码,同时需要引用头文件#include 和#include

srand((unsigned)time(NULL))

7. 判断输赢

判断输赢情况:
1.玩家赢 *
2.电脑赢 #
3.平局 Q
4.继续 C
由上述可知,还需要一个返回值ret去判断输赢情况,游戏结束一共有3种情况,玩家赢,电脑赢,平局。不管是电脑赢还是玩家赢都是3个子相同时(3行相同,3列相同,两个对角线相同)才会退出。而平局则是如果棋盘满了还没有人赢,则平局。故同时还需要一个判断棋盘是否满了的函数。

代码如下:

//判断棋盘是否满了
//0为空 1为满
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;
	
}

上述代码是判断棋盘是否满了,棋盘满了返回1,否则返回0

char is_win(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];
		}
	}

	//列相同
	int j = 0;
	for (j = 0; j < col; j++)
	{
		if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[0][j] != ' ')
		{
			return board[0][j];
		}
	}

	//对角线相同
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
	{
		return board[0][0];
	}

	if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[0][2] != ' ')
	{
		return board[2][0];
	}
	
	if (is_full(board, ROW, COL) == 1)
	{
		printf("平局\n");
	}
	return 'C';
}

上述代码判断游戏结束的情况,并且将返回值传给test.c中的游戏函数以判断游戏最终情况

最终情况判断如下:

	if (ret == '*')
	{
		printf("玩家赢了\n");
	}
	else if (ret == '#')
	{
		printf("电脑赢了\n");
	}
	else
	{
		printf("平局\n");
	}
	display_board(board, ROW, COL);
}

三、程序源码

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 ret = '0';
	char board[ROW][COL] = { 0 };
	//1:初始化棋盘(数据)
	init_board(board, ROW, COL);

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

	while (1)
	{
		//3:玩家下棋
		player_move(board, ROW, COL);
		display_board(board, ROW, COL);
		ret = is_win(board, ROW, COL);
		if (ret != 'C')   //判断游戏是否结束了
			break;

		//4:电脑下棋
		//电脑下棋要随机是生成一个坐标
		computer_move(board, ROW, COL);
		display_board(board, ROW, COL);
		if (ret != 'C')
			break;
	}

	//5:判断输赢
	//1:玩家赢   *
	//2:电脑赢    #
	//3:平局      Q
	//4:继续	  C

	if (ret == '*')
	{
		printf("玩家赢了\n");
	}
	else if (ret == '#')
	{
		printf("电脑赢了\n");
	}
	else
	{
		printf("平局\n");
	}
	display_board(board, ROW, COL);
}


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中代码

#define _CRT_SECURE_NO_WARNINGS 1

#include "game.h"


//初始化棋盘,将其打印成空格
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)
{
	//1:打印数据和 |(最后一列不打印)
	//2:再打印 -----(最后一行不打印) 和 |(最后一列不打印)
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < col; j++)
		{
			printf(" %c ", board[i][j]);
			if (j < col - 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)
{
	//1:输入坐标的合法性
	//2:该位置是否被占用
	int x = 0;
	int y = 0;
	printf("-----------------------------------\n");   //分割每次下棋的棋盘,便于观察
	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 computer_move(char board[ROW][COL], int row, int col)
{
	printf("电脑下棋\n");
	int x = rand() % row;
	int y = rand() % col;
	while (1)
	{
		if (board[x][y] == ' ')   
		{
			board[x][y] = '#';
			break;
		}
	}
}

//判断棋盘是否满了
//0为空 1为满
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;
	
}


//判断输赢
//游戏结束情况:
//1:玩家赢
//2:电脑赢
//3:平局
//4:棋盘满了
char is_win(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];
		}
	}

	//列相同
	int j = 0;
	for (j = 0; j < col; j++)
	{
		if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[0][j] != ' ')
		{
			return board[0][j];
		}
	}

	//对角线相同
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
	{
		return board[0][0];
	}

	if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[0][2] != ' ')
	{
		return board[2][0];
	}
	
	if (is_full(board, ROW, COL) == 1)
	{
		printf("平局\n");
	}
	return 'C';
}

game.h中代码

#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);

以上就是本游戏的全部代码,程序是在VS2019环境下实现

你可能感兴趣的:(C语言小项目,c语言,c++,开发语言)