【C语言小游戏】三子棋实现详解(自定义棋盘大小)

①前言

作为一个C语言初学者,当学会一些基础知识后就可以自己动手制作一个三子棋小游戏。与平常的三子棋游戏不同的是,本篇博客将会带领你实现自定义棋盘大小的三子棋。②


 ②效果演示

4d9ea5aa75544f358879cb8ab6254954.gif


③实现思路&流程

1.创建菜单函数,选择play或exit。

2.创建二维棋盘数组,并将棋盘初始化。

3.打印棋盘,显示游戏棋盘,给玩家选择坐标下棋。

 

进入循环

{

4.玩家下棋,并打印棋盘,打印棋盘前先清空屏幕,使界面看起来更加舒适(玩家输入行、列坐标,'O'=玩家棋子。

5.判断玩家是否获胜,判断是否继续进行游戏。

6.电脑下棋,并打印棋盘,打印棋盘前先清空屏幕,'X'=电脑棋子。

7.判断电脑是否获胜,判断是否继续进行游戏。

}

8.回到步骤1。


 ④实现过程

1.创建test.c 、gamg.c源文件 和 game.h头文件     三个文件

①这样做的目的是便于对代码进行管理,便于观察。用到的头文件和函数声明放在game.h文件中。

②main函数和游戏主函数以及颜色函数放在test.c文件中。

③游戏功能函数放在game.c文件中。


 

2.在game.h文件中引需要用到的头文件和定义棋盘的行、列

使用宏定义行、列的好处是,当要修改棋盘的大小时,只要修改宏定义就行,不需要全部代码都改一遍。!!!

ROW代表行,COL代表列,<time.h>头文件用于随机数的生成,<Window.h>头文件用于改变棋子的颜色。 

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<Windows.h>

#define ROW 10//行
#define COL 10//列

//多出来的一行一列用来存放数字,以便于找坐标
#define ROWS ROW+1
#define COLS COL+1

 

 3.创建main函数

int main()
{
	srand((unsigned)time(NULL));//用于随机数的生成
	int input = 0;//用户做出选择,1表示开始游戏,0表示退出游戏
	do
	{
		menu();//菜单函数
		printf("请选择:> ");
		scanf("%d", &input);

		system("cls");//清空屏幕,清除上次留下的信息

		switch (input)
		{
		case 1:
			//输入1,进入游戏
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误,请重新选择 ");
			break;
		}
	} while (input);
	return 0;
}

 

 4.创建菜单函数

void menu()//菜单函数
{
	printf("\t\t\t\t\t\t*******************************\n");
	printf("\t\t\t\t\t\t******      三子棋       ******\n");
	printf("\t\t\t\t\t\t******      1.play       ******\n");
	printf("\t\t\t\t\t\t******      2.exit       ******\n");
	printf("\t\t\t\t\t\t*******************************\n");
}

 

 5.实现游戏功能函数

1.初始化棋盘

把落子位置全部置成空格,剩下的位置置成行数字和列数字

void Initbroad(char broad[ROWS][COLS], int rows, int cols)//初始化棋盘
{
	//将下棋区域全部赋上空格' '
	for (int i = 1; i < rows; i++)
	{
		for (int j = 1; j < cols; j++)
		{
			broad[i][j] = ' ';
		}
	}
	//将第一行赋为0,1,2,3,4……
	for (int i = 0; i < cols; i++)
	{
		broad[0][i] = i;
	}
	//将第一列赋为1,2,3,4,5……
	for (int i = 1; i < rows; i++)
	{
		broad[i][0] = i;
	}
}

 

 2.打印棋盘

void Displaybroad(char broad[ROWS][COLS], int rows, int cols)//打印棋盘
{
	//打印第一行的数字
	for (int i = 0; i < rows; i++)
	{
		printf(" %2d ", broad[0][i]);
		if (i < rows - 1)
		{
			printf("|");
		}
	}
	printf("\n");
	for (int i = 1; i < rows; i++)
	{
		//打印分隔线
		for (int i = 0; i < rows; i++)
		{
			printf("----");
			if (i < rows - 1)
			{
				printf("|");
			}
		}

		printf("\n");

		printf(" %2d ", broad[i][0]);//打印第一列的数字
		for (int j = 1; j < cols; j++)
		{
			printf("|");

			if (broad[i][j] == 'O')//如果检测到下个打印的字符为'O',则改变输出字符的颜色
			{
				color(2);//将输出颜色变为绿色
				printf(" %2c ", broad[i][j]);
				color(15);//输出完后,再将输出颜色变为原来的颜色
				continue;//跳出本次循环
			}

			if (broad[i][j] == 'X')//如果检测到下个打印的字符为'X',则改变输出字符的颜色
			{
				color(6);//将输出颜色变为黄色
				printf(" %2c ", broad[i][j]);
				color(15);//输出完后,再将输出颜色变为原来的颜色
				continue;//跳出本次循环
			}

			printf(" %2c ", broad[i][j]);

		}
		printf("\n");
	}
}

打印棋盘过程。 

5d8926e1729c4bdea99688ba3b45dd20.gif


 

 3.玩家下棋函数

void Playermove(char broad[ROWS][COLS], int row, int col)//玩家下棋
{
	printf("玩家走\n");
	int x = 0;//行坐标
	int y = 0;//列坐标
	while (1)
	{
		printf("请选择你的坐标:> ");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)//如果输入坐标在棋盘内,则成立
		{
			if (broad[x][y] == ' ')
			{
				broad[x][y] = 'O';
				break;
			}
			else
			{
				printf("该坐标已被占用,请重新选择\n");
			}
		}
		else
		{
			printf("没有此坐标,请重新输入\n");
		}
	}
}

 

