栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C语言小游戏项目之三子棋

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C语言小游戏项目之三子棋

目录

三子棋的游戏逻辑

实现的大致思路

主菜单的思路

game函数的实现建议及其实现思路和代码

game函数的实现建议

game函数的实现思路

game函数代码框架

初始化二维数组boardInint实现

打印棋盘displayBoard实现

玩家落子(player_move)和电脑落子(computer_move)的实现

判断输赢函数(is_win)的思路和实现

运行结果

 小结


三子棋的游戏逻辑

三子棋游戏也叫井字棋

游戏的逻辑比较简单,三个一样的符号连成一行或者一列或者对角线即可胜出。

当然基于两人对战的情况下大多数都是平局。

实现的大致思路

和玩游戏一样,点开程序(程序运行)--->选择(游玩或者退出)--->游玩--->游戏结束--->选择--->再来一把或者退出。基于这个思路就可以很好实现这个代码了

主菜单的思路

和一般的游戏主菜单一样,通常使用do while 循环。

do while 循环的好处是先循环在判断,可以多循环一次,一般来说游戏的界面都是用这个框架来实现。

用menu函数对玩家的进行一个可供选则的一个提示。

如让玩家输入数字,用swtich语句对输入的数字进行一个选择 。例如输入1进行游戏,输入0退出。

那有的人输入错了,输入0或者1之外的其他数字。c语言中0为假,此外都是真,则会让玩家一直进行选择的一个循环

int main()
{
	int input = 0;	
	do
	{
		menu();//提示玩家因该输入什么数字
		scanf("%d", &input);//玩家输入数字	
		switch (input)//对玩家输入的数字进行选择
		{
		case 1:
			game();//进行游戏
			break;
		case 0:
			printf("游戏结束n");//游戏结束退出
			break;
		default:
			printf("选择错误n");//除0或者1之外的数字就会再打印一次菜单进行选择
			break;
		}
	} while (input);
	return 0;
}

game函数的实现建议及其实现思路和代码

game函数的实现建议

这里建议先简单打印一下“玩游戏”,检查一下之前写的代码有无错误,写一步运行一下。即使发现错误,也能及时修改;

等到最后代码写完了最后检查会比较费时费力;

例如printf(“玩游戏”)运行。

实现game函数比较复杂,需要用多个函数实现;

因此建议创建一个game.h的头文件用来声明game使用的函数;

用game.c的源文件来实现game.h声明的函数;

用test.c的源文件来对game.c来测试;当然,test.c和game.c最开头都要先声明一下

例如#include“game.h”

如果不用多个文件实现的话,代码都堆在一个文件会造成冗余,不够清晰,缺乏观赏性。

game函数的实现思路

三子棋游戏的棋盘像3×3的二维数组,下棋相当于在二维数组里面放字符。

基于这个思路我们先初始化一下这个二位数组;

然后打印棋盘,打印棋盘,玩家落子,打印棋盘,判断胜负,电脑落子,打印棋盘,判断胜负。

如果胜负未定,则一直循环玩家落子和电脑落子的过程;

当判断一方胜负或者棋盘下满为和棋之时就跳出这个循环游戏结束。

game函数代码框架
void game()
{
	char board[ROW][COL] = {0};
	boardInint(board,ROW,COL);//棋盘初始化
	displayBoard(board,ROW,COL);//打印棋盘
	char tmp = 0;
	while (1)
	{
		player_move(board, ROW, COL);//玩家下棋
		displayBoard(board, ROW, COL);//打印棋盘
		tmp = is_win(board, ROW, COL);//判断输赢
		if (tmp != 'c')//游戏是否继续
		{
			break;
		}			
		computer_move(board, ROW, COL);//电脑下棋
		displayBoard(board, ROW, COL);//打印棋盘
		tmp= is_win(board, ROW, COL);//判断输赢
		
		if (tmp != 'c')//游戏是否继续
		{
			break;
		}		
	}
	if (tmp == '*')
	{
		printf("恭喜你赢得游戏!n");
	}
	if (tmp == '#')
	{
		printf("很遗憾,你输了n");

	}
	if (tmp == 'p')
	{
		printf("平局n");
	}

}

用到的函数在头文件声明

初始化二维数组boardInint实现

初始化棋盘只要在二位数组里面放上空格就行

