您现在的位置是:首页 >学无止境 >使用C语言自定义棋盘大小实现三子棋网站首页学无止境

使用C语言自定义棋盘大小实现三子棋

君落华 2024-06-14 17:18:27
简介使用C语言自定义棋盘大小实现三子棋

一、整个程序的实现思路及设计

实现思路
1.打印一个简单的菜单供玩家选择如下:
image.png
2.玩家下棋
3.电脑下棋
4.判断输赢
5.循环菜单是否要继续游戏
使用多文件的方式编写

  • test.c文件游戏的框架
  • game.c文件游戏的实现
  • game.h文件游戏函数的声明

二、test.c文件的设计

在主函数(main)中的设计

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			//printf("三子棋
");
			game();
			break;
		case 0:
			printf("退出游戏
");
			break;
		default:
			printf("请输入合理的选择
");
			break;
		}

	} while (input);
	return 0;
}

使用menu()函数来打印菜单;

void menu()
{
	printf("***********************************
");
	printf("************    1.paly     ********
");
	printf("************    0.exit     ********
");
	printf("***********************************
");

}

使用do…while循环打印菜单;
使用srand()函数来随机生成电脑下的棋子;
使用switch根据玩家的选择来进行不同的实现;
游戏的实现放在game函数中;

void game()
{
	//char board[3][3] = { 0 };
	初始化棋盘
	//InitBoard(board, 3, 3);

	//定义一个数组用来存放数据
	char board[ROW][COL] = { 0 };
	//初始化棋盘
	InitBoard(board, ROW, COL);
	//打印棋盘
	DispalyBoard(board, ROW, COL);
	char ret = '0';
	while (1)
	{
		//玩家下棋
		PlayerMove(board, ROW, COL);
		//打印棋盘
		DispalyBoard(board, ROW, COL);
		ret=IsWin(board, ROW, COL);
		if (ret!='c')
		{
			break;
		}
		//电脑下棋
		ComputerMove(board, ROW, COL);
		//打印棋盘
		DispalyBoard(board, ROW, COL);
		ret=IsWin(board, ROW, COL);
		if (ret != 'c')
		{
			break;
		}
	}
	if (ret=='*')
	{
		printf("玩家赢
");
	}
	else if (ret == '#')
	{
		printf("电脑赢
");
	}
	else
	{
		printf("平局
");
	}
}

整个test.c文件的代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu()
{
	printf("***********************************
");
	printf("************    1.paly     ********
");
	printf("************    0.exit     ********
");
	printf("***********************************
");

}

void game()
{
	//char board[3][3] = { 0 };
	初始化棋盘
	//InitBoard(board, 3, 3);

	//定义一个数组用来存放数据
	char board[ROW][COL] = { 0 };
	//初始化棋盘
	InitBoard(board, ROW, COL);
	//打印棋盘
	DispalyBoard(board, ROW, COL);
	char ret = '0';
	while (1)
	{
		//玩家下棋
		PlayerMove(board, ROW, COL);
		//打印棋盘
		DispalyBoard(board, ROW, COL);
		ret=IsWin(board, ROW, COL);
		if (ret!='c')
		{
			break;
		}
		//电脑下棋
		ComputerMove(board, ROW, COL);
		//打印棋盘
		DispalyBoard(board, ROW, COL);
		ret=IsWin(board, ROW, COL);
		if (ret != 'c')
		{
			break;
		}
	}
	if (ret=='*')
	{
		printf("玩家赢
");
	}
	else if (ret == '#')
	{
		printf("电脑赢
");
	}
	else
	{
		printf("平局
");
	}
}

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			//printf("三子棋
");
			game();
			break;
		case 0:
			printf("退出游戏
");
			break;
		default:
			printf("请输入合理的选择
");
			break;
		}

	} while (input);
	return 0;
}

三、game.h文件的设计

此文件主要用来声明函数如下:

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 3
#define COL 3
//版本一没有使用对象宏来定义,以后修改更加的麻烦,
//void InitBoard(char board[3][3], int row, int col);
//初始化棋盘,放置空格
void InitBoard(char board[ROW][COL], int row, int col);
//声明打印棋盘的函数
void DispalyBoard(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文件的设计

1.使用InitBoard()函数初始化棋盘

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.使用DispalyBoard()函数打印棋盘
版本一:

void DispalyBoard(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]);
		}
		printf("
");
	}
}

版本二:

void DispalyBoard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		//打印数据
		printf(" %c | %c | %c ", board[i][0], board[i][1], board[i][2]);
		printf("
"); 
		//打印分割行
		if (i<row-1)
		{
			printf("---|---|---");
			printf("
");
		}
		
	}
}

版本三:

void DispalyBoard(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("
");
		//打印分割行 最后一行不答应所以需要判断
		if (i < row - 1)
		{
			int j = 0;
			for ( j = 0; j < col; j++)
			{
				printf("---");
				//最后一个|不打印所以也需要判断
				if (j<col-1)
				{
					printf("|");
				}
			}
			printf("
");
		}

	}
}

就以上三个版本来说:
我觉得最好的就是第三个版本,因为要是想改变棋盘的大小只需要在game.h中修改对象宏的大小即可,前两个版本都有一定的缺陷,我建议使用第三个版本来实现棋盘的打印,这样可以使代码的可读性和后期的修改更好。
3.使用PlayerMove()函数实现玩家下棋

void PlayerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("请输入坐标:
");

	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("坐标被占用,请重新输入。
");
			}
		}
		else
		{
			printf("坐标不合法,请输入合法的坐标:
");
		}
	}
}

以上的代码进行了两次判断:

  • 第一次是判断坐标输入是否合法(也就是坐标是否在棋盘的范围)
  • 第二次是判断坐标是否被占用,要是被占用就使用循环重新输入;

4.使用ComputerMove()函数实现电脑下棋

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

其中使用了rand()函数它的作用是生成随机的值

  • 使用rand()%row是来控制随机值的大小
  • 同时还要再主函数中使用srand()函数来声明
  • 再game.h头文件中还要引用两个头文件(stdlib.h和time.h)

5.使用IsWin()函数实现结果的判断
版本一:

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[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 (IsFull(board,row,col)==1)
	{
		return 'Q';
	}
	//继续
	return 'c';
}

版本二:

char IsWin(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] != ' ') {
				//如果列上连续的三个值相等就返回,注意j+2不能超过列
				if (j < col - 2 && board[i][j] == board[i][j + 1] && board[i][j + 1] == board[i][j + 2]) {
					return board[i][j];
				}
				//如果行上连续的三个值相等就返回,注意i+2不能超过行
				else if (i < col - 2 && board[i][j] == board[i + 1][j] && board[i + 1][j] == board[i + 2][j]) {
					return board[i][j];
				}
				//如果左斜线上连续的三个值相等就返回
				else if (i < row - 2 && j < col - 2 && board[i][j] == board[i + 1][j + 1] && board[i + 1][j + 1] == board[i + 2][j + 2]) {
					return board[i][j];
				}
				//如果右斜线上连续的三个值相等就返回
				else if (i >= 2 && j <= i && board[i][j] == board[i - 1][j + 1] && board[i - 1][j + 1] == board[i - 2][j +2]) {
					return board[i][j];
				}
			}

		}
	}
	//平局
	if (IsFull(board, row, col) == 1)
	{
		return 'Q';
	}
	//继续
	return 'c';
}

以上的两个版本我更加喜欢第二个版本:

  • 当棋盘的大小改变的时候,也可以进行判断不需要再次修改代码
  • 版本一只适合3*3的棋盘

综上考虑个人觉得第二个版本更加的好
6.使用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;
}

下面是game.c完整的代码:

#define _CRT_SECURE_NO_WARNINGS 1
#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] = ' ';
		}
	}
}
//版本1
//void DispalyBoard(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]);
//		}
//		printf("
");
//	}
//}

//版本二
//void DispalyBoard(char board[ROW][COL], int row, int col)
//{
//	int i = 0;
//	for (i = 0; i < row; i++)
//	{
//		打印数据
//		printf(" %c | %c | %c ", board[i][0], board[i][1], board[i][2]);
//		printf("
"); 
//		打印分割行
//		if (i<row-1)
//		{
//			printf("---|---|---");
//			printf("
");
//		}
//		
//	}
//}

//版本三
void DispalyBoard(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("
");
		//打印分割行 最后一行不答应所以需要判断
		if (i < row - 1)
		{
			int j = 0;
			for ( j = 0; j < col; j++)
			{
				printf("---");
				//最后一个|不打印所以也需要判断
				if (j<col-1)
				{
					printf("|");
				}
			}
			printf("
");
		}

	}
}

//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("请输入坐标:
");

	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("坐标被占用,请重新输入。
");
			}
		}
		else
		{
			printf("坐标不合法,请输入合法的坐标:
");
		}
	}
}

//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	x = rand() % row;
	y = rand() % col;
	printf("电脑下棋
");
	while (1)
	{
		if (board[x][y]==' ')
		{
			board[x][y] = '#';
			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++) {
		int j = 0;
		for (j = 0; j < col; j++) {
			//不为空字符进入判断
			if (board[i][j] != ' ') {
				//如果列上连续的三个值相等就返回,注意j+2不能超过列
				if (j < col - 2 && board[i][j] == board[i][j + 1] && board[i][j + 1] == board[i][j + 2]) {
					return board[i][j];
				}
				//如果行上连续的三个值相等就返回,注意i+2不能超过行
				else if (i < col - 2 && board[i][j] == board[i + 1][j] && board[i + 1][j] == board[i + 2][j]) {
					return board[i][j];
				}
				//如果左斜线上连续的三个值相等就返回
				else if (i < row - 2 && j < col - 2 && board[i][j] == board[i + 1][j + 1] && board[i + 1][j + 1] == board[i + 2][j + 2]) {
					return board[i][j];
				}
				//如果右斜线上连续的三个值相等就返回
				else if (i >= 2 && j <= i && board[i][j] == board[i - 1][j + 1] && board[i - 1][j + 1] == board[i - 2][j +2]) {
					return board[i][j];
				}
			}

		}
	}
	//平局
	if (IsFull(board, row, col) == 1)
	{
		return 'Q';
	}
	//继续
	return 'c';
}

以上就是我关于使用C语言怎么自定义棋盘大小来实现三子棋的代码,希望能帮到大家,更好的掌握这门语言,请大家给我多评论,让我知道自己的不足,从而大家共同进步。谢谢大家的点赞!!!!!!!!!!!

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。