C语言经典小游戏之三子棋

目录

一、代码思路

二、代码实现

1.菜单

2.实现棋盘

3.玩家下棋

 4.电脑下棋

5.判断输赢

三、代码

1.game.h代码

3.game.c代码

3.test.c代码

 


一、代码思路

首先需要创建三个文件:

test.c       //用于测试游戏的逻辑性

game.c    //游戏代码的实现

game.h   //游戏代码的声明(函数声明、符号定义)

  • 实现三子棋流程:

开始菜单--->实现棋盘--->玩家、电脑下棋--->判断输赢 

  • 主要运用了函数和数组。

二、代码实现

1.菜单

  • 首先我们需要打印一个菜单(开始游戏、结束游戏)以及最简单化游戏思路。

 由于菜单至少需要执行一次,所以这里选用do while 循环,因为要进行选择是否开始游戏,所以我们这里需要用scanf输入一个数,并且用到switch来进行游戏选择,(这里的while判断为假的时候我们需要退出循环,结束游戏,所以这里可以巧妙的选用0来实现)。

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
menu()
{
	printf("**************\n");
	printf("*** 1.play ***\n");
	printf("*** 0.exit ***\n");
	printf("**************\n");
}
int main()
{
	int input = 0;
	do 
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("三子棋\n");
			break;
		case 0:
			printf("退出游戏!\n");
			break;
		default:
			printf("选择错误,请重新选择\n");
		}
		


	} while (input);
	return 0;
}
  • 注意:每写完一个版块都要测试一下,以免写完后出问题,不知道问题在哪。 

测试:

 

2.实现棋盘

首先,我们需要知道三子棋是一个3*3的格子组合而成,可以用我们的二维数组来进行实现 

  • 创建数组,初始化棋盘。(这里的ROW、COL在game.h文件中统一定义为3,这样方便于以后写多子棋,不用一个个去更改参数,game.c和test.c只需要引用头文件game.h即可)
//game.c中
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] = ' ';
		}
	}
}
//test.c中
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include"game.h"
menu()
{
	printf("**************\n");
	printf("*** 1.play ***\n");
	printf("*** 0.exit ***\n");
	printf("**************\n");
}
game()
{
	
	char board[ROW][COL] = { 0 };
	//初始化棋盘的函数
	InitBoard(board, ROW, COL);
}
int main()
{
	int input = 0;
	do 
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏!\n");
			break;
		default:
			printf("选择错误,请重新选择\n");
		}
		


	} while (input);
	return 0;
}
//game.h中
#pragma once
#define ROW 3
#define COL 3
//初始化棋盘的函数
void InitBoard(char board[ROW][COL], int row, int col);
  •  打印棋盘,棋盘周围都有线相隔,所以我们需要用一些分割线来让数组看起来像棋盘。

这里函数的定义(test.c)声明(game.h)与上面相同,只是名称换了。 

//game.c
//打印棋盘
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");
		}
	}
}


//添加到game.h
//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col);

//添加到test.c
DisplayBoard(board,ROW,COL);

打印结果 :这样就有一个棋盘的雏形。

 

3.玩家下棋

这里的玩家落子,我们用 来表示, 玩家输入坐标后,我们首先需要判断坐标是否合法,合法后再判断玩家下的位置是否被占用。(这里函数的定义(test.c)声明(game.h)与上面相同,只是名称换了)。

  • 这里用board[x-1][y-1]是因为,玩家在落子的时候应该只会从1开始,而数组的坐标是从0开始的,所以这里需要-1.
  • 落子完成后,我们需要打印棋盘,给玩家可读性。
//game.c中
//玩家下棋
void Player(char board[ROW][COL], int row, int col)
{
	int x = 0;//横坐标
	int y = 0;//纵坐标
	while (1)
	{
		printf("玩家下棋\n");
		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");
		}

	}
	
}


//添加到test.c
//玩家下棋
	Player(board, ROW, COL);
	//打印棋盘
	DisplayBoard(board, ROW, COL);

打印结果:成功落子

 

 4.电脑下棋

要让电脑随机下棋,这里我们需要用的rand( )函数、srand( )函数和time(NULL)来生成随机数.

注意头文件的添加,要添加两个头文件在game.h中:#include<stdio.h>、#include<time.h>。

(这里函数的定义(test.c)声明(game.h)与上面相同,只是名称换了)

rand()函数和srand()函数是C语言中用于生成随机数的两个重要函数。‌

  • rand()函数:‌用于生成伪随机数。‌它存在于头文件<stdlib.h>中,‌返回一个介于0和RAND_MAX(‌通常是32767)‌之间的伪随机整数。‌这个函数使用线性同余法来计算随机数,‌这意味着在一定范围内生成一串数字,‌有一个最大周期M。‌默认情况下,‌rand()函数的种子是1,‌所以每次运行程序时生成的随机数序列都是相同的。‌为了增加随机性,‌通常会配合srand()函数使用。‌

  • srand()函数:‌用于设置随机数种子。‌它的作用是产生一个随机种子,‌将这个种子传递给rand()函数,‌从而达到生成不同的随机数序列的目的。‌srand()函数可以接受不同的参数来产生不同的种子,‌例如使用time(NULL)getpid(NULL)的返回值作为参数,‌以确保每次产生不同的种子。‌使用time(NULL)可以确保每次程序运行时产生不同的时间,‌而getpid(NULL)则用来取得目前进程的进程识别码,‌用于建立临时文件以避免文件同名问题。‌

