数组的实现 -- 三子棋小游戏 --(C语言实现)详解

三子棋游戏–数组的实现–(C语言)详解

文章目录

  • 前言
  • 一、三子棋游戏基本思路
  • 二、设计游戏
    • 1.三子棋游戏主函数大概框架
    • 2.编写游戏程序构成
  • 三、游戏整体代码
  • 总结


前言

随着C语言的不断学习,练习也显的很重要,本文通过三子棋小游戏加强了C语言函数,循环,选择,数组等学习基础内容的理解。


一、三子棋游戏基本思路

1、设计棋盘
2、设计过程,游戏玩家如何走,电脑如何走
3、存储数据判断输赢状态

二、设计游戏

1.三子棋游戏主函数大概框架

1)、游戏需要先开始一把,可以用do while语句实现
2)、利用菜单让玩家选择,利用switch语句判断是否开始游戏
3)、do while循环条件用input,当玩家input输入错误时,可跳出switch语句,while(input)判断后重新进入switch

代码如下(示例):

void menu()
{
	printf("*************************");
	printf("*******   1.play  *******");
	printf("*******   0.exit  *******");
	printf("*************************");
}
int main()
{
	int input;
	do
	{
		menu();
		printf("请输入:<");
		scanf("%d", &input);
		switch (input)
		{
		case 1 :
			printf("玩三子棋游戏");
			break;
		case 0 : 
			printf("退出游戏");
			break;
		default :
			printf("输入错误,重新输入");
			break;
		}
	} while (input);
	return 0;
}

2.编写游戏程序构成

1)初始化棋盘,设定棋盘大小
假定3*3的棋盘,棋盘大小固定为3,会有游戏限制,调整为自定义棋盘,棋盘大小可用定义全局变量的方式,
例如:#define ROW 3
三子棋是一个3 * 3的棋盘,存储数据需要一个二维数组,(需要初始化一下数组,不然随机值无法控制,不利于查看)
修改前
代码如下(示例):

void game()
{
	char board[3][3];//存储数据
	InitBoard(board, 3, 3);//初始化棋盘
	DisplayBoard(board, 3, 3);//打印棋盘
}
void InitBoard(char board[3][3],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 DisplayBoard(char board[3][3], 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 game()
{
	char board[ROW][COL];//存储数据
	InitBoard(board, ROW, COL);//初始化棋盘
	DisplayBoard(board, ROW, COL);//打印棋盘
}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("|");// |打印次数少 %c 一次
		}
		printf("\n");
		if (i < row - 1)//打印"---|---|---"少于" |  |  "一次,把空格|看作一个整体
		{
			int j = 0;
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < row - 1)//打印|次数少于---一次
				{
					printf("|");
				}
			}
			printf("\n");
		}
	}
}

棋盘测试样例:
数组的实现 -- 三子棋小游戏 --(C语言实现)详解_第1张图片
2)玩家,电脑下棋
参数传入,需要判断玩家下棋是否符合规则
—玩家下棋坐标与数组认为的坐标不同,玩家下棋的坐标比数组认为坐标+1(数组下标从0开始),
所以用数组下标时记得-1(x-1,y-1).
—玩家下棋需要先判断输入坐标是否符合范围,符合时还需判断所下坐标是否已经有值,坐标==‘ ’时玩家落子,再跳出循环.
—电脑走,需要用到rand函数产生随机坐标
----rand
(注释)不能 直接调用rand函数(产生随机数,不调用srand产生随机数一样), 要在rand的之前调用srand(设置一个随机起点)。
rand 函数返回了一个0-32767直接的数字
rand和srand 两个函数头文件:
----time函数返回时间戳,time函数返回值类型为整型需要我们强制转换一下(转换成unsigned int),
unsigned int 为srand需要的值,(unsigned int)time (NULL))不想放东西,给time放一个空指针
头文件

	
	void PlayerMove(char board[ROW][COL], int row, int col)
{
	int x;
	int y;
	printf("玩家先走,请输入坐标:>\n");
	//玩家输入行走坐标
	scanf("%d %d", &x, &y);
	while (1)//玩家输入错误时需要再次输入用到循环
	{
		if (x >= 1 && x <= row && y>=1 && y <= col)//判断坐标是否在范围内
		{
			if (board[x-1][y-1] == ' ')
			{
				board[x - 1][y - 1] = '*';
				break;//防止死循环,当输入正确时跳出循环
			}
			else
			{
				printf("该位置已被占用,请更换坐标");
			}
		}
		else
		{
			printf("输入坐标超出范围,请重新输入");
		}
	}
}
void ComputerMove(char board[ROW][COL], int row, int col)
{
	printf("电脑走:>\n");
	//电脑走,自己可以设定电脑走的坐标范围
	int x = rand()%row;
	//对rand()生成的随机数取模,将0-32767的所有数转化为余数0-2范围内
	int y = rand()%col;//同上
	while (1)
	{
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
}
	}

