帅气的三字棋

目录

>三子棋的实现要点

·应用多文件的形式写代码

·游戏不退出,玩了一把又一把

·正式游戏

>具体代码实现

·游戏菜单

·主函数使用菜单

·重复的选择玩游戏

·开始游戏

*game函数

*InitBoard函数 

*DisplayBoard函数

#打印棋盘格子(行灵活)

 #列灵活

·下棋

*玩家下棋

#PlayerMove函数

#检验报错

 *电脑下棋

 #ComputerMove函数

#rand函数,srand函数,time函数

#检验报错

 ·判断输赢

#Iswin函数

 ·判断平局

#Isfull函数


>三子棋的实现要点

三字棋程序的关键点,以下。

·应用多文件的形式写代码

test.c —— 测试游戏部分。

game.c —— 游戏函数的实现部分。

game.h —— 游戏函数的声明部分。

·游戏不退出,玩了一把又一把

do—while循环。

·正式游戏

3*3的二维数组。

由空格元素替换为*或者#作为棋。

>具体代码实现

·游戏菜单

打印一个简易版的游戏菜单。

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

不需要返回值,void。别忘记\n。

·主函数使用菜单

在主函数中调用菜单

int main()
{
	menu();
	int input = 0;
	printf("请选择>:");//提示输入
	scanf("%d", &input);//输入 0,1或其他

	return 0
}

选择后给予响应,使用switch语句来实现

switch (input)//switch()中的表达式只能是整型,字符型或枚举型表达式
    {
    case 1:
        game();//玩游戏,game函数实现
        break;//break在case语句中尤为重要,如果不加,则会继续执行下面的case
    case 0:
        printf("退出游戏");//提醒语句
        break;
    default://default可以放在switch中的任意位置,如果不是放在最后也要有break
        printf("选择错误,请重新选择>:");
        break;
    }

·重复的选择玩游戏

游戏不退出,玩了一把又一把,循环来实现

int main()
{
	int input = 0;//要放在循环外部
	
	do
	{
		menu();
	
		printf("请选择>:");
		scanf("%d", &input);

		switch (input)
		{}

	} while (input);//除了选择0退出游戏以外,无论选择什么都需要重新打印菜单
	//计算while()中的表达式,如果值为真(非零),则继续执行循环体,如果值为假(零),则退出循环
	
	return 0;

}

实现效果 

·开始游戏

究其根本,三字棋游戏其实是一个3*3的二维数组。

*game函数

定义一个游戏函数game()来实现

void gamne()
{
	char board[3][3] = { 0 };
	InitBoard(board, 3, 3);//利用函数来初始化数组,将行和列都传参过去

}

*InitBoard函数 

利用函数InitBoard进行数组的初始化,并在另一个文件game.h中进行函数的声明

 此时创建的是一个3*3的数组,为防止3*3“棋盘”不够用需要更改的情况,我们采用宏定义的方式。

以便后期更改棋盘的格式。

#define ROW 3
#define COL 3

InitBoard(char board[ROW][COL], int row, int col);

要使用另一个文件中的宏定义,要包含自己创建的这个头文件。这样任何需要行列的地方都可以使用ROW,COL。

函数声明结束,接下来在第三个文件game.c中对函数进行实现。

注意:在第三个头文件中仍然要包含自己创建的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] = ' ';
		}
	}
}

 此时数组已经全部初始化为空格。

*DisplayBoard函数

利用DisplayBoard函数来打印验证是不是数组均已初始化为空格,依旧在game.h文件中进行声明,在game.c文件中进行实现。

void DisplayBoard(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]);//char类型的用%c进行打印

		}
		printf("\n");//打印完一行记得换行
	}
}

运行

此时打印了数组空格,但我们看不到,打印X更直观

#打印棋盘格子(行灵活)

 加上分割线,只需一层行循环。数据分割线,数据分割线,数据分割线。

    int i = 0;
	for (i = 0; i < row; i++)
	{
		printf(" %c | %c | %c \n",board[i][0], board[i][1], board[i][2]);//char类型的用%c进行打印
		printf("---|---|---");
		printf("\n");
	}

效果

去掉最后一行的分割线,在循环内部加条件if。

for (i = 0; i < row; i++)
	{
		printf(" %c | %c | %c \n",board[i][0], board[i][1], board[i][2]);//char类型的用%c进行打印
		
		if (i < row - 1)
		printf("---|---|---\n");
		
	}

效果

 #列灵活

列固定死了,让列变得灵活起来。

观整个棋盘可以看成是一行数据,一行分割线,单看一行又可以看成数据分割线,数据分割线。

