C语言学习过程中不容错过的小游戏(1)--三子棋

三子棋的介绍

   三子棋又叫井字棋,就是我们小时候上课偷偷和同学在下面玩的圈圈叉叉。
规则很简单:只要将自己的三个棋子走成一条线,则获胜        

三子棋的基本流程

用户交互页面

首先我们要创建一个菜单栏函数,实现与用户的交互

//打印菜单
void menu()
{
	printf("游戏规则:* 代表玩家的棋子; # 代表电脑的棋子\n");
	printf("输入需要落子的行和列即可落子\n");
	printf("三个相同的连成一线则获胜\n");
	printf("**************************************\n");
	printf("*************     1.play    **********\n");
	printf("*************     0.exit    **********\n");
	printf("**************************************\n");
	printf("请选择是否开始游戏(1 开始游戏 0 退出游戏):\n");
}

效果如下
在这里插入图片描述

游戏循环设置(一盘不过瘾,可以选择一直玩)

这里就需要用到我们学过的一个循环语句–do-while循环,它可以保证至少进行一次游戏

int main()
{
	srand((unsigned int)time(NULL));//用作产生随机数
	int input;
	do
	{
		menu();//打印用户交互菜单
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("开始游戏>\n");
			playgame();
			break;
		case 0:
			printf("退出\n");
			break;
		default:
			printf("输入错误!请重新输入:\n");
		}
	} while (input);
	return 0;
}

初始化棋盘

初始化,棋盘的过程中,需要将棋盘的每一个格子都是空格,这里用一个双重循环就可以实现

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

打印棋盘

整个棋盘是由棋子和格子构成,棋子用 * 和 # 表示;格子我们用 - 和 | 来构建
再通过for循环语句进行排列,一个规矩大方的棋盘就诞生了

//打印棋盘
void PrintArr(char arr[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	for ( i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			printf("%c", arr[i][j]);
			if (j < col - 1)
				printf("  |");
				
	    }
		printf("\n");
		if(i<row-1)
		for (j = 0; j < col; j++)
		{
			printf("---");
			if (j < col - 1)
				printf("|");
		}
		printf("\n");
	}
}

效果如下
在这里插入图片描述

玩家落子

采用输入行和列的方式来落子,同时我们需要判断输入行和列是否正确,落子区域是否已经被占用。 如果玩家输入输入结果超出范围,提醒玩家输入错误,重新输入;如果格子已被占用,提醒玩家该棋格已被占用!,请重新输入。输入正确,玩家落子为‘ * ’

//玩家落子
void PlayerMove(char arr[ROW][COL], int row, int col) 
{
	int i=0, j=0;
	while (1)
	{
		scanf("%d%d", &i, &j);
		if (i < 0 ||j < 0 || i > row || j >col)//判断输入是否正确
		{
			printf("输入错误!请重新输入:");
			continue;
		}
		if (i <=row &&i > 0 && j <=col && j > 0)//输入正确,落子为‘ * ’
		{
			if (JudgeOccupy(arr, i-1, j-1))//判断棋格是否被占用
			{
				arr[i-1][j-1] = '*';
				break;
			}
			else
				printf("该棋格已被占用!,请重新输入:");
		}
	}
}

上面代码中,为了简化代码,用了一个判断棋格是否被占用的函数JudgeOccupy(),实现如下

//判断棋格是否被占用
int JudgeOccupy(char arr[ROW][COL], int row, int col)
{
	if (arr[row][col] == '*' || arr[row][col] == '#')
		return 0;
	else
		return 1;
}

最后效果如下
在这里插入图片描述

电脑落子

电脑落子和玩家落子差不多,只不过是有电脑随机产生落子的行和列;怎么随机产生行和列呐,这里我们要用到一个rand 函数,他的作用是产生一个0-32767的随机数,在模上一个3,就可以得到0-3之间的随机数了。

//电脑落子
void ComputerMove(char arr[ROW][COL], int row, int col)
{
	while (1)
	{
		int i = rand() % 3;//产生行和列
		int j = rand() % 3;
		if (JudgeOccupy(arr, i, j))
		{
			arr[i][j] = '#';
			break;
		}
	}

}

判断游戏胜负

