【C语言】民间传统游戏——三子棋详细教学

请添加图片描述三子棋相信大家基本都玩过,也可以称作一条龙、井字棋、圈圈叉叉、九宫棋等等,今天我们来用c语言实现三子棋,此游戏主要练习大家应对偏多代码时函数的使用,创作不易,还请各位小伙伴多多关注,以后也会更新各种小游戏还有关于c语言的博客。


三子棋(介绍)

游戏分为双方对战,双方依次在9宫格棋盘上摆放棋子,率先将自己的三个棋子走成一条线就视为胜利,而对方就算输了,但是三子棋在很多时候会出现和棋的局面。 🌞

实现效果

在这里插入图片描述

🧐首先开始执行程序,一张菜单,可以选择0或者1,0退出,1进入游戏
在这里插入图片描述

如果选择1的话,开始游戏,根据坐标填入数字,直到棋盘满了或者一方先连成一条线获胜为止。

代码实现

1.打印菜单

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

菜单必不可少,让用户进来了解怎么操作

2.main函数

int main()
{
		int input = 0;
		srand((unsigned)time(NULL));   //生成随机数用于人机自动落子
	do 
	{
		menu();    //do-while语句进来先打印菜单栏
		printf("请进行选择(0/1)\n");   //这里进行输入有一个小细节就是把退出设置为0,然后把输入数字放在dowhile()里面这样输入0就直接退出循环了
		scanf("%d", &input);   
		switch (input)       //switch语句进行选择,一目了然
		{
		case 1:
			game();  //进入游戏
			break;
		case 0:
			printf("成功退出");
			break;
		default: 
			printf("输入错误,请重新输入");
			break;
		}
	} while (input); //为0中止
}

由于进程序就有菜单弹出所以这里选择do。while语句,再用switch语句进行判断,当玩家输入1,进入游戏,当玩家输入0,退出程序

  • 让我们想想进入游戏后都需要些什么(也就是game()函数都需要什么)❔
    • 首先我们需要一张棋盘,棋盘本质上来说是一个3*3的空间,我们这里选择用二维数组来放下。
char board[ROW][COL] = { 0 };

3.初始化棋盘

  • 在刚进游戏的时候,棋盘上是空的,所以我们要把棋盘上所有位置都初始化成空格。
void InitBoard(char board[ROW][COL],int row,int col) //形参的名字不能和define定义的相同,不然会报错
{
	for (int i = 0; i < row; i++)     //把棋盘初始化为空格
	{
		for(int j=0;j< col;j++)
		{
			board[i][j] =' ';
		}
	}
    //也可以使用库函数memset
    //memset(&board[0][0], ' ', row * col * sizeof(board[0][0]));
}

4.打印棋盘

  • 初始化棋盘之后我们就可以开始打印了
void printboard(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)		//打印col-1个|,做到  棋子|棋子|棋子
			{
				printf("|");
			}
		}
		printf("\n");
		if (i < row - 1) 	//打印分割线---|---|---
		{
			for (int j = 0; j < col; j++)
			{
				printf("---");			
				if (j < COL - 1)
				{
					printf("|");
				}
			}
			printf("\n");
		}
	}
}

✨✨如果游戏开始只有棋子,那么玩家看到的是一片空,所以我们要打印一个棋盘出来,这里选择用ROW(行)和COL(列)来控制棋盘的长短,如果想打印更大的棋盘就只需改掉define定义的ROW和COL即可。

在这里插入图片描述

5.玩家落子

  • 打印完棋盘之后玩家进行落子
void playerMove(char board[ROW][COL], int row, int col)//~玩家下子
{
	printf("该你了,请选择坐标(?,?)\n");
	while (1)
	{
		int num1=0;				//玩家输入的行
		int num2=0;				//玩家输入的列
		scanf("%d,%d", &num1, &num2);
		if ((num1 > 3 || num1 < 0) || (num2 > 3 || num2 < 0))	//如果超出棋盘范围,结束本次循环重新选择
		{
			printf("请输入正确位置");
			continue;
		}
		if (board[num1-1][num2-1] == ' ')	
		{
			board[num1-1][num2-1] = '*';    //返回1 ,落子成功,跳出循环
			break;
		}
		else   
		{
			printf("请选择空位下子\n");     //返回0 落子失败,重新输入
		}
	}
}

