超详细的三子棋(C语言实现)—实现人机对战 x 玩家vs玩家


目录

♈️一、三子棋的简介

♉️二、C语言实现思路

        大体框架的构建

        接口的定义

♊️ 三、根据所写接口实现函数主体

        菜单的构建

        game()主体的构建

        💟重点在判断输赢!(肥肠重要!!!)

♋️四、总体代码

        实现效果 


♈️一、三子棋的简介

        三子棋是一种简单的棋类游戏。游戏的目标是在一个3x3或者更大的4x4等等的棋盘上,先将自己的棋子在一条直线上连成三个即可获胜。棋子可以横、竖、斜着连线。游戏通常由两个人轮流下棋进行,一方执X棋子,另一方执O棋子。如果棋盘被填满了且没有一方达成获胜条件,则平局。


♉️二、C语言实现思路

        大体框架的构建

1. 定义棋盘:使用二维数组来表示棋盘,其中0表示空格,1表示*,2表示#。

2. 初始化棋盘:将每个元素初始化为0(空格)。

3. 画出棋盘:使用printf()函数在屏幕上绘制出棋盘,包括行和列的标记。

4. 玩家输入:使用scanf()函数让玩家在控制台上输入他想要下棋的位置。

5. 检查合法性:检查玩家输入的位置是否在棋盘范围内,并且是否为空格(即是否已经下过棋了)。