3)游戏过程中的情况判断游戏的状态
4种游戏状态:玩家赢–返回*,电脑赢–返回#,平局–返回Q,游戏继续–返回C;

赢得三种结果:
1.判断三行,一行相同即为赢,并排除全是空格的赢法
【注】执行函数时,当一行(列)相同时不用判断(是 * 还是#,Q,C)直接返回一行(列)里的任意一个值
2.判断三列(用循环)
3.判断对角线(直接用数组)

平局–看棋盘中是否还有空格(用双重循环判断)

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][0];
		}
	}
	//判断三列
	for (i = 0; i < col; i++)
	{
		if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
		{
			return board[1][i];
		}
	}
	//判断对角线
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
	{
		return board[0][0];
	}
	if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')
	{
		return board[0][2];
	}
	//判断平局,平局返回1,否则返回0
	int ret = IsFull(board, ROW, COL);
	if (ret == 1)
	{
		return 'Q';
	}
	//返回C游戏继续
	return 'C';
}

三、游戏整体代码

//头文件包含
#include
#include
#include
//符号定义
#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);
//玩家下棋
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);
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 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("|");// |打印次数少 %c 一次
		}
		printf("\n");
		if (i < row - 1)//打印"---|---|---"少于" |  |  "一次,把空格|看作一个整体
		{
			int j = 0;
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < row - 1)
				{
					printf("|");
				}
			}
			printf("\n");
		}
	}
}
void PlayerMove(char board[ROW][COL], int row, int col)
{
	int x;
	int y;
	printf("玩家先走,请输入坐标:>\n");
	//玩家输入行走坐标
	scanf("%d %d", &x, &y);
	while (1)//玩家输入错误时需要再次输入用到循环
	{
		if (x >= 1 && x <= row && y>=1 && y <= col)//判断坐标是否在范围内
		{
			if (board[x-1][y-1] == ' ')
			{
				board[x - 1][y - 1] = '*';
				break;//防止死循环,当输入正确时跳出循环
			}
			else
			{
				printf("该位置已被占用,请更换坐标");
			}
		}
		else
		{
			printf("输入坐标超出范围,请重新输入");
		}
	}
}
void ComputerMove(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;
		}
	}
}
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][0];
		}
	}
	//判断三列
	for (i = 0; i < col; i++)
	{
		if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
		{
			return board[1][i];
		}
	}
	//判断对角线
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
	{
		return board[0][0];
	}
	if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')
	{
		return board[0][2];
	}
	//判断平局,平局返回1,否则返回0
	int ret = IsFull(board, ROW, COL);
	if (ret == 1)
	{
		return 'Q';
	}
	//继续
	return 'C';
}
void menu()
{
	printf("*************************\n");
	printf("*******   1.play  *******\n");
	printf("*******   0.exit  *******\n");
	printf("*************************\n");
}

void game()
{
	char board[ROW][COL];//存储数据
	InitBoard(board, ROW, COL);//初始化棋盘
	DisplayBoard(board, ROW, COL);//打印棋盘
	int ret = 0;
	while (1)
	{
		//玩家下棋
		PlayerMove(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		ret = IsWin(board, ROW, COL);
		if (ret != 'C')
		{
			break;
		}
		//电脑下棋
		ComputerMove(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		ret = IsWin(board, ROW, COL);
		if (ret != 'C')
		{
			break;
		}
	}
	if (ret == '*')
	{
		printf("玩家赢了\n");
	}
	else if (ret == '#')
	{
		printf("电脑赢了\n");
	}
	else if (ret == "Q")
	{
		printf("平局\n");
	}
	DisplayBoard(board, ROW, COL);
}
int main()
{
	int input;
	srand((unsigned int)time(NULL));//使用一次所以在主函数中调用
	do
	{
		menu();
		printf("请输入:<");
		scanf("%d", &input);
		switch (input)
		{
		case 1 :
			game();
			break;
		case 0 : 
			printf("退出游戏");
			break;
		default :
			printf("输入错误,重新输入");
			break;
		}
	} while (input);
	return 0;
}

总结

以上就是三子棋代码详解内容,三子棋代码对我们C语言练习有很大帮助,对于函数的使用,数组循环的使用有了更深的理解,文章可能有错误,如有发现希望各位读友指正。

你可能感兴趣的:(c语言,算法)