在游戏进行的过程中我们会遇见4种情况:
1.玩家赢了
2.电脑赢了
3.棋盘满了,平局了
4.什么事情都没发生,游戏继续。
那么我们规定这个判断游戏胜负的函数,如果玩家赢了返回‘ * ’,电脑赢了返回‘ # ’,平局了返回‘ Q’,无事发生游戏继续返回‘ C ‘。

//判断是否赢得比赛
char JudgeWin(char arr[ROW][COL], int row, int col)
{
	//判断一行是否相等
	for (int i = 0; i < row; i++)
	{
		if (arr[i][0] == arr[i][1] && arr[i][1] == arr[i][2]&&arr[i][1]!=' ')
			return arr[i][1];
	}
	//判断一列是否相等
	for (int i = 0; i < col; i++)
	{
		if (arr[0][i] == arr[1][i] && arr[1][i] == arr[2][i] && arr[0][i] != ' ')
			return arr[0][i];
	}
	//判断对角线是否相等
	if (arr[0][0] == arr[1][1] && arr[1][1] == arr[2][2] && arr[0][0] != ' ')
		return arr[0][0];
	if (arr[0][2] == arr[1][1] && arr[1][1] == arr[2][0] && arr[0][2] != ' ')
		return arr[0][2];
	int ret = IsFull(arr, row, col);
	if (ret == 1)
		return 'Q';
	//什么都没发生继续游戏
	return 'C';
}

上面代码中判断棋盘是否满了的函数IsFull()实现如下

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

游戏实现函数

这个函数,我们需要将上面的函数整合到一起,实现一个游戏的运行整个过程。

//游戏的实现
void playgame()
{
	int ret = 0;
	char arr[ROW][COL] = { 0 };
	InitArr(arr, ROW, COL);//初始化棋盘
	PrintArr(arr, ROW, COL);//打印棋盘
	while (1)
	{
		printf("玩家走>\n");
		PlayerMove(arr, ROW, COL);
		PrintArr(arr, ROW, COL);
		ret = JudgeWin(arr, ROW, COL);//判断玩家是否获胜
		if (ret != 'C')
			break;
		printf("电脑走>\n");
		ComputerMove(arr, ROW, COL);
		PrintArr(arr, ROW, COL);
		ret = JudgeWin(arr, ROW, COL);//判断电脑是否获胜
		if (ret != 'C')
			break;
	}
	if (ret == '*')
		printf("恭喜玩家赢了\n");
	if (ret == '#')
		printf("很遗憾电脑赢了\n");
	if (ret == 'Q')
		printf("平局\n");
}

效果如下
在这里插入图片描述

总代码

为了方便代码的管理与测试,我将全部代码分为了三部分
1.头文件:用于函数的申明
2.game.c文件:用于函数的实现
3.text.c文件:代码的测试

头文件如下

#pragma once
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#define ROW 3//行
#define COL 3//列
//打印菜单
void menu();
//游戏的实现
void playgame();
//初始化棋盘
void InitArr(char arr[ROW][COL], int row, int col);
//打印棋盘
void PrintArr(char arr[ROW][COL], int row, int col);
//玩家落子
void PlayerMove(char arr[ROW][COL], int row, int col);
//电脑落子
void ComputerMove(char arr[ROW][COL], int row, int col);
//判断棋格是否被占用
int JudgeOccupy(char arr[ROW][COL], int row, int col);
//判断是否赢得比赛
char JudgeWin(char arr[ROW][COL], int row, int col);
//判断棋盘是否满了
int IsFull(char arr[ROW][COL], int row, int col);

game.c文件如下

