C语言实现三子棋

C语言实现三子棋

来自菜鸡的第一次写博客

菜鸡自学C语言----学到数组这里,课堂有一节练习----三子棋 这不就是小时玩过的井字棋?

本菜鸡用最简单的C语言编程来实现这个三子棋游戏

菜鸡

**设计电脑与玩家作为下棋的两方,用键盘输入坐标的形式作为玩家的游戏操作 **

1.效果图

程序总的构架:

			1.test.c		--->>	测试游戏的逻辑
			2.game.h		--->>	关于游戏相关的函数声明,符号声明,头文件包含
			3.game.c		--->>	游戏相关函数的实现

我们只要输入坐标就可以和电脑对弈了.

电脑的棋子用#代替,玩家的棋子用*代替。

2.打印菜单

可以根据自己的爱好设计各种风格的菜单,自己赏心悦目,让自己游戏界面更加美观以及游戏体验更佳.

void menu()
{
	printf("\n");
	printf("******************************************\n");
	printf("*******    欢迎来到三子棋游戏    *********\n");
	printf("************    1. play    ***************\n");
	printf("************    0. exit    ***************\n");
	printf("******************************************\n");
}

3.初始化棋盘

ROW,COL分别表示棋盘的宽度和高度(既是棋盘的x和y坐标,也是数组的行和列)

一开始把棋盘初始化为' '(空格).

//初始化棋盘
//把数组每个元素初始化成空格
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] = ' ';//初始化成空格
		}
	}
}

4.打印棋盘

打印棋盘,棋盘由符号加数组元素组成,用符号把棋盘的框架打印下来

//打印棋盘
//打印数组元素及棋盘的框架
void DisplayBoard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		//printf(" %c | %c | %c \n",board[i][0],board[i][1],board[i][2]);
		int j = 0;
		for (j = 0; j < col; j++)
		{
			
			printf(" %c ",board[i][j]);
			if (col - 1 > j )
			{
				printf("|");
			}
			
		}
		printf("\n");
		if (i < row - 1)
		{
			//printf("---|---|---\n");
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1 )
				{
					printf("|");
				}
			}
		}
		
		printf("\n");
	}

}

5.下棋

可以使用判断语句让用户选择是先下还是后下,选完后再进行下棋.

首先我给出电脑下棋的逻辑,我是利用srand()函数和rand函数产生随机值让电脑在棋盘有空的位置上随机下棋.用一个循环判断就可以实现。也可以设计电脑让其更"聪明",能够判断玩家已经下好的棋,并能做出阻止(我没有做这一步,如果有兴趣的话,可以自己研究研究🧐)

电脑下棋

//电脑下棋
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][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}

}

玩家下棋

从键盘上输入下棋坐标,判断坐标正好是棋盘上空的地方,则成功下棋,若在棋盘上但非空位置,提示玩家该坐标已经被占用,要重新输入,若不在棋盘上,提示玩家该坐标非法,要重新输入。

//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("玩家走:>\n");
	while (1)
	{
		printf("请选择坐标(x,y):>");
		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("坐标非法,请重新输入");
		}
	}
}

6.判断输赢

游戏进行会有4种状态

  • 玩家赢 -->返回'*'
  • 电脑赢 -->返回'#'
  • 平局 -->返回'Q'
  • 游戏继续 -->返回'C'

双方谁能3颗棋子先连成一条线,就是赢家

下面有个判断输赢我写了个5子棋的判断输赢代码

