【C语言初阶】 三子棋游戏的简单实现(C语言后附完整代码)

目录

 

整体思路与设计

1.数组的初始化

  2.打印棋盘 

3.选手输入

4.电脑输入

5.判断输赢

完整代码

game.h

game.c 

test.c 


 

整体思路与设计

三子棋又叫井字棋,规则为在一个3*3的棋盘里对弈,最后三子一线则为赢。而接下来我们将用C语言来简单实现它。实现结果展示大概为这样,具体实现请看下文 

03836dc68fd3479cbd0f130d8594f60c.png

博主使用的是VS2019进行编译,有对该编译器感兴趣或想要下载链接的可以私信博主

首先呢我们先创建一个工程,在此工程中创建三个文件为

12509f97f60c4b5fba7570e8ad014f94.png

game.h 为我们所创建的头文件,里面有我们所需要的所有函数声明

game.c 为我们三子棋游戏的具体实现

test.c 为我们的主函数所在,和实现

写一个代码,我们从它的主函数开始写起,那么我们这个主函数该怎么写呢;我们写一个游戏,首先是不是得有一个游戏界面,得让使用者知道要干些什么;而且得让他有的选择;其次呢万一玩家完了之后还要继续玩呢?当我们知道这些后就可开始test.c的实现了;

void menu()
{
	printf("********  三子棋游戏  ********\n");
	printf("******** 1 .  玩游戏   *******\n");
	printf("******** 2 . 退出游戏  *******\n");
	printf("**规则:一次一子,三子相连为赢\n");
	printf("******************************\n");
}

首先我们创建一个menu()的函数来实现菜单的打印

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));//产生随机数,与rand()搭配使用,在game()中会用到
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);//进行选择
		switch (input)
		{
		case 1:
			game();//game()的实现后续会讲到
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误,重新选择!\n");
			break;
		}
		getchar();//两个getchar(),是为了吃掉回车,后续会讲到具体用处
		getchar();
		system("cls");//清空前面输出的棋盘,使页面更加整洁(每一局结束后清理)
	} while (input);
	return 0;
}

这就是我们的主函数,因为博主觉得菜单不算game()函数的具体实现,便放在了test.c里

我们来看一下博主写的test.c

#include "game.h"//我们自己创建的头文件
void menu()
{
	printf("********  三子棋游戏  ********\n");
	printf("******** 1 .  玩游戏   *******\n");
	printf("******** 2 . 退出游戏  *******\n");
	printf("**规则:一次一子,三子相连为赢\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;
		}
		getchar();
		getchar();
		system("cls");
	} while (input);
	return 0;
}

接下来我们来到最难的game()函数的实现了,这里我们采用二维数组来实现

首先我们得对数组初始化,其次呢我们得有个棋盘,然后呢就是下棋过程,分为玩家下棋,和电脑下棋,而每一轮下完棋后,又需要进行判断输赢情况。

那么我们就有了思路,可分为以下几个模块来写:

        1.数组的初始化

        2.打印棋盘

        3.选手输入

        4.电脑输入

        5.判断输赢

在函数篇讲到函数:先声明后使用

则在头文件game.h里的函数声明如下

#pragma once
#include<stdio.h>
#include<time.h>
#include<windows.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 PlayerMove(char board[ROW][COL], int row, int col);
//电脑输入
void ComputerMove(char board[ROW][COL], int row, int col);
//判断输赢
char IsWin(char board[ROW][COL], int row, int col);

那接下来我们就开始game()函数的实现部分;

1.数组的初始化

在这里我们从最开始结果展示可以发现,最开始是什么都没有·,所以都初始化为空格,数组初始化不懂得可以看看博主对数组篇得讲解

void InitBoard(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.打印棋盘 

我们先来看一下我们所需要得棋盘长什么样子?

52345b3b59064c7084e872dc768d0832.png

接下来我们看一下具体得代码实现

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("|");//因为最后一个字符不用打印'|',所一只用打印col-1次
		}
		printf("\n");
		for (j = 0; j < row; j++)
		{
			if (i < row - 1)//同理,后一行不打印
			{
				printf("---");//产生棋盘的分割线
				if (j < col - 1)//与上面相同,最后一个不用打印
					printf("|");
			}
		}
		printf("\n");
	}
}

关于每一步得思路和注释已经写在了代码里,有需要得宝子可以看一下

3.选手输入

选手输入时不但要做出提示,还得对输入的位置进行判断,此处是否能落子,实现代码如下

void PlayerMove(char board[ROW][COL], int row, int col)
{
	printf("玩家输入\n");
	printf("请输入一个坐标,中间用空格隔开>:");
	int x = 0;
	int y = 0;
	while (1)//若不对可循环输入
	{
		scanf("%d%d", &x, &y);
		if ((x<1 && x>row) || (x<1 && x>col))
			printf("非法输入,请重新输入\n");
		if (board[x - 1][y - 1] == ' ')//玩家输入的坐标都是从一开始的,而数组的下标是从0开始的,
		{                              //所以需要减一
			board[x - 1][y - 1] = '*';//我们让玩家下的棋子为'*';
			break;//输入正确跳出循环
		}
		else printf("此处已被占用,请重新输入\n");
	}
}

测试一下,实现成功 

a980d401c63f4438897be3c1dfed80c6.png

4.电脑输入

电脑输入这里我们将引用前面猜数字游戏所讲的一个知识点,随机数的产生,接下来我们来看看代码的实现