上一个打印数据和打印分割线的代码均要第二步分割。

    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("\n");
		
		//打印分割线(整体的第二行),细分处理
		if (i < row - 1)//分割线在整体中本来就是if语句控制的,所以这个循环要在if语句中
		{
			int j = 0;
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)
					printf("|");//同上最后一行不打印
			}
			printf("\n");
		}
			
	}

 打印7*7的效果

·下棋

*玩家下棋

#PlayerMove函数

向数组中换数据,仍然需要将数组的行列传参到函数中

void PlayerMove(char board[ROW][COL], int row, int col);

具体函数实现,简单框架

        printf("请输入下棋的坐标(中间使用空格)>:\n");
		scanf("%d %d", &x, &y);

		//坐标合法
		if (x >= 1 && x <= row && y >= 1 && y <= col)//玩家不是程序员,从1开始
		{

		}

		//坐标非法
		else
		{
			printf("坐标非法,重新输入>:\n");
		}

如果坐标非法,则重新输入,循环。

while (1)
	{
		printf("请输入下棋的坐标(中间使用空格)>:\n");
		scanf("%d %d", &x, &y);

		//坐标合法
		if (x >= 1 && x <= row && y >= 1 && y <= col)//玩家不是程序员,从1开始
		{

		}

		//坐标非法
		else
		{
			printf("坐标非法,重新输入>:\n");
		}
	}

当玩家坐标合法时,且不被占用的情况下才可下棋,即元素是空格的时候。 

while (1)
	{
		printf("请输入下棋的坐标(中间使用空格)>:\n");
		scanf("%d %d", &x, &y);

		//坐标合法
		if (x >= 1 && x <= row && y >= 1 && y <= col)//玩家不是程序员,从1开始
		{
			if (board[x - 1][y - 1] == ' ')
			{
				board[x - 1][y - 1] = '*';
				break;
			}
			else
			{
				printf("坐标被占用,不能落子,请重新输入坐标>:\n");//重新落子进入循环没有break
			}
		}

		//坐标非法
		else
		{
			printf("坐标非法,重新输入>:\n");
		}
	}

下棋效果调用DisplayBoard函数展示,可添加换行增加可读性

    InitBoard(board, ROW, COL);//利用函数来初始化数组,将行和列都传参过去
	DisplayBoard(board, ROW, COL);
	printf("\n");
	PlayerMove(board, ROW, COL);
	printf("\n");
	DisplayBoard(board, ROW, COL);//下棋之后再次调用,展示下棋结果
	printf("\n");

#检验报错

玩家落子超过范围,落子被占用的情况

while循环,玩家一直下

while(1)
	{ PlayerMove(board, ROW, COL);
	printf("\n");
	DisplayBoard(board, ROW, COL);//下棋之后再次调用,展示下棋结果
	printf("\n");}

 *电脑下棋

 #ComputerMove函数

电脑随机下棋,与玩家下棋情况相似。

void ComputerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;//电脑不似玩家,坐标可以控制为0~row-1
	int y = 0;//0~col-1

	printf("电脑下棋>:\n");

}
#rand函数,srand函数,time函数

rand函数来生成随机数,使用rand函数需要调用srand函数。

srand函数需要包含<stdlib.h>头文件,time函数需要包含<time.h>头文件。

头文件的包含也可以嵌套。

void ComputerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;

	printf("电脑下棋>:\n");

	x = rand() % row;
	y = rand() % col;//%上最大值,控制范围

}





int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	
#检验报错

电脑落子范围确定,只会出现落子被占用的情况。如果落子被占用只需循环重新生成随机数几个。

while (1)
	{
		x = rand() % row;
		y = rand() % col;//%上最大值,控制范围
		
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}

 ·判断输赢

#Iswin函数

玩家赢,电脑赢,平局,游戏继续。

玩家赢返回“*”,电脑赢返回“#”,平局返回“Q”,游戏继续返回“C”。

返回不同的值代表不同的状态。

ret = Iswin(board, ROW, COL);
		if (ret != 'C')
			break;
	}

	if (ret == '*')
		printf("你赢啦!\n");

	else if (ret == '#')
		printf("你输了。\n");

	else
		print("平局。\n");
}

判断行

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[2][i] == board[1][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[1][1];//前后呼应,返回什么谁就赢了
		}
	
		if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')
		{
			return board[1][1];//前后呼应,返回什么谁就赢了
		}

 ·判断平局

没人赢且棋盘满了

#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;






		if (Isfull(board, row, col) == 1)
		{
			return 'Q';
		}

		return 'C';

 成了

评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值