4.电脑下棋函数

void Computermove(char broad[ROWS][COLS], int row, int col)//电脑下棋
{
	printf("电脑走\n");
	while (1)
	{
		int x = rand() % row + 1;//随机生成1~row的数字
		int y = rand() % col + 1;//随机生成1~col的数字
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (broad[x][y] == ' ')
			{
				broad[x][y] = 'X';
				break;
			}
		}
	}
}

 

5.判断输赢函数

判断算法图示

1.判断行

d9ccb59eafb840e5aa19236a1781c183.gif

 2.判断列

2fed1e9242ee40609a4491655adba179.gif

 3.判断斜向

127db548536944ddb39df55a2a03386e.gif

 

char Jugdewin(char broad[ROWS][COLS], int row, int col)//判断输赢
{
	for (int i = 1; i <= row; i++)//控制每一行和每一列
	{
		for (int j = 1; j <= col - 2; j++)
		{
			//判断行是否符合
			if (broad[i][j] == broad[i][j + 1] && broad[i][j + 1] == broad[i][j + 2] && broad[i][j] != ' ')
			{
				return broad[i][j];
			}

			//判断列是否符合
			if (broad[j][i] == broad[j + 1][i] && broad[j + 1][i] == broad[j + 2][i] && broad[j][i] != ' ')
			{
				return broad[j][i];
			}
		}
	}
	//判断斜向是否符合
	for (int i = 1; i <= row - 2; i++)
	{
		for (int j = 1; j <= col - 2; j++)
		{
			if (broad[i][j] == broad[i + 1][j + 1] && broad[i + 1][j + 1] == broad[i + 2][j + 2] && broad[i + 1][j + 1] != ' ')
			{
				return broad[i + 1][j + 1];
			}

			if (broad[i][row - j + 1] == broad[i + 1][row - j] && broad[i + 1][row - j] == broad[i + 2][row - j - 1] && broad[i + 1][row - j] != ' ')
			{
				return broad[i + 1][row - j];
			}
		}
	}
	//检查棋盘是否已满,如果不是,则返回 u
	for (int i = 1; i <= row; i++)
	{
		for (int j = 1; j <= row; j++)
		{
			if (broad[i][j] == ' ')
			{
				return 'u';
			}
		}
	}

	return 'f';
}

如果玩家获胜,则返回'O',如果电脑获胜,则返回'X',如果棋盘已满,则返回'f',如果都不符合,则说明没人获胜,棋盘也没满,则返回'u‘。


 

6.实现游戏主体函数

1.实现输入变化颜色函数

void color(int num)//颜色函数,将'X','O',赋上不同的颜色,以便于观察
{
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), num);
}

 

2.实现游戏主体函数

