C语言实现三子棋(胎教版教学)由浅入深

举报
鸽芷咕 发表于 2023/09/27 23:59:42 2023/09/27
【摘要】 快来用C语言实现你的第一个项目把!教你一步步构建多文件形式的三子棋

@TOC

三子棋介绍

三子棋 是一种民间传统游戏,又叫九宫棋、井字棋等。游戏分为双方对战,双方依次在9宫格棋盘上摆放棋子,率先将自己的三个棋子走成一条线就视为胜利。

在这里插入图片描述

确定步骤开始配置文件

我们选择的是用多文件的形式教大家独立完成,三子棋游戏的实现
首先我们要准备三个文件分别是 game.h 来声明函数 game.c 来实现函数的定义 test.c 大体的文件架构就完成了
在这里插入图片描述

游戏代码的实现

步骤一、确定文件主体test.c的几个部分

  • 一、游戏的菜单来确定是否开始和退出

输入1为开始游戏输入0为退出游戏

#include “game.h”//由于我们要调用game.h头文件所以其他需要的头文件
				//就全部放在game.h里面避免代码冗余,让代码更加简洁
//菜单
void menu()
{
	printf("************************\n");
	printf("*******  1.play  *******\n");
	printf("*******  0.exit  *******\n");
	printf("************************\n");
}
int main()
{

	int input = 0;	//创建变量来接收输入的结果
	do
	{   
		//打印菜单
		menu();
		printf("请输入你的选择 >");
		scanf("%d",&input);
		switch (input)
		{
			//开始游戏
		case 1:
			game();//这里先写出游戏函数后面实现
			break; 
			//退出游戏
		case 0: 
			printf("退出游戏!\n");
			break;
		default:
			printf("输入错误,请重新输入!");
			break;
		}
	} while (input);
	return 0;
}

1、编写 game() 函数的主体

  • 1、棋盘的初始化
  • 2、打印棋盘
  • 3、玩家下棋    棋子用 * 表示
  • 4、电脑下棋    棋子用 # 表示
  • 5、判断输赢
    • 玩家赢返回 *****
    • 电脑赢返回 #
    • 平局返回 Q
    • 继续返回 C

1、棋盘的初始化

观察棋盘三子棋盘是3×3的所以我们用3×3的数组存储棋子并完成初始化

void game()//三子棋游戏主体函数
{
	char board[ROW][COL] = {0};
	//初始化数组
	InitBoard(board, ROW, COL);
}
在这里插入代码片

然后先创建实现5个小功能的函数后面再调用

//三子棋游戏
void game()
{
	char board[ROW][COL] = {0};
	//初始化数组
	InitBoard(board, ROW, COL);
	char ret = 0;//用来接收输赢函数返回的  值
	char play = 0;//用来接收下棋坐标被占用的返回值
	//打印棋盘
	DisplayBoard(board, ROW, COL);
	while (1)//创建一个循环只要没有人赢就一直下
	{
		//玩家下棋
		play = PlayMove(board, ROW, COL);
		if (play == 'P')//当下棋时坐标输入错误和坐标被占用就退出循环
				continue;//不让电脑下棋
		//判断输赢
		ret = IsWin(board, ROW, COL);//接收每次判断的结果
		if (ret != 'C')//当返回的不是 C 继续的话就退出说明有人赢了
		{
			system("cls");//退出时清空所有棋盘并打印一遍
			//打印棋盘
			DisplayBoard(board, ROW, COL);		
			break;
		}		
		//打印棋盘
		DisplayBoard(board, ROW, COL);
		//电脑下棋
		ComputerMove(board, ROW, COL);
		system("cls");//每次下完棋后清空屏幕所有内容并打印一遍棋盘
		//打印棋盘	  //让每次屏幕上只有一个棋盘
		DisplayBoard(board, ROW, COL);
		//判断输赢
		ret = IsWin(board, ROW, COL);
		if (ret != 'C')//当返回的不是 C 继续的话就退出说明有人赢了
		{				//就进入if里面结束本次循环
			system("cls");//退出时清空所有棋盘并打印一遍
			//打印棋盘
			DisplayBoard(board, ROW, COL);
			break;
		}
	}
	if (ret == '*')
	{
		printf("玩家赢!\n");
	}
	else if (ret == '#')
	{
		printf("电脑赢!\n");
	}
	else 
	{
		printf("平局!\n");
	}
}

