详解C语言三子棋

一 需求分析

我们需要建3个文件来实现三子棋游戏:1.test.c文件是用来测试代码的;2.game.h文件是函数的声明;3.game.c是函数的实现.具体的内容会在实现步骤里面写.
整个代码的逻辑其实就是:
1.需求分析;
2.需求的实现;
3.调试和运行;
需求分析:1.打印菜单的逻辑; 2.初始化棋盘的内容为空; 3.对棋盘的打印; 4.玩家下棋;5.电脑下棋; 6.判断输赢
只要这个分析好了 ,代码的实现就容易很多.
需求的实现:根据上面的分析,写出每个分析用函数封装起来,然后在函数里面实现,需要用的时候直接调用就好了.
调试和运行:在写代码时,需要我们写一点代码就运行和调试,这样就可以快速找到和解决问题了.

这就是整个代码实现的逻辑啦

二 实现步骤

2.1菜单的打印

为了使主函数main里面的内容简单点,我们写一个函数来实现菜单打印的逻辑;

#define _CRT_SECURE_NO_WARNINGS 1

#include"game.h"
void menu()
{
	printf("***********************************************\n");
	printf("**********           1. play          *********\n");
	printf("**********           0. exit          *********\n");
	printf("***********************************************\n");
}
void test()
{
	printf("请选择->\n");
	menu();
	int input = 0;
	do
	{
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			//game()函数;玩游戏的实现
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误,请重新输入\n");
			break;
		}
	} while (input);
}
int main()
{
	test();
	return 0;
}

这就完成了整个菜单逻辑的打印了,实现起来很简单

2.2初始化棋盘内容

现在进入了整个三子棋游戏部分的实现,我们把游戏实现部分用一个game();函数封装起来,首先是实现初始化棋盘内容,把玩三子棋看作是一个字符型的二维数组,我们需要用一个三行三列的二维数组的形式把他存起来.
我们是写了一个init_board( );函数来实现这个功能,这个函数在game.h文件里面声明,在这个game();函数中调用

//初始化棋盘内容函数的实现
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] = ' ';
		}
	}
}

2.3棋盘的打印

可以根据自己喜欢的样子打印棋盘,我们写了一个print_board( );函数来实现这个功能,这个函数在game.h文件里面声明,在这个game();函数中调用

//打印棋盘内容函数的实现
void print_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");
		}
	}
}

棋盘打印出来的样子
在这里插入图片描述

2.4玩家下棋

玩家输入对应的x,y坐标,来确定下棋的位置,如果坐标为空则输入’*'代表玩家的落子位置,玩家下棋这个过程是一个循环,直到平局或者玩家赢或者电脑赢才结束.
我们是写了一个player_move( );这个函数来实现玩家下棋的功能,这个函数在game.h文件中声明,在game( );函数中调用.

//玩家下棋函数的实现
player_move(char board[ROW][COL], int row, int col)
{
	printf("玩家下棋\n");
	while (1)
	{
		int x = 0;
		int y = 0;
		printf("请输入对应的坐标\n");
		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");
		}
	}
	
}

2.5电脑下棋

电脑下棋我们需要生成随机坐标,需要用到rand()函数来实现,使用rand函数前需要使用sand()函数,srand又需要时间戳来产生随机种子,头文件的包含有#include<stdlib.h>和#include<time.h>
电脑输入对应的x,y坐标,来确定下棋的位置,如果坐标为空则输入’#'代表电脑的落子位置,电脑下棋这个过程是一个循环,直到平局或者玩家赢或者电脑赢才结束.
我们是写了一个computer_move( );这个函数来实现电脑下棋的功能,这个函数在game.h文件中声明,在game( );函数中调用.

//电脑下棋
//在test();函数中使用了srand函数,不然rand生成的随机数每次开始玩游戏都是一样的坐标
void computer_move(char board[ROW][COL], int row, int col)
{
	int x = rand() % row;
	int y = rand()% col;
	printf("电脑下棋");
	while (1)
	{
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
		
	}
}

2.6判断输赢

我们写了一个is_win函数来判断是玩家赢,还是电脑赢, 平局返回Q,继续返回C
玩家赢返回’*’
电脑赢返回’#’
平局返回’Q’
继续返回’C’

//判断是否平局,棋盘满了还没有返回则是平局,返回字母Q
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;
}

//判断输赢
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];
		}
	}

	//判断列是否相等
	for (i = 0; i < col; i++)
	{
		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 (is_full(board, row, col)==1)
	{
		return 'Q';
	}
		return 'C';
}

玩家赢:
在这里插入图片描述

平局:
在这里插入图片描述
电脑赢:
在这里插入图片描述
下面三个文件就是三子棋游戏的代码

2.7 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];//ROW COL在game.h中宏定义为3
	init_board(board, ROW, COL);
	print_board(board, ROW, COL);
	while (1)
	{
		player_move(board, ROW, COL);
		print_board(board, ROW, COL);//落子后打印
		//判断是否赢
		ret = is_win(board, ROW, COL);
		if (ret != 'C')
		{
			break;
		}
		computer_move(board, ROW, COL);
		print_board(board, ROW, COL);//落子后打印
		//判断是否赢
		ret = is_win(board, ROW, COL);
		if (ret != 'C')
		{
			break;
		}
	}
	if (ret == '*')
		{
			printf("玩家赢\n");
		}
		else if (ret == '#')
		{
			printf("电脑赢\n");
		}
		else 
		{
			printf("平局\n");
		}
}
void test()
{
	srand((unsigned int)time(NULL));
	
	int input = 0;
	do
	{
		printf("请选择->\n");
		menu();
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			//game()函数;玩游戏的实现
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);
}
int main()
{
	test();
	return 0;
}

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

//玩家下棋函数的实现
void player_move(char board[ROW][COL], int row, int col)
{
	printf("玩家下棋\n");
	while (1)
	{
		int x = 0;
		int y = 0;
		printf("请输入对应的坐标\n");
		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");
	while (1)
	{
		int x = rand() % row;
		int y = rand() % col;
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
		
	}
}

//判断是否平局,棋盘满了还没有返回则是平局,返回字母Q
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;
}

//判断输赢
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];
		}
	}

	//判断列是否相等
	for (i = 0; i < col; i++)
	{
		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 (is_full(board, row, col)==1)
	{
		return 'Q';
	}
		return 'C';
}

2.9 game.h文件的代码

#pragma once

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

#define ROW 3
#define COL 3
//初始化棋盘内容的函数声明
void init_board(char board[ROW][COL], int row, int col);
//打印棋盘的内容函数声明
void print_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);

三 总结

整个代码的逻辑其实就是:
1.需求分析;
2.需求的实现;
3.调试和运行
需求分析:1.打印菜单的逻辑; 2.初始化棋盘的内容为空; 3.对棋盘的打印; 4.玩家下棋;5.电脑下棋; 6.判断输赢
只要这个分析好了 ,代码的实现就容易很多.
需求的实现:根据上面的分析,写出每个分析用函数封装起来,然后在函数里面实现,需要用的时候直接调用就好了.
调试和运行: 在写代码时,需要我们写一点代码就运行和调试,这样就可以快速找到和解决问题了.

这就是整个代码实现的逻辑啦

注意:
1.在设定行和列的时候我们可以用#define来定义,如果要修改行和列的话 就可以直接在#define定义里面修改;
2.使用随机坐标时,要用到随机值,rand函数可以生成随机值,但是每次程序开始运行时,都是一样的值,所以在使用rand函数前要使用srand函数,srand函数使用时,需要一个随时变化的值,那么这个值可以是时间戳,需要使用time这个函数;

完结~
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小卜~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值