void game()
{
	char ret;//用于接受“判断输赢函数”的返回值,返回"O",则玩家获胜,返回"X",则电脑获胜,返回'f',则棋盘已满,平局,返回'u’,则继续游戏
	char broad[ROWS][COLS];//二维数组棋盘
	Initbroad(broad, ROWS, COLS);//初始化棋盘
	Displaybroad(broad, ROWS, COLS);//打印棋盘

	while (1)
	{
		Playermove(broad, ROW, COL);//玩家下棋

		system("cls");

		Displaybroad(broad, ROWS, COLS);//打印棋盘

		ret = Jugdewin(broad, ROW, COL);//判断输赢

		if (ret != 'u')//如果Jugdewin不等于'u',则游戏结束,跳出循环
		{
			break;
		}

		Computermove(broad, ROW, COL);//电脑下棋

		system("cls");

		Displaybroad(broad, ROWS, COLS);//打印棋盘

		ret = Jugdewin(broad, ROW, COL);//判断输赢

		if (ret != 'u')//如果Jugdewin不等于'u',则游戏结束,跳出循环
		{
			break;
		}
	}
	if (ret == 'O')
	{
		printf("玩家获胜\n");
	}
	else if (ret == 'X')
	{
		printf("电脑获胜\n");
	}
	else
	{
		printf("平局\n");
	}
}

 

⑤源代码

1.game.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<Windows.h>

#define ROW 10//行
#define COL 10//列

//多出来的一行一列用来存放数字,以便于找坐标
#define ROWS ROW+1
#define COLS COL+1

void Initbroad(char broad[ROWS][COLS], int rows, int cols);//初始化棋盘
void Displaybroad(char broad[ROWS][COLS], int rows, int cols);//打印棋盘

void Playermove(char broad[ROWS][COLS], int row, int col);//玩家下棋
void Computermove(char broad[ROWS][COLS], int row, int col);//电脑下棋

char Jugdewin(char broad[ROWS][COLS], int row, int col);//判断输赢

 

2.test.c

#include"game.h"

void menu()//菜单函数
{
	printf("\t\t\t\t\t\t*******************************\n");
	printf("\t\t\t\t\t\t******      三子棋       ******\n");
	printf("\t\t\t\t\t\t******      1.play       ******\n");
	printf("\t\t\t\t\t\t******      2.exit       ******\n");
	printf("\t\t\t\t\t\t*******************************\n");
}

void color(int num)//颜色函数,将'X','O',赋上不同的颜色,以便于观察
{
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), num);
}

void game()
{
	char ret;//用于接受“判断输赢函数”的返回值,返回"O",则玩家获胜,返回"X",则电脑获胜,返回'f',则棋盘已满,平局,返回'u’,则继续游戏
	char broad[ROWS][COLS];//二维数组棋盘
	Initbroad(broad, ROWS, COLS);//初始化棋盘
	Displaybroad(broad, ROWS, COLS);//打印棋盘

	while (1)
	{
		Playermove(broad, ROW, COL);//玩家下棋

		system("cls");

		Displaybroad(broad, ROWS, COLS);//打印棋盘

		ret = Jugdewin(broad, ROW, COL);//判断输赢

		if (ret != 'u')//如果Jugdewin不等于'u',则游戏结束,跳出循环
		{
			break;
		}

		Computermove(broad, ROW, COL);//电脑下棋

		system("cls");

		Displaybroad(broad, ROWS, COLS);//打印棋盘

		ret = Jugdewin(broad, ROW, COL);//判断输赢

		if (ret != 'u')//如果Jugdewin不等于'u',则游戏结束,跳出循环
		{
			break;
		}
	}
	if (ret == 'O')
	{
		printf("玩家获胜\n");
	}
	else if (ret == 'X')
	{
		printf("电脑获胜\n");
	}
	else
	{
		printf("平局\n");
	}
}

int main()
{
	srand((unsigned)time(NULL));//用于随机数的生成
	int input = 0;//用户做出选择,1表示开始游戏,0表示退出游戏
	do
	{
		menu();//菜单函数
		printf("请选择:> ");
		scanf("%d", &input);

		system("cls");//清空屏幕,清除上次留下的信息

		switch (input)
		{
		case 1:
			//输入1,进入游戏
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误,请重新选择 ");
			break;
		}
	} while (input);
	return 0;
}

 

3.game.c

#include"game.h"

