C语言游戏——三子棋

        

目录

        一.游戏介绍:

        二,整体逻辑实现

        三. 游戏内部函数逻辑

        1.棋盘的实现

        2.玩家自主下棋

        3.电脑随机下棋

        4.游戏结束的判断

        四.三子棋代码


来介绍一个c语言的小游戏吧——三子棋(井字棋),我们的童年或多或少都体验过这个游戏的乐趣,本子随手一画就是一局游戏的开始,就让我们一起来看看用C语言相关的知识如何开始这一小游戏吧。

        一.游戏介绍:

         如图所示,我们会在一个“井”字里面进行下棋,有“⭕”,“❌”两种棋子存在,一共九个位置,哪方率先将同样的棋连成一条直线,那一方即为胜利,游戏的规则非常简单,让我们来逐步实现一下该逻辑吧!

        在这个小游戏中,我们分为三个模块来进行实现,我们将自定义函数的的声明放置在“game.h”头文件中,函数的定义放在“game.c”文件中,函数的使用放在“test.c”文件中来逐步实现。

        二,整体逻辑实现

        对于一共游戏而言,避免不了菜单的出现,而在菜单中,就必然需要我们选择是否开始游戏,考虑到玩游戏的次数可能是多次,我们采用do while循环来打印菜单,switch语句来选择游戏选项,随后判断游戏是否进行第二轮,代码如下:

#include<stdio.h>
//菜单打印
void 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:
			game();
			printf("开始游戏:\n");
			break;
		case 0:
			printf("退出游戏.");
			break;
		default :
			printf("选择错误,请重新选择\n");
			break;
		}
   	} while (input);
    return 0;
}

//test.c文件里实现

        我们采用1开始游戏,0结束游戏来匹配do while的判断情况,打印效果如上所示,当然我们不能选择1后只有个“开始游戏”在屏幕显示,所以接下来我们介绍游戏逻辑的实现——定义一个game函数。

        三. 游戏内部函数逻辑

        1.棋盘的实现

        我们进行人机游戏实现,将game函数放在case 1后进行,如三子棋的图示可见,我们需要一个3×3的棋盘来让玩家和电脑放置棋子,于是便需要一个Board二维数组来制作棋盘,而当棋盘制作好后需要打印出棋盘以观察落子情况,所以这里我们需要定义和打印棋盘,这里我们将3×3的数字以宏的形式来定义:

#define ROW 3

#define COL 3

将此宏定义放置在game.h头文件中,接下来实现game函数:

void game()
{
	//定义棋盘.
	char Board[ROW][COL] = { 0 };
	//打印棋盘.
	display_Board(Board, ROW, COL);
}//在test.c文件中


//打印棋盘
void display_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");
		}
	}
}//函数的定义放在game.c文件

 当我们按照上述逻辑打印后会有如下结果:棋盘的格式很凌乱,达不到我们想要的效果

 这是因为我们定义二维数组的时候进行的初始化是0,而字符0是不会打印的,所以我们会有错行情况出现,所以我们也要进行棋盘的初始化——放置空格来满足。

//初始化棋盘
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.玩家自主下棋

在实现完棋盘后,我们进入游戏第二步:玩家下棋

玩家下棋满足的情况:

1.下棋位置合法(不能超出棋范围)

2.下棋的位置没有被占用,代码实现如下:

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

在这里,因为数组第一个元素从0开始,但输入坐标时我们从1计算,所以我们要将x,y坐标减一来进行实现。

         可以观察到我们只下了一步便退出了玩家下棋的逻辑,这是不合理的,所以我们应该将玩家和电脑下棋的函数都放置在while循环中,直到游戏结束再结束下棋

        3.电脑随机下棋

我们在这里不将电脑设置成可以追堵玩家的模式,只需要它在空余位置落子即可,由于电脑落子是随机的,我们需要使用一个rand函数来制造随机数以便电脑下棋

 观察rand函数的作用,返回一个从0到最大值的随机数,这个RAND_MAX我们可以在vs观察其数值为:32767,也就是我们可以返回一个0~32767的随机数

 但注意第二段,这个随机数是由算法生成的,而该算法需要使用srand函数来调用

 而观察srand函数时,可以看到,它建议设置seed种子参数时候使用time函数

因为时间每分每秒都在改变,我们使用srand设置种子时,如果种子的数值不变,那么得到的算法单一,产生的随机数会相同,这不是我们想要的结果,于是我们使用time函数,将参数设置为NULL空指针,它返回的值是时间,只需将time_t的类型强制类型转换即可:

srand((unsigned int)time(NULL));

种子只需要设定一次,所以我们将srand函数放在main函数里面,减少代码计算量,然后进行电脑随机下棋:

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;
		}
	}
}

        4.游戏结束的判断

在玩家和电脑逐步下棋对战后,便是来到了我们判断游戏是否结束的环节:

我们进行如下设定:

1.玩家获胜——我们返回 “ * ”

2.电脑获胜——我们返回 “ # ”

3.平局——我们返回 “ Q ”

4.游戏继续——返回 “ C ”

按照如上逻辑,我们先设定一个ret变量,来存储上述四种返回值——以此来判断游戏是否继续情况和赢家是谁:

char judge_winner(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[0][0] != ' ')
	{
		return board[0][0];
	}
	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))
	{
		return 'Q';
	}

	return 'C';
}

我们进行三行,三列以及对角线的判断,因为我们设定的玩家下“ * ”,电脑下“ # ”,所以只需要直接返回下的该棋子即可判断输赢情况,如果输赢都不满足,那我们只需判断棋盘是否填满,如若不是则继续进行游戏,直到结束。

        四.三子棋代码

test.c文件:
#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] = { 0 };
	//初始化棋盘.
	InitBoard(Board, ROW, COL);
	//打印棋盘
	display_Board(Board, ROW, COL); 
	while (1)
	{
		//玩家下棋
		player_move(Board, ROW, COL);
		display_Board(Board, ROW, COL);
		ret = judge_winner(Board, ROW, COL);
		if (ret != 'C')
			break;
		//电脑下棋
		computer_move(Board, ROW, COL);
		display_Board(Board, ROW, COL);
		ret = judge_winner(Board, ROW, COL);
		if (ret != 'C')
			break;

	}
	if (ret == '*')
	{
		printf("玩家获胜! \n");
	}
	else if (ret == '#')
	{
		printf("电脑获胜! \n");
	}
	else if (ret == 'Q')
	{
		printf("平局");
	}
	display_Board(Board, ROW, COL);
}

int main()
{
	srand((unsigned int)time(NULL));
	int input = 0;	
	do
	{
		menu();
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			printf("开始游戏:\n");
			break;
		case 0:
			printf("退出游戏.");
			break;
		default :
			printf("选择错误,请重新选择\n");
			break;
		}
	} while (input);
	return 0;
}

game.c文件:
//初始化棋盘
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 display_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)
{
	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 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;
		}
	}
}

//判断棋盘是否满格
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;
}

//判断胜利
//C——游戏继续
//*——玩家获胜
//#——电脑获胜
//Q——平局
char judge_winner(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[0][0] != ' ')
	{
		return board[0][0];
	}
	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))
	{
		return 'Q';
	}

	return 'C';
}

game.h文件:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 3
#define COL 3


//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col);

//打印棋盘
void display_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 judge_winner(char board[ROW][COL], int row, int col);

好啦,这便是小编对于三子棋的实现情况,谢谢各位的阅读,我们期待下次更新吧~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值