//判断输赢
char  IsWim(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[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];
	}

	// 横线上五子连成一线,赢家产生
	
	//for (i = 0; i < row; i++)
	//{
	//	for (j = 0; j < col - 4; j++)
	//	{
	//		if (board[i][j] == board[i][j + 1]
	//			&& board[i][j + 1] == board[i][j + 2]
	//			&& board[i][j + 2] == board[i][j + 3]
	//			&& board[i][j + 3] == board[i][j + 4]
	//			&& board[i][j] != ' ')
	//		{
	//			return board[i][j];
	//		}
	//	}
	//}

	// 竖线上五子连成一线,赢家产生
	 
	//for (j = 0; j < col; j++)
	//{
	//	for (i = 0; i < row - 4; i++)
	//	{
	//		if (board[i][j] == board[i + 1][j]
	//			&& board[i + 1][j] == board[i + 2][j]
	//			&& board[i + 2][j] == board[i + 3][j]
	//			&& board[i + 3][j] == board[i + 4][j]
	//			&& board[i][j] != ' ')
	//		{
	//			return board[i][j];
	//		}
	//	}
	//}

	// 斜线上五子连成一线,赢家产生
	
	//for (i = 0; i < row - 4; i++)
	//{
	//	if (board[i][i] == board[i + 1][i + 1]
	//		&& board[i + 1][i + 1] == board[i + 2][i + 2]
	//		&& board[i + 2][i + 2] == board[i + 3][i + 3]
	//		&& board[i + 3][i + 3] == board[i + 4][i + 4]
	//		&& board[i][i] != ' ')
	//	{
	//		return board[i][i];
	//	}
	//	if (board[i][i + 4] == board[i + 1][i + 3]
	//		&& board[i + 1][i + 3] == board[i + 2][i + 2]
	//		&& board[i + 2][i + 2] == board[i + 3][i + 1]
	//		&& board[i + 3][i + 1] == board[i + 4][i]
	//		&& board[i][i + 4] != ' ')
	//	{
	//		return board[i][i + 4];
	//	}
	//}

	//判断平局
	//如果棋盘满了返回1 反之0
	int ret = isFull(board, ROW, COL);
	if (1 == ret)
	{
		return 'Q';
	}
	else
	{
		return 'C';
	}
}

7.判断平局

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

8.游戏执行

以上就是我们要实现三子棋的模块,要想把这些模块整合起来运行,就需要一个游戏执行函数来调用这些模块,定义个game()函数实现,代码如下:

//三子棋游戏运行逻辑
void game()
{
	//存储数据 - 二维数组
	//char board[3][3];//3*3的棋盘 后期如果需要更大的棋盘需要改大 修改数据太多工程量大 不适合
	//棋盘是游戏的属性 
	char board[ROW][COL];
	//初始化棋盘 - 初始化为空格
	//初始化棋盘函数属于游戏模块 -->game.h
	//不初始化出现随机值影响外观
	InitBoard(board,ROW,COL);

	//打印棋盘
	//本质上是打印数组的内容
	DisplayBoard(board,ROW,COL);

	//在游戏进行的过程
	//1.玩家赢了		*
	//2.电脑赢了		#
	//3.平局			Q
	//4.游戏继续		C
	//char IsWin 用来判断游戏的状态
	
	char ret = 0;//接受游戏状态

	while (1)
	{
		//玩家先下棋
		PlayerMove(board, ROW, COL);
		//打印棋盘
		DisplayBoard(board, ROW, COL);
		//判断用户输赢
		ret = IsWin(board,ROW,COL);
		if ('C' != ret)
		{
			break;
		}
		//电脑下棋
		ComputerMove(board, ROW, COL);
		//打印棋盘
		DisplayBoard(board, ROW, COL);
		//判断电脑输赢
		ret = IsWin(board, ROW, COL);
		if ('C' != ret)
		{
			break;
		}
	}
	if ('*' == ret)
	{
		printf("玩家赢了!\n");
	}
	else if ('#' == ret)
	{
		printf("电脑赢了\n");
	}
	else
	{
		printf("平局!\n");
	}
	DisplayBoard(board, ROW, COL);
}

9.头文件

在头文件 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 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);

//在游戏进行的过程
//1.玩家赢了		*
//2.电脑赢了		#
//3.平局			Q
//4.游戏继续		C
//char IsWin 用来判断游戏的状态

char IsWin(char board[ROW][COL], int row, int col);

10.测试

可以将棋盘x和y轴更改多个值进行测试,以确保代码的稳定性.