步骤二、game.h 头文件的声明

前面已经把游戏拆成了5个小部分接下来就是声明和定义了

  • 声明和经常使用的头文件,我们把它都放在 game.h 的头文件里
#pragma once
#include <stdio.h> //输入输出头文件
#include <stdlib.h> //获取随机函数头文件 后面会用
#include <time.h> //srand函数所需要获取时间戳的头文件 后面会用
#define ROW 3 //棋盘的行
#define COL 3 //棋盘的列
//初始化数组
void InitBoard(char board[ROW][COL],int row,int col);
//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col);
//玩家下棋
int PlayMove(char board[ROW][COL], int row, int col);
//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col);
//判断输赢
char IsWin(char board[ROW][COL], int row, int col);
//平局
int  IsFull(char board[ROW][COL], int row, int col);

步骤三、game.c 的函数实现

各种函数名和 函数声明 我们已经完成了接下来就是在 game.c 里面实现这些小功能

#include "game.h"//先在game.c里面调用
				//在game.h里面声明的头文件和函数

1、初始化棋子数组函数的实现

用循环遍历数组的棋子使里面存放的都是空格

//初始化数组	
void InitBoard(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] = ' ';
		}
	}

}

2、打印棋盘函数的实现

在这里插入图片描述

观察棋盘发现 分为2个部分组成

在这里插入图片描述

  • 第一部分是 (空格 棋子 空格 | 空格 棋子 空格 | 空格 棋子 空格)
  • 第二部分是 (- - - | - - - | - - -)而每个部分都要输出三次

所以我们用for循环来写
| 每行只有俩个所以要写个if判断

//打印棋盘
void DisplayBoard(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++)
		{
			printf(" %c ",board[i][j]);
			if(j < col-1)
				printf("|");
			
		}
		printf("\n");
		for (j = 0; j < col; j++)
		{
			printf("---");
			if (j < col - 1)
				printf("|");
		}
		printf("\n");

		
	}

}

3、玩家下棋函数的实现

这边接收的是玩家输入的坐标 一般是1 开始 到 3
但是数组下标是从0开始所以把每次玩家输入的行和列 - 1 就好了

//玩家下棋
int  PlayMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("玩家下棋");
	printf("请输入坐标,中间用空格隔开 ->");
	
	scanf("%d %d",&x,&y);
	//检查坐标是否合法
	if (x >= 1 && y >= 1 && x <= row  && y <= col )
	{
		if (board[x - 1][y - 1] == ' ')
		{
			 board[x - 1][y - 1] = '*';
		}
		else
		{
			printf("坐标被占用请重新输入!\n");
			return 'P';
		}
	}
	else
	{
		printf("输入错误请重新输入!\n");
		return 'P';
	}
	
}

4、电脑下棋函数的实现

我们让电脑每次产生随机数坐标 产生行和列 来下棋

//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col)
{
	//随机下棋
	int x = 0;
	int y = 0;
	printf("电脑下棋:>\n");
	while (1)
	{
		x = rand() % row;//产生的随机数模除我们需要的行 产生的数就在行0~3之内了
		y = rand() % col;
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
	
}

5、判断输赢函数的实现

//玩家赢返回 *
//电脑赢返回 #
//平局返回   Q
//继续返回	 C
char IsWin(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][1] != ' ')
		{
			return board[i][0];
		}
		//判断列
		if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
		{
			return board[0][i];
		}		
	}
	//判断对角线
	if (board[0][0] == board[1][1] && board[1][1] ==  board[2][2] && board[1][1] != ' ')
		return board[1][1];
	//判断对角线
	if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
		return board[1][1];
	//判断平局
	if (IsFull(board, row, col) == 1)
	{
		return 'Q';
	}
	else 
	{
		return 'C';
	}
	//继续 C
}