✨✨轮到玩家输入,首先要给个提示,提示玩家落子,如果玩家输入的坐标不对的话,提示重新下子,如果玩家输入的坐标已经有棋子的话,提示重新下子。

6.人机落子

  • 玩家落子之后人机落子
void computerMove(char board[ROW][COL], int row, int col)//~电脑下子
{
	while(1)
	{
		int num1 = rand() % row;     //生成随机数并取模row,保证row范围在棋盘大小内
		int num2 = rand() % col;	 //生成随机数并取模COL,保证COL范围在棋盘大小内
		if (board[num1][num2] == ' ')	
		{
			board[num1][num2] = '#';		//如果为空落子成功,如果不为空重新生成随机数
			break;
		}
	}
	printf("人机落子并说道:你输定了小伙子\n");
}

7.判断输赢

  • 判断输赢是很重要的一步,不论是玩家落子后或电脑落子后,我们都应该进行判断程序是否应该结束
char ending(char board[ROW][COL], int row, int col) //判断游戏是否应该结束
{
	for (int i = 0; i < ROW; i++)
	{
		if (board[0][i] == board[1][i] && board[1][i] == board[2][i])
		{
			return board[0][i]; //列相等返回所在列的字符,游戏结束
		}
	}
	for (int i = 0; i < COL; i++)
	{
		if (board[i][0] == board[i][1] && board[i][1] == board[i][2])
		{
			return board[i][1];//行相等返回所在行的字符,游戏结束
		}
	}
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2])
	{
		return board[1][1];//斜线相等返回所在字符,游戏结束
	}
	if (board[0][2] == board[1][1] && board[1][1] == board[2][0])
	{
		return board[1][1];//斜线相等返回所在字符,游戏结束
	}
	for (int i = 0; i < ROW; i++)
	{
		for (int j = 0; j < COL; j++)
		{
			if (board[i][j] == ' ')
			{
				return;		//如果还有空位,则游戏继续
			}
		}
	}
	return 'q';//运行到这里证明棋盘已经满了,游戏结束
}

8.game函数

  • 最后我们根据这些函数的作用将所有的函数整合到一块,就形成了我们整个游戏程序
void game()
{
	char board[ROW][COL] = { 0 };     //三子棋是一个长3宽3的棋盘,这里用二维数组来装这个棋盘
	init(board, ROW, COL);			  //此函数用于二维数组初始化
	printboard(board, ROW, COL);      //~用于打印棋盘
	while (1)
	{
		char end = '\0';
		playerMove(board, ROW, COL);	//~玩家下子
		printboard(board, ROW, COL);		//~打印棋盘
		end = ending(board, ROW, COL); //查看是否应该结束
		if (end == '*')			//返回值为*玩家胜利
		{
			printf("Player WIN!!!\n");
			break;
		}
		else if (end == 'q')		//返回值为棋盘满了未分胜负,平局,退出游戏
		{
			printf("敌人太强大了,居然平分秋色\n");
		}
		computerMove(board, ROW, COL);		//~电脑下子
        printboard(board, ROW, COL);		//打印棋盘
		end = ending(board, ROW, COL);	//查看是否应该结束
		if (end == '#')			//返回值为#人机获得胜利
		{
			printf("Computer WIN!!!\n");
			break;
		}
		else if (end == 'q')
		{
			printf("平局\n");			
		}

	}
}

文件分类

🌞🌞为了使代码更有阅读性,我们不建议把所有函数写在一个文件里,所以这里分成三个文件

test.c

  • 这个文件包含程序的主体构思,程序用到的一系列函数我们封装在其他文件夹,这里只需要引入头文件即可
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"