void Initbroad(char broad[ROWS][COLS], int rows, int cols)//初始化棋盘
{
	//将下棋区域全部赋上空格' '
	for (int i = 1; i < rows; i++)
	{
		for (int j = 1; j < cols; j++)
		{
			broad[i][j] = ' ';
		}
	}
	//将第一行赋为0,1,2,3,4……
	for (int i = 0; i < cols; i++)
	{
		broad[0][i] = i;
	}
	//将第一列赋为1,2,3,4,5……
	for (int i = 1; i < rows; i++)
	{
		broad[i][0] = i;
	}
}

void Displaybroad(char broad[ROWS][COLS], int rows, int cols)//打印棋盘
{
	//打印第一行的数字
	for (int i = 0; i < rows; i++)
	{
		printf(" %2d ", broad[0][i]);
		if (i < rows - 1)
		{
			printf("|");
		}
	}
	printf("\n");
	for (int i = 1; i < rows; i++)
	{
		//打印分隔线
		for (int i = 0; i < rows; i++)
		{
			printf("----");
			if (i < rows - 1)
			{
				printf("|");
			}
		}

		printf("\n");

		printf(" %2d ", broad[i][0]);//打印第一列的数字
		for (int j = 1; j < cols; j++)
		{
			printf("|");

			if (broad[i][j] == 'O')//如果检测到下个打印的字符为'O',则改变输出字符的颜色
			{
				color(2);//将输出颜色变为绿色
				printf(" %2c ", broad[i][j]);
				color(15);//输出完后,再将输出颜色变为原来的颜色
				continue;//跳出本次循环
			}

			if (broad[i][j] == 'X')//如果检测到下个打印的字符为'X',则改变输出字符的颜色
			{
				color(6);//将输出颜色变为黄色
				printf(" %2c ", broad[i][j]);
				color(15);//输出完后,再将输出颜色变为原来的颜色
				continue;//跳出本次循环
			}

			printf(" %2c ", broad[i][j]);

		}
		printf("\n");
	}
}

void Playermove(char broad[ROWS][COLS], int row, int col)//玩家下棋
{
	printf("玩家走\n");
	int x = 0;//行坐标
	int y = 0;//列坐标
	while (1)
	{
		printf("请选择你的坐标:> ");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)//如果输入坐标在棋盘内,则成立
		{
			if (broad[x][y] == ' ')
			{
				broad[x][y] = 'O';
				break;
			}
			else
			{
				printf("该坐标已被占用,请重新选择\n");
			}
		}
		else
		{
			printf("没有此坐标,请重新输入\n");
		}
	}
}

void Computermove(char broad[ROWS][COLS], int row, int col)//电脑下棋
{
	printf("电脑走\n");
	while (1)
	{
		int x = rand() % row + 1;//随机生成1~row的数字
		int y = rand() % col + 1;//随机生成1~col的数字
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (broad[x][y] == ' ')
			{
				broad[x][y] = 'X';
				break;
			}
		}
	}
}

char Jugdewin(char broad[ROWS][COLS], int row, int col)//判断输赢
{
	for (int i = 1; i <= row; i++)//控制每一行和每一列
	{
		for (int j = 1; j <= col - 2; j++)
		{
			//判断行是否符合
			if (broad[i][j] == broad[i][j + 1] && broad[i][j + 1] == broad[i][j + 2] && broad[i][j] != ' ')
			{
				return broad[i][j];
			}

			//判断列是否符合
			if (broad[j][i] == broad[j + 1][i] && broad[j + 1][i] == broad[j + 2][i] && broad[j][i] != ' ')
			{
				return broad[j][i];
			}
		}
	}
	//判断斜向是否符合
	for (int i = 1; i <= row - 2; i++)
	{
		for (int j = 1; j <= col - 2; j++)
		{
			if (broad[i][j] == broad[i + 1][j + 1] && broad[i + 1][j + 1] == broad[i + 2][j + 2] && broad[i + 1][j + 1] != ' ')
			{
				return broad[i + 1][j + 1];
			}

			if (broad[i][row - j + 1] == broad[i + 1][row - j] && broad[i + 1][row - j] == broad[i + 2][row - j - 1] && broad[i + 1][row - j] != ' ')
			{
				return broad[i + 1][row - j];
			}
		}
	}
	//检查棋盘是否已满,如果不是,则返回 u
	for (int i = 1; i <= row; i++)
	{
		for (int j = 1; j <= row; j++)
		{
			if (broad[i][j] == ' ')
			{
				return 'u';
			}
		}
	}

	return 'f';
}

⑥结语

创作不易,如果对你有帮助,记得点赞哟!!!

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值