【C语言】实现三子棋,附完整代码及详解

努力,就从现在开始。不要为逝去的的时间惋惜,也不要为未至的明天忧虑,你能把握的就只有当下的时光。


前言

本篇为用C语言实现三子棋,用到的知识点为函数和循环,总体不难容易掌握,重点在功能实现的逻辑。那就跟随yena,一起来思考如何来实现这个小游戏吧~


提示:以下是本篇文章正文内容,下面案例可供参考

1.三子棋准备阶段

首先·,我们要建一个test.c文件,用于实现游戏的主体功能
建一个game.c文件,存放所有函数的定义代码
最后,建一个game.h头文件,用于存放此项目所用到的所有头文件,以及函数的声明

这个游戏总体逻辑分为以下步骤。

2.菜单打印

打印菜单,菜单的样子如下所示。先确认是否进入游戏,选择1,进入;选择0,退出;选择其他数字,则显示输入错误。此处需要用到while循环和switch语句,大家有想法了没?
在这里插入图片描述

答案如下
// void menu()
{
	printf("*************************************\n");
	printf("****  1.开始游戏     0.退出游戏  ****\n");
	printf("*************************************\n");
}
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);

3.游戏实现

3.1 棋盘初始化及打印

用户选择1后开始游戏,需要让用户看一下初始棋盘的样子,需要打印的棋盘如下。这个棋盘由棋子和格子构成。这里的棋子,我们要定义一个二维数组,大家观察下面的棋盘,会发现初始化的棋盘没有棋子,其实,这里的棋子被初始化为空格。棋盘的格子打印需要普通的循环,方法不唯一,能打出来即可。大家动手尝试一下吧。
在这里插入图片描述

答案如下。注意,此处为代码片。此函数的定义是放在game.c里
函数的声明放在game.h里
#define ROW 3
#define COL 3
这样定义棋盘的行列数,之后想改变棋盘尺寸时直接改此处即可。
char board[ROW][COL] = { 0 };
	//初始化棋盘的函数
	InitBoard(board, ROW, COL);
	DispalyBoard(board, ROW, COL);
	
//棋子初始化函数定义
void InitBoard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			board[i][j] = ' ';
		}
	}
}

//打印棋盘函数定义
void DispalyBoard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		//打印数据
		//printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
		int j = 0;
		for (j = 0; j < col; j++)
		{
			printf(" %c ", board[i][j]);
			if (j < col - 1)
				printf("|");
		}
		printf("\n");
		//打印分割信息
		//printf("---|---|---\n");
		if (i < row - 1)
		{
			int j = 0;
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)
					printf("|");
			}
			printf("\n");
		}
	}
}

3.2 玩家与电脑竞技

实现玩家下棋,电脑下棋,以及判断胜负的功能。玩家手动输入所选的坐标,电脑自动选择位置。有一方占满一行或一列或一条对角线,则此方胜利,若棋盘已满不分胜负,则平局。样例如下图
在这里插入图片描述
在这里插入图片描述

3.2.1 下棋实现

3.2.1.1 玩家下棋实现

玩家通过输入选择的坐标来下棋,首先要判断此时游戏是否未结束(此代码之后说明),以及此坐标大小是否合理,此坐标是否被占用,若满足以上条件,执行玩家下棋函数。玩家下的棋子用‘*’显示,,为方便用户使用,用户输入的坐标从1 1开始。

代码实现如下
// 玩家下棋函数定义

// void PlayerMove(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] = '*';
				break;
			}
			else
			{
				printf("坐标被占用,不能下棋,请选择其他位置\n");
			}
		}
		else
		{
			printf("坐标非法,请重新输入\n");
		}
	}
}
3.2.1.2 电脑下棋实现

电脑自动选择坐标下棋,电脑下的棋用‘#’显示。此处要用到rand()函数,rand()函数为电脑获取随机的一个大于0的整数,因为电脑选择的坐标范围是0~2,需要x=rand()%3来实现,因为任意一个整数对3取余数,就只有0,1,2的可能,那随机获取1至100呢,就是rand()%99+1啦。为保证每次选择的坐标不同,需要在主函数添加srand((unsigned int)time(NULL));代码这个代码是时间戳,保证每个时刻获取的坐标不同。这里需要<stdlib.h>以及<time.h>头文件

