C语言—3字棋(N字棋)的实现

三子棋 ​​​​​​​​​​

在这里插入图片描述

前言

三子棋是一个经典的游戏,也是一个简单益脑的游戏,在如今的地位也是十分的受欢迎,所以我们如何用C语言去实现呢?让我们继续一探究竟


一、主要思路

如果我们想要实现一个不小的程序,我们分别用 game.h,game.c,test.c 一个头文件,两个源代码,game.h 我们用来声明函数作为接口函数和定义一些变量 game.c 主要是用来对游戏函数的实现。 test.c 就是我们整个的测试程序 把他分为3个文件,可以理清我们的思路 关于3字棋的棋盘,首先我们的思路就是去创建一个棋盘,我们创建棋盘需要怎么做呢,一上来的想法就是创建一个二维数组去用来实现。这就是我们一上来能想到的一些思路


二、代码模块

1. test.c

首先做一个菜单函数 menu()

void menu()
{
	printf("********************************\n");
	printf("***********1.进入游戏***********\n");
	printf("***********0.退出游戏***********\n");
	printf("********************************\n");
}

用do while语句使循环至少运行一次,用switch语句进行判断,此时我们把case 0设置为退出,正好判断0为假可以跳出循环

int main()
{
	int input=0;
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		printf("请选择:>\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出成功\n");
			break;
		default:
			printf("输入错误,请重新输入:\n");
			break;
		}
	
	} while (input);
	return 0;
}

这里是整个下棋的流程。我们创建game()函数 创建一个二维数组,把数组长度用ROW COL来定义 这样方便我们以后修改棋盘的格数


void game()
{
	char ret = 0;
	char board[ROW][COL] = { 0 };
	init_board(board, ROW, COL);
	display_board(board, ROW, COL);	
	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);
		ret = is_win(board, ROW, COL);
		if (ret != 'C')
			break;
		
	}
	if (ret == '*')			 //*玩家赢 #电脑赢 Q平局 C继续游戏
	{
		printf("玩家赢!\n");
	}              
	else if (ret == '#')
	{
		printf("电脑赢!\n");
	}
	else if (ret == 'Q')
	{
		printf("平局\n");
	}
	
	
	
}

这里我们在每次玩家和电脑下棋之后进行判断,用一行if进行判断是否继续这样也可以避免判断三行的输赢关系,避免了垄长的代码。
还有我们这里用*来代表玩家赢,#代表了电脑赢,一会会在game.c讲到

2. game.h

接口函数

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


#define ROW 3
#define COL 3

void display_board(char board[ROW][COL], int row, int col);   //展示出棋盘
void init_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); //判断输赢

3. game.c

打印棋盘

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

在这里插入图片描述

如果我们想实现出这样的棋盘,在每一列中要打印出空格%c空格和丨
为了美观在最后一列中没有丨所以要进行判断,同理打印—和丨也是一样的方法,这里要注意的是在最后一行也是没有—丨—丨—所以我们要有一个条件进行判断


初始化函数

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

这里要注意的是如果把每个数组赋为\0的话会造成棋盘位置不美观,如下图

在这里插入图片描述


玩家下棋

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

我们都知道在数组中第一个元素是0,但是玩家认为第一行第一列是1,所以我们要以玩家考虑,并且使得玩家输入的在棋盘之中。


电脑下棋

void computer_move(char board[ROW][COL], int row, int col)
{
	printf("电脑下棋:>\n");
	
	while (1)
	{
		int x = rand() % row;  //放在循环内部 每次都重新赋一个值 
		int y = rand() % col;
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}

}

假如我们设计的是三子棋这里我们设计一个随机值使得 x,y的范围在0-2之内


判断输赢
*代表玩家赢 #代表电脑赢 Q代表平局 C代表继续游戏

char is_win(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 (j > 0 && board[i][j] == board[i][j + 1] && board[i][j] == board[i][j - 1] && j < col - 1 && board[i][j] != ' ')
			{
				return board[i][j];
			}
			//列
			if (i > 0 && board[i][j] == board[i+1][j] && board[i][j]==board[i-1][j] && i < row - 1 && board[i][j] != ' ')
			{
				return board[i][j];
			}
			//两对角线
			if (i > 0 && j > 0 && board[i][j] == board[i + 1][j + 1] && board[i][j] == board[i - 1][j - 1] && i < row - 1 && j < col - 1 && board[i][j] != ' ')
			{
				return board[i][j];
			}
			if (i > 0 && j > 0 && board[i][j] == board[i + 1][j - 1] && board[i][j] == board[i - 1][j + 1] && i < row - 1 && j < col - 1 && board[i][j] != ' ')
			{
				return board[i][j];
			}
		}
	}
	//判断平局
	if (is_full(board, row, col) == 1)
	{
		return 'Q';
	}
	//游戏继续
	return 'C';
}

上面我们讲到判断胜利的条件返回值是*或者#,这样正好就在game()函数中 *和#来判断 可以直接返回任意一个数组,很方便。 不用再返回个1


判断棋盘空满

static int is_full(char board[ROW][COL],int row,int col) //满了返回1 不满返回0
{
	int i = 0;             //static修饰的函数 只能在本文件引用 其他文件中不能引用
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < col; j++)
		{
			if (board[i][j] == ' ')
			{
				return 0;
			}
		}
	}
	return 1;
}

这里我们用一个static关键字 用处是限制只能在本文件之中引用,不能被以外的代码文件调用,函数设立为静态函数,具有唯一性。


运行程序

在这里插入图片描述

总结

以上就是今天的内容,整的来说代码难度不大,重要的是整个流程的思路,希望发表的这篇文章可以让大家有一个明确的思路,获得一定的收获,谢谢大家!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值