6. 下棋:如果玩家输入的位置合法,那么在该位置上下一颗棋子(*或#)。

7. 检查胜负:每下一颗棋子都需要检查是否有玩家已经获胜了,如果有,游戏结束。

8. 切换玩家:玩家vs玩家:每次玩家下完一步棋,需要切换到另一个玩家继续游戏。玩家vs电脑:电脑自动下,然后玩家下。

9. 循环游戏:按照上述步骤重复进行游戏,直到有一方获胜或者平局。

10. 打印结果:游戏结束后,使用printf()函数输出结果,说明谁获胜了或者是平局。

        接口的定义

        定义了棋盘的大小,ROW和COL来控制,以及两个主题函数,一个是作为菜单的函数,另外一个是作为游戏的主体函数,较为简单。(●'◡'●)

#define ROW 5
#define COL 5

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

void menu();

void game();


♊️ 三、根据所写接口实现函数主体

        菜单的构建

void menu()//菜单
{
	printf("---------------------------\n");
	printf("|*************************|\n");
	printf("|*******  1.play  ********|\n");
	printf("|*******  0.exit  ********|\n");
	printf("|*************************|\n");
	printf("---------------------------\n");
}

                        大道至简,无需多言 !

        game()主体的构建

        首先还是要先构思一下大体框架->要实现什么功能?人机大战! 玩家vs玩家!->这样便又需要一个菜单来供选择了 ε=(´ο`*)))唉 ->用什么来做比较合适?数组!二维数组!->需要什么?棋盘!->用了数组因此需要初始化,需要打印棋盘,需要对于玩家落子和电脑落子进行分别的操作!->最主要的操作!判断输赢!->棋盘满算平局(重点),执子 * 和  # 哪边先达到要求哪边胜出!

        实现如下:

#define _CRT_SECURE_NO_WARNINGS 01

#include"game.h"

void menu()//菜单
{
	printf("---------------------------\n");
	printf("|*************************|\n");
	printf("|*******  1.play  ********|\n");
	printf("|*******  0.exit  ********|\n");
	printf("|*************************|\n");
	printf("---------------------------\n");
}

void Initboard(char board[ROW][COL], int row, int col)//初始化棋盘
{
	for (int i = 0; i < row;i++)
	{
		for (int j = 0; j < col; j++)
		{
			board[i][j] = ' ';
		}
	}
}

void Disboard(char board[ROW][COL], int row, int col)//打印现在棋盘上所落子
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			printf(" %c ", board[i][j]);
			if(j<col-1)
			printf("|");
		}
		printf("\n");
		if(i<row-1)
		for (int j = 0; j < col; j++)
		{
			printf("--- ");
		}
		printf("\n");
	}
}

int isfull(char board[ROW][COL], int row, int col)//判断棋盘是否满
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			if (board[i][j] == ' ')
				return 0;
		}
	}
	return 1;
}

void Player(char board[ROW][COL], int row, int col)//玩家动作
{
	printf("输入要下棋的位置(二维坐标表示 空格隔开):");
	int a = 0,b = 0;
	scanf("%d %d", &a, &b);
	a = a - 1;
	b = b - 1;
	if (a <= row && b <= col && board[a][b] != '*' && board[a][b] != '#')
	{
		board[a][b] = '*';
	}
	else
	{
		printf("输入错误,请重新输入!");
		Player(board, ROW, COL);
	}
}

void Player2(char board[ROW][COL], int row, int col)//玩家动作
{
	printf("输入要下棋的位置(二维坐标表示 空格隔开):");
	int a = 0, b = 0;
	scanf("%d %d", &a, &b);
	a = a - 1;
	b = b - 1;
	if (a <= row && b <= col && board[a][b] != '*' && board[a][b] != '#')
	{
		board[a][b] = '#';
	}
	else
	{
		printf("输入错误,请重新输入!");
		Player2(board, ROW, COL);
	}
}

void Computer(char board[ROW][COL], int row, int col)//电脑动作
{
	while (1)
	{
		int a = rand() % row;
		int b = rand() % col;
		if (board[a][b] == ' ')
		{
			printf("电脑下棋:\n");
			board[a][b] = '#';
			break;
		}
		if (isfull(board,ROW,COL) == 1)
			break;
	}
}


int awin(char board[ROW][COL], int row, int col)//a玩家赢
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			if (board[i][j] == '*')
			{
				if (j + 2 < col)//横向
				{
					if (board[i][j] == board[i][j + 1] && board[i][j + 1] == board[i][j + 2])
						return 2;
				}
				if (i + 2 < row)//纵向
				{
					if (board[i][j] == board[i + 1][j] && board[i + 1][j] == board[i + 2][j])
						return 2;
				}
				if ((i + 2 < row) && (j + 2 < col))//右下
				{
					if (board[i][j] == board[i + 1][j + 1] && board[i + 1][j + 1] == board[i + 2][j + 2])
						return 2;
				}
				if ((i + 2 >= 0) && (j - 2 >= 0))//左下
				{
					if (board[i][j] == board[i + 1][j - 1] && board[i + 1][j - 1] == board[i + 2][j - 2])
						return 2;
				}
			}
				
		}
	}
	return 0;
}

int bwin(char board[ROW][COL], int row, int col)//b玩家赢
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			if (board[i][j] == '#')
			{
				if (j + 2 < col)//横向
				{
					if (board[i][j] == board[i][j + 1] && board[i][j + 1] == board[i][j + 2])
						return 3;
				}
				if (i + 2 < row)//纵向
				{
					if (board[i][j] == board[i + 1][j] && board[i + 1][j] == board[i + 2][j])
						return 3;
				}
				if ((i + 2 < row) && (j + 2 < col))//右下
				{
					if (board[i][j] == board[i + 1][j + 1] && board[i + 1][j + 1] == board[i + 2][j + 2])
						return 3;
				}
				if ((i + 2 >= 0) && (j - 2 >= 0))//左下
				{
					if (board[i][j] == board[i + 1 ][j - 1] && board[i + 1][j - 1] == board[i + 2][j - 2])
						return 3;
				}
			}

		}
	}
	return 0;
}

char judge(char board[ROW][COL], int row, int col)
{
	if(bwin(board, ROW, COL) == 3)
		return '#';
	else if (awin(board, ROW, COL) == 2)
		return '*';
	else if(isfull(board, ROW, COL) == 1)//平局
		return 'p';
	else return ' ';
}

void game1()
{
	srand((unsigned int)time(NULL));
	char board[ROW][COL] = { 0 };
	Initboard(board, ROW, COL);
	Disboard(board,ROW,COL);
	char ret = ' ';
	while(1)
	{

		printf("玩家下棋:\n");
		Player(board, ROW, COL);
		Disboard(board, ROW, COL);
		ret = judge(board, ROW, COL);
		if (ret != ' ')
			break;
	
		Computer(board, ROW, COL);
		Disboard(board, ROW, COL);
		ret = judge(board, ROW, COL);
		if (ret != ' ')
			break;

	}
	if (ret == 'p')
		printf("平局!\n");
	else if (ret == '*')
		printf("玩家赢!\n");
	else if (ret == '#')
		printf("电脑赢!\n");
	
}

void game2()
{
	char board[ROW][COL] = { 0 };
	Initboard(board, ROW, COL);
	Disboard(board, ROW, COL);
	char ret = ' ';
	while (1)
	{
		printf("玩家a下棋:\n");
		Player(board, ROW, COL);
		Disboard(board, ROW, COL);
		ret = judge(board, ROW, COL);
		if (ret != ' ')
			break;

		printf("玩家b下棋:\n");
		Player2(board, ROW, COL);
		Disboard(board, ROW, COL);
		ret = judge(board, ROW, COL);
		if (ret != ' ')
			break;

	}
	if (ret == 'p')
		printf("平局!\n");
	else if (ret == '*')
		printf("玩家a赢!\n");
	else if (ret == '#')
		printf("玩家b赢!\n");
}

void game()
{
	printf("         **********************\n");
	printf("              选择游玩模式\n");
	printf("         ******1.人机大战*******\n");
	printf("         **2.player vs player**\n");
	printf("         **********************\n");
	printf("         **********************\n");
	int in = 0;
	scanf("%d", &in);
	printf("\n\n");
	switch (in)
	{
	case 1:
		game1();
		break;
	case 2:
		game2();
		break;
	default:
		printf("选择错误\n");
		break;
	}
}

        💟重点在判断输赢!(肥肠重要!!!)

        平局!最主要的就是判满!便历棋盘看是否剩下空格->也就是没落子的地方,若全满返回1以告诉后续接受的函数棋盘满了,可以判平!

        判平实现如下: 

int isfull(char board[ROW][COL], int row, int col)//判断棋盘是否满
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			if (board[i][j] == ' ')
				return 0;
		}
	}
	return 1;
}

        玩家或者电脑赢!判断方法都是一样的!最主要的就是怎么判赢!思路->先找到要判赢玩家或电脑所执棋子,这里是‘*’,找到了便可以进行判断了!->分为横向和纵向以及斜向。横向和纵向太斜向的思路都是差不多的-极限。->首先说明为什么我们只判断右下和左下,前面横向和纵向也是为啥只判断一边就行了,因为前边我们的查找:找到‘*’才进行判断。那么之前我们就都判断过了一边,为什么呢?因为我们的起点是从0,0开始的,我们没有左边也没有上边,也没有左上右上。那么接下来的位置实际上我们已经判断过了一边了,只需要判断另一边即可。(也许是我思考有误?希望大家能帮忙指出Ծ‸Ծ)

int awin(char board[ROW][COL], int row, int col)//a玩家赢
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			if (board[i][j] == '*')
			{
				if (j + 2 < col)//横向
				{
					if (board[i][j] == board[i][j + 1] && board[i][j + 1] == board[i][j + 2])
						return 2;
				}
				if (i + 2 < row)//纵向
				{
					if (board[i][j] == board[i + 1][j] && board[i + 1][j] == board[i + 2][j])
						return 2;
				}
				if ((i + 2 < row) && (j + 2 < col))//右下
				{
					if (board[i][j] == board[i + 1][j + 1] && board[i + 1][j + 1] == board[i + 2][j + 2])
						return 2;
				}
				if ((i + 2 >= 0) && (j - 2 >= 0))//左下
				{
					if (board[i][j] == board[i + 1][j - 1] && board[i + 1][j - 1] == board[i + 2][j - 2])
						return 2;
				}
			}
				
		}
	}
	return 0;
}

♋️四、总体代码

game.h

#pragma once

#define ROW 5
#define COL 5

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

void menu();

void game();


game.c

#define _CRT_SECURE_NO_WARNINGS 01

#include"game.h"

void menu()//菜单
{
	printf("---------------------------\n");
	printf("|*************************|\n");
	printf("|*******  1.play  ********|\n");
	printf("|*******  0.exit  ********|\n");
	printf("|*************************|\n");
	printf("---------------------------\n");
}

void Initboard(char board[ROW][COL], int row, int col)//初始化棋盘
{
	for (int i = 0; i < row;i++)
	{
		for (int j = 0; j < col; j++)
		{
			board[i][j] = ' ';
		}
	}
}

void Disboard(char board[ROW][COL], int row, int col)//打印现在棋盘上所落子
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			printf(" %c ", board[i][j]);
			if(j<col-1)
			printf("|");
		}
		printf("\n");
		if(i<row-1)
		for (int j = 0; j < col; j++)
		{
			printf("--- ");
		}
		printf("\n");
	}
}

int isfull(char board[ROW][COL], int row, int col)//判断棋盘是否满
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			if (board[i][j] == ' ')
				return 0;
		}
	}
	return 1;
}

void Player(char board[ROW][COL], int row, int col)//玩家动作
{
	printf("输入要下棋的位置(二维坐标表示 空格隔开):");
	int a = 0,b = 0;
	scanf("%d %d", &a, &b);
	a = a - 1;
	b = b - 1;
	if (a <= row && b <= col && board[a][b] != '*' && board[a][b] != '#')
	{
		board[a][b] = '*';
	}
	else
	{
		printf("输入错误,请重新输入!");
		Player(board, ROW, COL);
	}
}

void Player2(char board[ROW][COL], int row, int col)//玩家动作
{
	printf("输入要下棋的位置(二维坐标表示 空格隔开):");
	int a = 0, b = 0;
	scanf("%d %d", &a, &b);
	a = a - 1;
	b = b - 1;
	if (a <= row && b <= col && board[a][b] != '*' && board[a][b] != '#')
	{
		board[a][b] = '#';
	}
	else
	{
		printf("输入错误,请重新输入!");
		Player2(board, ROW, COL);
	}
}

void Computer(char board[ROW][COL], int row, int col)//电脑动作
{
	while (1)
	{
		int a = rand() % row;
		int b = rand() % col;
		if (board[a][b] == ' ')
		{
			printf("电脑下棋:\n");
			board[a][b] = '#';
			break;
		}
		if (isfull(board,ROW,COL) == 1)
			break;
	}
}


int awin(char board[ROW][COL], int row, int col)//a玩家赢
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			if (board[i][j] == '*')
			{
				if (j + 2 < col)//横向
				{
					if (board[i][j] == board[i][j + 1] && board[i][j + 1] == board[i][j + 2])
						return 2;
				}
				if (i + 2 < row)//纵向
				{
					if (board[i][j] == board[i + 1][j] && board[i + 1][j] == board[i + 2][j])
						return 2;
				}
				if ((i + 2 < row) && (j + 2 < col))//右下
				{
					if (board[i][j] == board[i + 1][j + 1] && board[i + 1][j + 1] == board[i + 2][j + 2])
						return 2;
				}
				if ((i + 2 >= 0) && (j - 2 >= 0))//左下
				{
					if (board[i][j] == board[i + 1][j - 1] && board[i + 1][j - 1] == board[i + 2][j - 2])
						return 2;
				}
			}
				
		}
	}
	return 0;
}

int bwin(char board[ROW][COL], int row, int col)//b玩家赢
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			if (board[i][j] == '#')
			{
				if (j + 2 < col)//横向
				{
					if (board[i][j] == board[i][j + 1] && board[i][j + 1] == board[i][j + 2])
						return 3;
				}
				if (i + 2 < row)//纵向
				{
					if (board[i][j] == board[i + 1][j] && board[i + 1][j] == board[i + 2][j])
						return 3;
				}
				if ((i + 2 < row) && (j + 2 < col))//右下
				{
					if (board[i][j] == board[i + 1][j + 1] && board[i + 1][j + 1] == board[i + 2][j + 2])
						return 3;
				}
				if ((i + 2 >= 0) && (j - 2 >= 0))//左下
				{
					if (board[i][j] == board[i + 1 ][j - 1] && board[i + 1][j - 1] == board[i + 2][j - 2])
						return 3;
				}
			}

		}
	}
	return 0;
}

char judge(char board[ROW][COL], int row, int col)
{
	if(bwin(board, ROW, COL) == 3)
		return '#';
	else if (awin(board, ROW, COL) == 2)
		return '*';
	else if(isfull(board, ROW, COL) == 1)//平局
		return 'p';
	else return ' ';
}

void game1()
{
	srand((unsigned int)time(NULL));
	char board[ROW][COL] = { 0 };
	Initboard(board, ROW, COL);
	Disboard(board,ROW,COL);
	char ret = ' ';
	while(1)
	{

		printf("玩家下棋:\n");
		Player(board, ROW, COL);
		Disboard(board, ROW, COL);
		ret = judge(board, ROW, COL);
		if (ret != ' ')
			break;
	
		Computer(board, ROW, COL);
		Disboard(board, ROW, COL);
		ret = judge(board, ROW, COL);
		if (ret != ' ')
			break;

	}
	if (ret == 'p')
		printf("平局!\n");
	else if (ret == '*')
		printf("玩家赢!\n");
	else if (ret == '#')
		printf("电脑赢!\n");
	
}

void game2()
{
	char board[ROW][COL] = { 0 };
	Initboard(board, ROW, COL);
	Disboard(board, ROW, COL);
	char ret = ' ';
	while (1)
	{
		printf("玩家a下棋:\n");
		Player(board, ROW, COL);
		Disboard(board, ROW, COL);
		ret = judge(board, ROW, COL);
		if (ret != ' ')
			break;

		printf("玩家b下棋:\n");
		Player2(board, ROW, COL);
		Disboard(board, ROW, COL);
		ret = judge(board, ROW, COL);
		if (ret != ' ')
			break;

	}
	if (ret == 'p')
		printf("平局!\n");
	else if (ret == '*')
		printf("玩家a赢!\n");
	else if (ret == '#')
		printf("玩家b赢!\n");
}

void game()
{
	printf("         **********************\n");
	printf("              选择游玩模式\n");
	printf("         ******1.人机大战*******\n");
	printf("         **2.player vs player**\n");
	printf("         **********************\n");
	printf("         **********************\n");
	int in = 0;
	scanf("%d", &in);
	printf("\n\n");
	switch (in)
	{
	case 1:
		game1();
		break;
	case 2:
		game2();
		break;
	default:
		printf("选择错误\n");
		break;
	}
}

        text.c

#define _CRT_SECURE_NO_WARNINGS 01

#include"game.h"

int main()
{
	int input = 0,flag=0;
	do
	{
		menu();
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			if(flag==0)
			printf("\n              -- 三子棋 --\n \n");
			flag = 1;
			game();
			break;
		case 0:
			printf("--退出成功--\n");
			break;
		default:
			printf("--输入错误,请重新输入!--\n");
		}
	} while (input);
	return 0;
}

        实现效果 

        人机大战!

         player vs player!