void ComputerMove(char board[ROW][COL], int row, int col)
{
	printf("电脑输入\n");
	while (1)//循环输入,直到输入成功为止
	{
		int x = rand() % row;//与前面所讲的srand()一起使用,可产生1-row的随机数
		int y = rand() % col;//1-col的随机数
		if (board[x - 1][y - 1] == ' ')
		{
			board[x - 1][y - 1] = '#';//电脑下棋落子记为'#'
			break;//输入成功跳出循环
		}
	}
}

结果展示可以参考上一张图

5.判断输赢

数据输入了进来,这时候我们就要进行判断游戏是否继续,如果不继续结果是怎么样的?

代码如下:

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) == 1)
	{
		return 'Q';
	}
	//继续
	return 'C';
}

这个函数里还嵌套了一个IsFull()得函数,用来判断是否所有空格都被填满,代码如下

int IsFull(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;
}

到此为止所有需要得功能都已经写完,接下来我们要将他们组装起来,组装如下

void game()
{
	char board[ROW][COL] = { 0 };
	InitBoard( board,  ROW,  COL);//数组初始化
	DisplayBoard(board, ROW, COL);//打印最初得棋盘
	while (1)
	{
		
		PlayerMove(board, ROW, COL);//玩家输入
		DisplayBoard(board, ROW, COL);//打印已经改变的棋盘
		if (IsWin(board, ROW, COL) != 'C')//判断是否继续游戏
			break;//游戏结束跳出循环
		ComputerMove(board, ROW, COL);//电脑输入
		DisplayBoard(board, ROW, COL);//打印改变得棋盘
		if (IsWin(board, ROW, COL) != 'C')//判断是否继续游戏
			break;
	}
	if (IsWin(board, ROW, COL) == '*')
		printf("恭喜你,你赢了!!\n");//接受返回值做出判断
	if (IsWin(board, ROW, COL) == '#')
		printf("很遗憾,你输了!!\n");//接受返回值做出判断
	if (IsWin(board, ROW, COL) == 'Q')
		printf("平局!!\n");//接受返回值做出判断
		
}

至此呢,所有代码都已完成,我们来试玩一下

06712e108885438daf7582b9db5ded57.png

成功实现,但是我们发现,前面堆积太多了,下一次游戏进行十分不美观,这时候博主前面所讲得一个就起作用了  ,有了这一段代码后,只需要你再按一下回车,就可以清除前面所打印的。

ffbd0d12d42e4fd4b450d1aa9760b531.png

以上就是博主的对三子棋游戏的实现,制作不易,各位看官给个三连呗!!!

以上就是博主的对三子棋游戏的实现,制作不易,各位看官给个三连呗!!!

完整代码

game.h

#pragma once
#include<stdio.h>
#include<time.h>
#include<windows.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 PlayerMove(char board[ROW][COL], int row, int col);
//电脑输入
void ComputerMove(char board[ROW][COL], int row, int col);
//判断输赢
char IsWin(char board[ROW][COL], int row, int col);

game.c 

#include "game.h"

void InitBoard(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 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("|");
		}
		printf("\n");
		for (j = 0; j < row; j++)
		{
			if (i < row - 1)
			{
				printf("---");
				if (j < col - 1)
					printf("|");
			}
		}
		printf("\n");
	}
}

void PlayerMove(char board[ROW][COL], int row, int col)
{
	printf("玩家输入\n");
	printf("请输入一个坐标,中间用空格隔开>:");
	int x = 0;
	int y = 0;
	while (1)
	{
		scanf("%d%d", &x, &y);
		if ((x<1 && x>row) || (x<1 && x>col))
			printf("非法输入,请重新输入\n");
		if (board[x - 1][y - 1] == ' ')
		{
			board[x - 1][y - 1] = '*';
			break;
		}
		else printf("此处已被占用,请重新输入\n");
	}
}

void ComputerMove(char board[ROW][COL], int row, int col)
{
	printf("电脑输入\n");
	while (1)
	{
		int x = rand() % row;
		int y = rand() % col;
		if (board[x - 1][y - 1] == ' ')
		{
			board[x - 1][y - 1] = '#';
			break;
		}
	}
}

int IsFull(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 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) == 1)
	{
		return 'Q';
	}
	//继续
	return 'C';
}

void game()
{
	char board[ROW][COL] = { 0 };
	InitBoard( board,  ROW,  COL);
	DisplayBoard(board, ROW, COL);
	while (1)
	{
		
		PlayerMove(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		if (IsWin(board, ROW, COL) != 'C')
			break;
		ComputerMove(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		if (IsWin(board, ROW, COL) != 'C')
			break;
	}
	if (IsWin(board, ROW, COL) == '*')
		printf("恭喜你,你赢了!!\n");
	if (IsWin(board, ROW, COL) == '#')
		printf("很遗憾,你输了!!\n");
	if (IsWin(board, ROW, COL) == 'Q')
		printf("平局!!\n");
		
}

test.c 

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu()
{
	printf("********  三子棋游戏  ********\n");
	printf("******** 1 .  玩游戏   *******\n");
	printf("******** 2 . 退出游戏  *******\n");
	printf("**规则:一次一子,三子相连为赢\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;
		}
		getchar();
		getchar();
		system("cls");
	} while (input);
	return 0;
}

 

 

 

 

 

  • 13
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

遇事问春风乄

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

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

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

打赏作者

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

抵扣说明:

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

余额充值