6、判断平局函数的实现

遍历一遍数组当数组里面存放的没有空格就说明棋盘满了 平局

//平局
int IsFull(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;
}

整体代码如下:

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};
	//初始化数组
	InitBoard(board, ROW, COL);
	char ret = 0;
	char play = 0;
	//打印棋盘
	 DisplayBoard(board, ROW, COL);
	while (1)
	{
		//玩家下棋
		play = PlayMove(board, ROW, COL);
		if (play == 'P')
			continue;
		//判断输赢
		ret = IsWin(board, ROW, COL);
		if (ret != 'C')
		{
			system("cls");
			//打印棋盘
			DisplayBoard(board, ROW, COL);		
			break;
		}		
		//打印棋盘
		DisplayBoard(board, ROW, COL);
		//电脑下棋
		ComputerMove(board, ROW, COL);
		system("cls");
		//打印棋盘
		DisplayBoard(board, ROW, COL);
		//判断输赢
		ret = IsWin(board, ROW, COL);
		if (ret != 'C')
		{	
			system("cls");
			//打印棋盘
			DisplayBoard(board, ROW, COL);
			
			break;
		}
	}
	if (ret == '*')
	{
		printf("玩家赢!\n");
	}
	else if (ret == '#')
	{
		printf("电脑赢!\n");
	}
	else 
	{
		printf("平局!\n");
	}
}
int main()
{

	int input = 0;	
	do
	{   
		srand((unsigned int)time(NULL));
		//打印菜单
		menu();
		printf("请输入你的选择 >");
		scanf("%d",&input);
		switch (input)
		{
			//开始游戏
		case 1:
			game();
			break; 
			//退出游戏
		case 0: 
			printf("退出游戏!");
			break;
		default:
			printf("输入错误,请重新输入!");
			break;
		}
	} while (input);
	return 0;
}

game.h代码

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdlib.h>
#define ROW 3
#define COL 3
//初始化数组
void InitBoard(char board[ROW][COL],int row,int col);
//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col);
//玩家下棋
int PlayMove(char board[ROW][COL], int row, int col);
//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col);
//判断输赢
char IsWin(char board[ROW][COL], int row, int col);
//平局
int  IsFull(char board[ROW][COL], int row, int col);

game.c代码

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
//初始化数组	
void InitBoard(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 DisplayBoard(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++)
		{
			printf(" %c ",board[i][j]);
			if(j < col-1)
				printf("|");
			
		}
		printf("\n");
		for (j = 0; j < col; j++)
		{
			printf("---");
			if (j < col - 1)
			{
				
				printf("|");
			}
				
		}
		printf("\n");

		
	}

}

//玩家下棋
int  PlayMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("玩家下棋");
	printf("请输入坐标,中间用空格隔开 ->");
	
	scanf("%d %d",&x,&y);
	//检查坐标是否合法
	if (x >= 1 && y >= 1 && x <= row  && y <= col )
	{
		if (board[x - 1][y - 1] == ' ')
		{
			 board[x - 1][y - 1] = '*';
		}
		else
		{
			printf("坐标被占用请重新输入!\n");
			return 'P';
		}
	}
	else
	{
		printf("输入错误请重新输入!\n");
		return 'P';
	}
	
}

//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col)
{
	//随机下棋
	int x = 0;
	int y = 0;
	printf("电脑下棋:>\n");
	while (1)
	{
		x = rand() % row;
		y = rand() % col;
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
	
}
//玩家赢 *
//电脑赢 #
//平局   Q
//继续	 C
char IsWin(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][1] != ' ')
		{
			return board[i][0];
		}
		//判断列
		if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
		{
			return board[0][i];
		}
		
	}
	//判断对角线
	if (board[0][0] == board[1][1] && board[1][1] ==  board[2][2] && board[1][1] != ' ')
		return board[1][1];
	//判断对角线
	if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
		return board[1][1];
	//判断平局
	if (IsFull(board, row, col) == 1)
	{
		return 'Q';
	}
	else 
	{
		return 'C';
	}
	//继续 C

	

}
//平局
int IsFull(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;
}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。