用数组实现三子棋-进来速看

本文详细描述了如何使用模块化编程实现三子棋游戏,包括初始化棋盘、打印棋盘、玩家和电脑下棋以及判断输赢的过程。通过使用头文件和函数声明,提高了代码的可读性和可维护性。
摘要由CSDN通过智能技术生成

①前言

在这里插入图片描述
三子棋游戏分为双方对战,双方依次在9宫格棋盘上摆放棋子,率先将自己的三个棋子连成一条线即(一行,一列,对角线)的一方则视为胜利者。

我们既然知道游戏规则,那我们开始构思如何实现三子棋,通过目录我么大致可以把代码分成四个模块,如果所有的函数均放在都放在一个main.c里,若使用的模块比较多,则一个文件内会有很多的代码,不利于代码的组织和管理,而且很影响编程者的思路。
所以把各个模块的代码放在不同的.c文件里,在.h文件里提供外部可调用函数的声明,其它.c文件想使用其中的代码时,只需要#include "XXX.h"文件即可。使用模块化编程可极大的提高代码的可阅读性、可维护性、可移植性等。
创建两个.c文件和一个.h文件
我们在test.c里放上游戏的测试(包含初始化棋盘函数,打印棋盘函数,下棋部分实现等等)
首先我们需要设计一个菜单用于进入游戏后玩家开始选择,增加游戏整体的美观。
菜单展示
玩家进入到游戏界面开始选择1.开始玩游戏 2.退出游戏
我们用一个do while()循环实现菜单和游戏的主题部分。

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		menu();//**我们在这里设计一个打印菜单的函数**
		printf("请选择:>");
		scanf("%d", &input);//**我们输入的数字就三种1 0 其他**
		switch (input)
		{
		case 1:
			game();//进入到game.c里实现游戏
			break;
		case 0:
			printf("退出游戏\n");//退出游戏
			break;
		default:
			printf("选择错误,重新选择\n");//重新选择
			break;
		}
	} while (input);


	return 0;
}

打印菜单函数实现

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

我们输入的数字就三种1 0 其他
1 开始游戏
0 退出游戏
其他 重新开始

②初始化棋盘

先在game.h里声明InitBoard初始化函数在这里插入图片描述
头文件game.h里用#define定义两个常量,后期修改只需要改这两个就都改了,方便设计成多子棋

//初始化棋盘
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] = ' ';
		}
	}
}

在game.c里实现初始化棋盘的操作。
定义一个三行三列的二维数组board[3][3],我们用两个嵌套的for循环把数组chne初始化全为空格“ ”。为什么不初始化为0呢,初始化为空格方便我们直接输入符号经行游戏。

③打印棋盘

三子棋又叫做井子棋,是因为他的棋盘是井字形。
三子棋棋盘
我们这里为了棋盘的美观好看,我们也需要把棋盘打印成井字形。
//打印棋盘

//打印棋盘
void DisplayBoard(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++)
		{
			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");
	}
}

打印棋盘这里,我们需要注意两点:
1.printf(" %c ",board[i][j]); 在打印这个空格是我们打印的属于字符,所以需要用%c来替换,其次是%c前后各有两个空格,方便对应我们棋盘上的“— — —
2.其次我们没打印完一行,都需要在打印三个短横线,用作分割线。
printf(“_ _ _”);
if (j < col - 1)
{
printf(“|”);
}
分割线打完之后还需要打印COL-1个“|”竖分割线。

④开始下棋

头文件里申明三个函数
头文件里生明三个头文件。

一.玩家下棋

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

我们这里采用输入坐标的方式来完成坐标的输入,当我们输入2 2时在棋盘上会自己打印“*”,用这样的方式来完成坐标的输入。
2  2坐标处
这里我们需要注意两点:
1.数组是0 1 2的三行三列,但对应我们的棋盘坐标是从1 2 3开始的。上面的数组元素坐标是 1 1,但对于我们玩家来说默认输入都是从1开始,而非0开始。
(x >= 1 && x <= row && y >= 1 && y <= col)
2.我们数完坐标只能说成功了一半,我们还需要检测坐标的正确性,是否被占用。
如果被占用我们需要重新输入。
我们这里只需要家检测输入之前该处坐标是否为“ ”空格即可。
if (board[x - 1][y - 1] == ’ ')

二.电脑下棋

srand((unsigned int)time(NULL));
使用rand()%行或者列生成随机的二维数组下标落子而使用它要配合srand((unsigned)time(NULL))使用time函数的参数为time_t*这里用不上所以使用NULL空指针
我们需要电脑下棋,即让电脑产生随机数。
x = rand() % row;产生0 1 2三个随机数
y = rand() % col;产生0 1 2三个随机数

void ComputerBoard(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;
			 }
		}
}

同理我们也需要判断输入之前该处是否为空格。
if (board[x][y] == ’ ')
是空格我们再输入“#”作为电脑的输入。

三.判断输赢

最后我们玩游戏需要分出输赢。分为三种情况:
1.玩家赢 - ‘*’
2.电脑赢 - ‘#’
3.平局 — ‘Q’
4.游戏继续-‘C’
前三种情况都是已经结束游戏,第四种情况我们用来判断,即我们没输完一个坐标我们就检测一下是否有前三种情况出现,如果有就直接输出对应的结果。如果还没有就返回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][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 (IsFull(board, row, col))
	{
		return 'Q';
	}

	return 'C';
}

if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ’ ')
这里我们判断是否出现行的三坐标都一样。
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ’ ')
这里我们判断是否出现列的三坐标都一样。
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ’ ')
这里我们判断是否出现对角线的三坐标都一样。

⑤模块化代码实现

1.test.c游戏逻辑测试

#define _CRT_SECURE_NO_WARNINGS 1

#include "game.h"
void game()
{
	char ret = 0;
	char board[ROW][COL];
	//开始的时候,数组的内容应该是全部空格
	InitBoard(board, ROW, COL);
	DisplayBoard(board, ROW, COL);
	//下棋
	while (1)
	{
		PlayMove(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		//判断输赢
		ret = IsWin(board, ROW, COL);
		if (ret != 'C')
		{
			break;
		}
		ComputerBoard(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
	{
		printf("平局\n");
	}
}
void menu()
{
	printf("*************************\n");
	printf("*****   1. play    ******\n");
	printf("*****   0. exit    ******\n");
	printf("*************************\n");
}

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	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;
}
**```
2.game.c游戏相关函数模块实现**

```c
#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 DisplayBoard(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++)
		{
			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 PlayMove(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 ComputerBoard(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;
			 }
		}
}


static 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][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 (IsFull(board, row, col))
	{
		return 'Q';
	}

	return 'C';
}

3.game.h游戏头文件相关声明代码的实现

#pragma once

#include <stdio.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);
//玩家下棋
 void PlayMove(char board[ROW][COL], int row, int col);
 //电脑随机下棋
 void ComputerBoard(char board[ROW][COL], int row, int col);
 //比较输赢
 char IsWin(char board[ROW][COL], int row, int col);
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值