具体实现如下
void ComputerMove(char board[ROW][COL], int row, int col)
{
	printf("电脑下棋:>\n");

	int x = 0;
	int y = 0;

	while (1)
	{
		x = rand() % row;//0~2
		y = rand() % col;//0~2
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
}

3.3 胜负判断

若有一方一行,一列,一条对角线连成一条线,则此方胜利,若棋盘已满,但没有胜负,则平局。

3.3.1 行,列,对角线判断

代码实现如下
//行
	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][1];//
		}
	}

	//列
	int j = 0;
	for (j = 0; j < col; j++)
	{
		if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] != ' ')
		{
			return board[1][j];
		}
	}
	//对角线
	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];
	}

3.3.2 平局判断实现

若代码全满且无胜负之分,为平局。

代码实现如下
int IsFull(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			if (board[i][j] == ' ')
			{
				return 0;
			}
		}
	}
	return 1;
}

4.附完整代码

4.1 test.c

test.c用于游戏总体逻辑实现
玩家赢,返回‘*’;电脑赢,返回‘#’;平局,返回‘Q’;
否则,游戏继续,返回‘C’。
#define _CRT_SECURE_NO_WARNINGS

#include "game.h"

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

void game()
{
	char ret = 0;
	char board[ROW][COL] = { 0 };
	//初始化棋盘的函数
	InitBoard(board, ROW, COL);
	DispalyBoard(board, ROW, COL);
	//下棋
	while (1)
	{
		PlayerMove(board, ROW, COL);
		//判断输赢
		ret = IsWin(board, ROW, COL);

		if (ret != 'C')
		{
			break;
		}
		DispalyBoard(board, ROW, COL);
		ComputerMove(board, ROW, COL);
		//判断输赢
		ret = IsWin(board, ROW, COL);
		if (ret != 'C')
		{
			break;
		}
		DispalyBoard(board, ROW, COL);
	}
	if (ret == '*')
	{
		printf("玩家赢\n");
	}
	else if (ret == '#')
	{
		printf("电脑赢\n");
	}
	else if(ret=='Q')
	{
		printf("平局\n");
	}
	DispalyBoard(board, ROW, COL);
}

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;
}

4.2 game.c

game.c用于存放所有代码定义,注意因为包含的头儿文件为
自定义的头文件,包含格式为#include " game.h "
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"


void InitBoard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			board[i][j] = ' ';
		}
	}
}

//第一个版本
//void DispalyBoard(char board[ROW][COL], int row, int col)
//{
//	int i = 0;
//	for (i = 0; i < row; i++)
//	{
//		//打印数据
//		printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
//		//打印分割信息
//		if(i<row-1)
//			printf("---|---|---\n");
//	}
//}

void DispalyBoard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		//打印数据
		//printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
		int j = 0;
		for (j = 0; j < col; j++)
		{
			printf(" %c ", board[i][j]);
			if (j < col - 1)
				printf("|");
		}
		printf("\n");
		//打印分割信息
		//printf("---|---|---\n");
		if (i < row - 1)
		{
			int j = 0;
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)
					printf("|");
			}
			printf("\n");
		}
	}
}

void PlayerMove(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] = '*';
				break;
			}
			else
			{
				printf("坐标被占用,不能下棋,请选择其他位置\n");
			}
		}
		else
		{
			printf("坐标非法,请重新输入\n");
		}
	}
}

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

	int x = 0;
	int y = 0;

	while (1)
	{
		x = rand() % row;//0~2
		y = rand() % col;//0~2
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
}

//满了就返回1
//不满  返回0
int IsFull(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			if (board[i][j] == ' ')
			{
				return 0;
			}
		}
	}
	return 1;
}

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][1];//
		}
	}

	//列
	int j = 0;
	for (j = 0; j < col; j++)
	{
		if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] != ' ')
		{
			return board[1][j];
		}
	}
	//对角线
	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))
	{
		return 'Q';
	}

	//游戏继续
	return 'C';
}

4.3 game.h

// A code block
var foo = 'bar';
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define ROW 3
#define COL 3

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

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

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

//电脑下棋
//找没有下棋的随机下棋
void ComputerMove(char board[ROW][COL], int row, int col);

//
//玩家赢 - '*'
//电脑赢 - '#'
//平局 - 'Q'
//继续 - 'C'
//

char IsWin(char board[ROW][COL], int row, int col); 

总结

此代码需要注意的细节很多,需要大家在动手实践的过程中,细细思考,做好笔记。本篇文章到这里就终于结束啦!!!

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值