void menu() //菜单
{
	printf("****************************\n");
	printf("******    1.  play     *****\n");
	printf("******    0.  exit     *****\n");
	printf("****************************\n");
}
void game()
{
	char board[ROW][COL] = { 0 };     //三子棋是一个长3宽3的棋盘,这里用二维数组来装这个棋盘
	initboard(board, ROW, COL);			  //此函数用于二维数组初始化
	printboard(board, ROW, COL);      //~用于打印棋盘
	while (1)
	{
		char end = '\0';
		playerMove(board, ROW, COL);	//~玩家下子
		printboard(board, ROW, COL);		//~打印棋盘
		end = ending(board, ROW, COL); //查看是否应该结束
		if (end == '*')
		{
			printf("Player WIN!!!\n");
			break;
		}
		else if (end == 'q')
		{
			printf("敌人太强大了,居然平分秋色\n");
		}
		computerMove(board, ROW, COL);		//~电脑下子
		printboard(board, ROW, COL);		//打印棋盘
		end = ending(board, ROW, COL);	//查看是否应该结束
		if (end == '#')
		{
			printf("Computer WIN!!!\n");
			break;
		}
		else if (end == 'q')
		{
			printf("平局\n");
		}

	}
}

int main()
{
		int input = 0;
		srand((unsigned)time(NULL));   //生成随机数用于人机自动落子
	do 
	{
		menu();    //do-while语句进来先打印菜单栏
		printf("请进行选择(0/1)\n");   //这里进行输入有一个小细节就是把退出设置为0,然后把输入数字放在dowhile()里面这样输入0就直接退出循环了
		scanf("%d", &input);   
		switch (input)       //switch语句进行选择,一目了然
		{
		case 1:
			game();  //进入游戏
			break;
		case 0:
			printf("成功退出");
			break;
		default: 
			printf("输入错误,请重新输入");
			break;
		}
	} while (input);
}

game.c

  • 进入游戏后需要的所有函数都封装在这里
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"

void initboard(char board[ROW][COL],int row,int col)//此函数用于二维数组初始化
{
	memset(&board[0][0], ' ', row * col * sizeof(board[0][0]));
}

void printboard(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("---");
				if (j < COL - 1)
				{
					printf("|");
				}
			}
			printf("\n");
		}
	}
}

void playerMove(char board[ROW][COL], int row, int col)//~玩家下子
{
	printf("该你了,请选择坐标(?,?)\n");
	while (1)
	{
		int num1=0;
		int num2=0;
		scanf("%d,%d", &num1, &num2);
		if ((num1 > 3 || num1 < 0) || (num2 > 3 || num2 < 0))
		{
			printf("请输入正确位置");
			continue;
		}
		if (board[num1-1][num2-1] == ' ')
		{
			board[num1-1][num2-1] = '*';
			break;
		}
		else
		{
			printf("请选择空位下子\n");
		}
	}
}

void computerMove(char board[ROW][COL], int row, int col)//~电脑下子
{
	while(1)
	{
		int num1 = rand() % row;
		int num2 = rand() % col;
		if (board[num1][num2] == ' ')
		{
			board[num1][num2] = '#';
			break;
		}
	}
	printf("你输定了小伙子\n");
}
char ending(char board[ROW][COL], int row, int col) //判断游戏是否应该结束
{
	for (int i = 0; i < ROW; i++)
	{
		if (board[0][i] == board[1][i] && board[1][i] == board[2][i])
		{
			return board[0][i]; //列相等返回所在列的字符,游戏结束
		}
	}
	for (int i = 0; i < COL; i++)
	{
		if (board[i][0] == board[i][1] && board[i][1] == board[i][2])
		{
			return board[i][1];//行相等返回所在行的字符,游戏结束
		}
	}
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2])
	{
		return board[1][1];//斜线相等返回所在字符,游戏结束
	}
	if (board[0][2] == board[1][1] && board[1][1] == board[2][0])
	{
		return board[1][1];//斜线相等返回所在字符,游戏结束
	}
	for (int i = 0; i < ROW; i++)
	{
		for (int j = 0; j < COL; j++)
		{
			if (board[i][j] == ' ')
			{
				return;		//如果还有空位,则游戏继续
			}
		}
	}
	return 'q';//运行到这里证明棋盘已经满了
}

game.h

  • 将;主程序所需要的函数全部在头文件中声明,增加代码阅读性
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#define COL  3
#define ROW  3

void printboard(char board[ROW][COL], int row, int col);//~用于打印棋盘
void initboard(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 ending(char board[ROW][COL], int row, int col);//查看是否应该结束

撒花

这就是实现三子棋的全部内容了,创作不易,还请各位小伙伴多多点赞关注,以后也会更新各种小游戏还有关于c语言的博客。

请添加图片描述

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值