int main()
{
	int input = 0;//定义用户的选择变量
	//生成随机值 srand()函数只会调用一次
	srand((unsigned int)time(NULL));
	do
	{
		menu();//打印简易的菜单
		printf("请选择:>");
		scanf("%d", &input);//接受用户输入的选择
		switch (input)
		{
			case 1:
				game();
				//printf("三子棋游戏\n");
				break;
			case 0:
				printf("退出游戏\n");
				break;
			default:
				printf("选择错误,重新选择\n");
				break;
		}
	} while (input);
	return 0;
}

附:game.c的源码

#include "game.h"
//重复了
//#include <stdio.h>
//“printf”未定义

//初始化棋盘
//数组的每一元素初始化成空格
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;
	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)
		{
			//printf("---|---|---\n");
			int j = 0;
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)
				{
					printf("|");
				}
				
			}
		}
		printf("\n");
	}

}


//函数不够完善 一旦改了行与列这个棋盘会出现问题 行没有问题但是列少了
// 只适用3*3棋盘
//void DispalyBoard(char board[ROW][COL], int row, int col)
//{
//	int i = 0;
//	for (i = 0; i < row; i++)
//	{
//		printf(" %c | %c | %c \n",board[i][0],board[i][1],board[i][2]);
//		if (i < row - 1)
//		{
//			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][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
}

//玩家走
void PlayerMove(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");
		}
	}
	
}

//判断输赢
char  IsWim(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[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];
	}

	// 横线上五子连成一线,赢家产生
	
	//for (i = 0; i < row; i++)
	//{
	//	for (j = 0; j < col - 4; j++)
	//	{
	//		if (board[i][j] == board[i][j + 1]
	//			&& board[i][j + 1] == board[i][j + 2]
	//			&& board[i][j + 2] == board[i][j + 3]
	//			&& board[i][j + 3] == board[i][j + 4]
	//			&& board[i][j] != ' ')
	//		{
	//			return board[i][j];
	//		}
	//	}
	//}

	// 竖线上五子连成一线,赢家产生
	 
	//for (j = 0; j < col; j++)
	//{
	//	for (i = 0; i < row - 4; i++)
	//	{
	//		if (board[i][j] == board[i + 1][j]
	//			&& board[i + 1][j] == board[i + 2][j]
	//			&& board[i + 2][j] == board[i + 3][j]
	//			&& board[i + 3][j] == board[i + 4][j]
	//			&& board[i][j] != ' ')
	//		{
	//			return board[i][j];
	//		}
	//	}
	//}

	// 斜线上五子连成一线,赢家产生
	
	//for (i = 0; i < row - 4; i++)
	//{
	//	if (board[i][i] == board[i + 1][i + 1]
	//		&& board[i + 1][i + 1] == board[i + 2][i + 2]
	//		&& board[i + 2][i + 2] == board[i + 3][i + 3]
	//		&& board[i + 3][i + 3] == board[i + 4][i + 4]
	//		&& board[i][i] != ' ')
	//	{
	//		return board[i][i];
	//	}
	//	if (board[i][i + 4] == board[i + 1][i + 3]
	//		&& board[i + 1][i + 3] == board[i + 2][i + 2]
	//		&& board[i + 2][i + 2] == board[i + 3][i + 1]
	//		&& board[i + 3][i + 1] == board[i + 4][i]
	//		&& board[i][i + 4] != ' ')
	//	{
	//		return board[i][i + 4];
	//	}
	//}

	//判断平局
	//如果棋盘满了返回1 反之0
	int ret = isFull(board, ROW, COL);
	if (1 == ret)
	{
		return 'Q';
	}
	else
	{
		return 'C';
	}
}
//判断棋盘满否
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;//棋盘满了
}

C语言实现三子棋本菜鸡以及写完了,有些缺漏或没写好的请各位大佬请教请教,小生也是第一次写博客,有些写不好的还请勿怪。感谢各位的收看.谢谢大家!

posted @ 2021-10-28 09:21  L-wk  阅读(95)  评论(0)    收藏  举报