通过结合使用rand()和srand()函数,‌可以在C语言中生成所需的随机数,‌这对于模拟、‌游戏、‌加密等多种应用场景都非常有用。‌例如,‌可以通过调用srand(time(NULL))来初始化随机数生成器,‌然后使用rand()来生成一系列的随机数,‌从而实现各种随机过程

//电脑下棋
void Computer(char board[ROW][COL], int row, int col)
{
    printf("电脑下棋\n");
	int x = 0;
	int y = 0;
	while (1)
	{
		x = rand() % row;//0-2
		y = rand() % col;//0-2
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
	
	
}

不要忘了在主函数中添加srand来设置随机数起点: 

 

打印结果:

5.判断输赢

  • 到这里就快成功了,首先需要把玩家下棋和电脑下棋使用循环,让他们打回合,不然一把就结束了。
  • 然后进行输赢判断首先我们约定:玩家赢 函数返回‘*’,电脑赢 函数返回‘#’,平局 函数返回‘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++)
	{
		if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
		{
			return board[i][1];
		}
	}

	//列
	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[1][1] == board[0][0] && board[1][1] == board[2][2] && board[1][1] != ' ')
	{
		return board[1][1];
	}

	else if (board[1][1] == board[0][2] && board[2][0] == board[1][1] && board[1][1] != ' ')
	{
		return board[1][1];
	}

	//平局
	if (Is_full(board, row, col))
	{
		return 'q';
	}
	return 'c';
}
//判断是否满盘
//满了返回1,没满返回0
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;
}

基本流程到这里就结束了。

三、代码

1.game.h代码

#pragma once
#define ROW 3
#define COL 3

#include<stdlib.h>
#include<time.h>
//初始化棋盘的函数
void InitBoard(char board[ROW][COL], int row, int col);

//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col);

//玩家下棋
void Player(char board[ROW][COL], int row, int col);

//电脑下棋
void Computer(char board[ROW][COL], int row, int col);

//判断输赢
char Is_win(char board[ROW][COL], int row, int col);
int Is_full(char board[ROW][COL], int row, int col);

3.game.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 Player(char board[ROW][COL], int row, int col)
{
	int x = 0;//横坐标
	int y = 0;//纵坐标
	while (1)
	{
		printf("玩家下棋\n");
		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 Computer(char board[ROW][COL], int row, int col)
{
	printf("电脑下棋\n");
	int x = 0;
	int y = 0;
	while (1)
	{
		x = rand() % row;//0-2
		y = rand() % col;//0-2
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
}

//判断是否满盘
//满了返回1,没满返回0
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;
	int j = 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][1];
		}
	}

	//列
	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[1][1] == board[0][0] && board[1][1] == board[2][2] && board[1][1] != ' ')
	{
		return board[1][1];
	}

	else if (board[1][1] == board[0][2] && board[2][0] == board[1][1] && board[1][1] != ' ')
	{
		return board[1][1];
	}

	//平局
	if (Is_full(board, row, col))
	{
		return 'q';
	}
	return 'c';
}

3.test.c代码

 

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include"game.h"
menu()
{
	printf("**************\n");
	printf("*** 1.play ***\n");
	printf("*** 0.exit ***\n");
	printf("**************\n");
}
game()
{
	char r = 0;//接收输赢的返回值
	char board[ROW][COL] = { 0 };
	//初始化棋盘的函数
	InitBoard(board, ROW, COL);
	//打印棋盘
	DisplayBoard(board, ROW, COL);

	while (1)
	{
		//玩家下棋
		Player(board, ROW, COL);
		//判断输赢
		r = Is_win(board, ROW, COL);
		if (r != 'c')
			break;
		//打印棋盘
		DisplayBoard(board, ROW, COL);
		

		//电脑下棋
		Computer(board, ROW, COL);
		//判断输赢
		r = Is_win(board, ROW, COL);
		if (r != 'c')
			break;
		//打印棋盘
		DisplayBoard(board, ROW, COL);
	}
	if (r == '*')
	{
		printf("玩家赢\n");
	}
	else if (r == '#')
	{
		printf("电脑赢\n");
	}
	else if (r == 'q')
	{
		printf("平局\n");
	}
	//打印棋盘
	DisplayBoard(board, ROW, COL);
}
int main()
{
	srand((unsigned int)time(NULL));//设置随机数起点
	int input = 0;
	do 
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏!\n");
			break;
		default:
			printf("选择错误,请重新选择\n");
		}
		


	} while (input);
	return 0;
}

最终代码运行效果:

 


当然这个代码可能存在bug,还有很多可优化性,可以自己尝试更改代码 ,如果哪里写错了,欢迎指正。

  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值