#include "game.h"
//打印菜单
void menu()
{
	printf("游戏规则:* 代表玩家的棋子; # 代表电脑的棋子\n");
	printf("输入需要落子的行和列即可落子\n");
	printf("三个相同的连成一线则获胜\n");
	printf("**************************************\n");
	printf("*************     1.play    **********\n");
	printf("*************     0.exit    **********\n");
	printf("**************************************\n");
	printf("请选择是否开始游戏(1 开始游戏 0 退出游戏):\n");
}
//游戏的实现
void playgame()
{
	int ret = 0;
	char arr[ROW][COL] = { 0 };//创建棋盘
	InitArr(arr, ROW, COL);//初始化棋盘
	PrintArr(arr, ROW, COL);//打印棋盘
	while (1)
	{
		printf("玩家走>\n");
		PlayerMove(arr, ROW, COL);
		PrintArr(arr, ROW, COL);
		ret = JudgeWin(arr, ROW, COL);//判断玩家是否获胜
		if (ret != 'C')
			break;
		printf("电脑走>\n");
		ComputerMove(arr, ROW, COL);
		PrintArr(arr, ROW, COL);
		ret = JudgeWin(arr, ROW, COL);//判断电脑是否获胜
		if (ret != 'C')
			break;
	}
	if (ret == '*')
		printf("恭喜玩家赢了\n");//公布游戏结果
	if (ret == '#')
		printf("很遗憾电脑赢了\n");
	if (ret == 'Q')
		printf("平局\n");
}
//初始化棋盘
void InitArr(char arr[ROW][COL],int row,int col)
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
			arr[i][j] = ' ';
	}
}
//打印棋盘
void PrintArr(char arr[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	for ( i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			printf("%c", arr[i][j]);
			if (j < col - 1)
				printf("  |");
				
	    }
		printf("\n");
		if(i<row-1)
		for (j = 0; j < col; j++)
		{
			printf("---");
			if (j < col - 1)
				printf("|");
		}
		printf("\n");
	}
}
//玩家落子
void PlayerMove(char arr[ROW][COL], int row, int col) 
{
	int i=0, j=0;
	while (1)
	{
		scanf("%d%d", &i, &j);
		if (i < 0 ||j < 0 || i > row || j >col)//判断是否输入错误
		{
			printf("输入错误!请重新输入:");
			continue;
		}
		if (i <=row &&i > 0 && j <=col && j > 0)
		{
			if (JudgeOccupy(arr, i-1, j-1))//判断棋格是否被占用
			{
				arr[i-1][j-1] = '*';//输入正确,落子为’*‘
				break;
			}
			else
				printf("该棋格已被占用!,请重新输入:");
		}
	}
}
//电脑落子
void ComputerMove(char arr[ROW][COL], int row, int col)
{
	while (1)
	{
		int i = rand() % 3;
		int j = rand() % 3;
		if (JudgeOccupy(arr, i, j))
		{
			arr[i][j] = '#';
			break;
		}
	}

}
//判断棋格是否被占用
int JudgeOccupy(char arr[ROW][COL], int row, int col)
{
	if (arr[row][col] == '*' || arr[row][col] == '#')
		return 0;
	else
		return 1;
}
//判断是否赢得比赛
char JudgeWin(char arr[ROW][COL], int row, int col)
{
	//判断一行是否相等
	for (int i = 0; i < row; i++)
	{
		if (arr[i][0] == arr[i][1] && arr[i][1] == arr[i][2]&&arr[i][1]!=' ')
			return arr[i][1];
	}
	//判断一列是否相等
	for (int i = 0; i < col; i++)
	{
		if (arr[0][i] == arr[1][i] && arr[1][i] == arr[2][i] && arr[0][i] != ' ')
			return arr[0][i];
	}
	//判断对角线是否相等
	if (arr[0][0] == arr[1][1] && arr[1][1] == arr[2][2] && arr[0][0] != ' ')
		return arr[0][0];
	if (arr[0][2] == arr[1][1] && arr[1][1] == arr[2][0] && arr[0][2] != ' ')
		return arr[0][2];
	int ret = IsFull(arr, row, col);
	if (ret == 1)
		return 'Q';
	//什么都没发生继续游戏
	return 'C';
}
//判断棋盘是否满了
int IsFull(char arr[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			return 0;
		}
	}
	return 1;
}

text.c文件

#include "game.h"
int main()
{
	srand((unsigned int)time(NULL));
	int input;
	do
	{
		menu();
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("开始游戏>\n");
			playgame();
			break;
		case 0:
			printf("退出\n");
			break;
		default:
			printf("输入错误!请重新输入:\n");
		}
	} while (input);
	return 0;
}

小编总结

首先给大家指出以上代码一个不好的地方,就是棋盘的命名应该为Board,而不是Arr,这样代码更具有可读性,一目了然。(那为啥小编还是写的Arr,其实我也不想,当我写完代码的时候才发现命名有点问题,呜呜呜,全部改回来,太难了,就用的Arr),特在此指出。
如果本文章对你有一点点的帮助,那请点上一个小赞。您的支持与鼓励,将是我继续写作的不竭动力,非常感谢~~

评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值