void boardInint(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] =' ';
		}
	}
}

打印棋盘displayBoard实现

打印棋盘就是打印二维数组里面的字符内容及其分隔符号;

分隔符号的打印可以打印一个空格一个字符再加一个空格,然后打印“|”,

在下一排打印“---|---|---”;

注意在边界是不需要打印“|”和“---|---|---”的。

 具体代码如下

void displayBoard(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++)
		{
			printf(" %c ", board[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");

	}
}

玩家落子(player_move)和电脑落子(computer_move)的实现

玩家落子和电脑落逻辑基本相同;

需要注意的是玩家落子和数组的起始数字;

玩家的起始数字的1,数组却是0;

玩家落子代码如下

void player_move(char board[ROW][COL], int row, int col)//玩家下棋
{
	printf("玩家下棋n");
	int x = 0;
	int y = 0;
	while (1)
	{
		printf("请输入坐标");
		scanf("%d %d", &x, &y);
		if (board[x - 1][y - 1] == ' ' && x >= 0 && x <= row && y >= 0 && y <= col)//玩家落子的范围必须在0-3和0-3之间并且此处没有字符,否则非法,循环继续落子
		{
			board[x - 1][y - 1] = '*';
			break;
		}
		else
			printf("坐标非法!");
	}
}

电脑落子需要用到两个函数

rand() 和srand()这两个函数

用rand随机生成一个数字的时候,需要用一个随机数来定义srand的标准;需要随机数又要用随机数来生成随机数,有点矛盾,但使用时间戳能解决这个问题,因为时间是不断在变化,时间戳会把时间转换成数字;

具体用法如下

srand((unsigned int)time(NULL));
int x = rand() ;

注意需要用#include 和#include 两个头文件,

srand((unsigned int)time(NULL));这句代码放在主函数开头就可以了,标准只需要设置一次就好

同样需要注意的是玩家落子和数组的起始数字;

玩家的起始数字的1,数组却是0;

电脑落子具体代码如下

void computer_move(char board[ROW][COL], int row, int col)//电脑下棋
{
	printf("电脑下棋n");

	while (1)
	{
		int x = rand() % 3 + 1;// 用随机数模上一个数字会生成0到(x-1)之间的数字,加一就会随机生成0到x之间的数字
		int y = rand() % 3 + 1;
		if (board[x - 1][y - 1] == ' ' && x >= 0 && x <= row && y >= 0 && y <= col)
		{
			board[x - 1][y - 1] = '#';
			break;
		}
	}
}

判断输赢函数(is_win)的思路和实现

用函数来判断输赢最好用一个返回字符来判断游戏是否继续和胜出;

例如玩家赢就返回玩家的落子字符,电脑赢就返回电脑落子的字符;

没有胜负就返回一个’c‘来使函数继续执行玩家落子和电脑落子;

此外非’c‘都可以市循环继续;

平局就返回”p“使循环结束;

平局需要再用一个函数(is_full)判断(is_full函数只需检查数组里面是不是没有空字符即可)

(is_win)具体代码如下

char is_win(char board[ROW][COL], int row, int col)//判断输赢,有四种情况,玩家赢,电脑赢,平局还有继续下棋,因此用返回的字符来判断是哪一种情况

{
	if (board[0][0] == board[1][1]&& board[1][1] == board[2][2]&&board[1][1]!=' ')//两条对角线相同
		return board[0][0];
	if (board[0][2] == board[1][1]&& board[1][1] == board[2][0] && board[1][1] != ' ')
		return board[0][2];
	for (int 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 (int i = 0; i < row; i++)
	{
		if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')//一列三个相同
			return board[i][0];
	}
	//平局只能是棋盘都下满了
	if (is_full(board, row, col) == 1)
		return 'p';
	//继续下棋
	return 'c';
}

(is_full)具体代码如下

int is_full(char board[ROW][COL], int row, int col)
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			if (board[i][j] == ' ')//还有空格,表示棋盘没满
				return 0;
		}
	}
	return 1;//循环结束都不是空格表示期盼满了
}

运行结果

 小结

该代码只能写出傻瓜电脑,如果需要电脑更加聪明,则需要在电脑落子的算法上进行优化。

还可以在每次落子之时用system('cls');这行代码清理一下屏幕,使其游戏体验更佳。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/457421.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号