三子棋代码教学

三子棋代码教学

三子棋算是比较早的益智互动游戏。那么我们怎么用C语言来解决呢?
在这里插入图片描述
这是利用代码之后的体现,我们在打代码之前,需要知道我们在游戏开始之前的界面长什么模样。那么我们在开始之前会有菜单函数来体现。
菜单函数

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

这是个比较简单的函数体现。那么我们在结束之后,我们需要一个变量来获取使用者的一个选择。同时我们也需要利用这个变量来开始之后的决策。
首先,我们要判断用户的输入会有哪些情况。
第一种情况就是输入1,
第二种情况就是输入2,
第三种情况是为了防止程序出现bug而想到的,那就是,用户的输入不是1或者2.
这里我们很容易看出来,这是单一输入多元输出,我建议是使用switch()语句。同时我们需要把这个语句放到主函数当中。
代码如下

int main()
{
	int m = 0;
	srand((unsigned int)time(NULL));  //用于生成随机数,用于电脑下棋。我们先不管这个。
	do
	{
		menu();
		printf("请输入你的选择\n");
		scanf("%d" , &m);
		switch(m)
		{
			case 1:
				game();  //用于游戏
				break;
			case 0:
				printf("退出游戏\n");
				break;
			default:
				printf("输入错误字符\n");
				break;
		}
	}while(m);
	return 0;
}

这个代码有这么几个重点需要知道,其一:我们运用的是do循环语句。这个语句的好处就是十分贴切switch语句。变量m既控制了用户输入,又控制着循环的开始和结束。case 1 , case 2 和default控制着我上面说的三种形式。那么到现在为止,我们很轻松的完成了这个函数的表面工作。
之后我们需要完成细节。
第一点,我们要学会制造棋盘。
棋盘代码


char board[row][col] = {0};  //定义棋盘的数组,因为三子棋是二维的,所以创建二维数组。

void dyboard(char board[row][col] ,int x,int y) //用于打印棋盘的函数
{
	int i = 0;   //控制行
	int j = 0;  //控制列
	for(i = 0;i < x;i++)     //第一个循环,是把三子棋的一行看作一个单元,然后进行复制性质的打印。
	{
		for(j = 0 ; j<y;j++)           //第二个循环,是把三子棋当中的一个个空格当作一个单元格进行复制打印。
		{
			printf(" %c " , board[i][j]);  //这边的打印同时也为了输入。可以让用户把想输入的位置输入正确的符号。
			if(j<y-1)
			{
				printf("|");     //这边一个判断是为了防止最后一个单元格也打印这个符号,我们可以清楚的发现最后一个单元格没有这个符号。
			}
		}
		printf("\n");   //这边是打印好之后的回车,
		for(j = 0;j <y;j++)
		{
			printf("---");
			if(j<y-1)
			{
				printf("|");    //同上所述
			}
		}
		printf("\n");
	}
}

在打印时我们发现,我们利用的是分割的思想,把一个大的工程,分割成一个个小的工程,然后进行复制打印。
那么棋盘打印好周,我们为了能玩好一遍之后还能再玩一遍,而不破坏棋盘时,我们可以初始化我们的棋盘。
初始化棋盘函数

void cshboard(char board[row][col] ,int x,int y)   //初始化棋盘函数 
{
	int i = 0;    //i和j控制着行和列。
	int j = 0;
	for(i = 0;i<x;i++)
	{
		for(j = 0 ; j < y ; j++)
		{
			board[i][j] = ' ';   //让board数组当中的每一个存储都变成空格
		}
	}
}

初始化棋盘之后我们就可以开始编写玩家该怎么进行游戏了。

玩家代码

void playermove(char board[row][col],int x,int y)  //玩家代码
{
	int ROW = 0;
	int COL = 0;
	while(1)
	{
		printf("玩家走\n请输入坐标。\n");  //玩家输入要下棋的位置
		scanf("%d %d" , &ROW , &COL);
		if(ROW>=1 && ROW<=x && COL>= 1 && COL<= y) //判断玩家下子的位置是否合法
		{
			if(board[ROW-1][COL-1] == ' ')  //判断玩家下子的位置,之前是不是有过棋子。
			{
				board[ROW-1][COL-1] = '*';  //如果下子的位置合法,就下。
				break;
			}
			else
			{
				printf("该坐标被占用\n");
			}
		}
		else
		{
			printf("输入错误坐标。\n");
		}
	}
}

在玩家下子的时候我们有很多的判断,是为了防止代码出现bug。当玩家输入之后,我们就轮到了,电脑下子。
电脑下子的程序

void computermove(char board[row][col],int x,int y)  //电脑下子的代码
{
	int ROW = 0;
	int COL = 0;
	printf("电脑走\n");
	while(1)  //利用循环帮助,电脑下子。
	{
		ROW = rand()%row;    //为了实现电脑下子的位置都是合法的。rand()函数可以利用之前用到的srand()和time()函数来帮忙实现真正的随机。
		COL = rand()%col;
		if(board[ROW][COL] == ' ')  //判断电脑下子的位置是不是已经有棋子了。
		{
			board[ROW][COL] = '#';
			break;
		}
	}
}

在电脑下子的代码里我们也需要保证下子的合法性。
当玩家和电脑都下子之后,我们需要一个函数来判断输赢。
判断输赢的函数

char pdsy(char board[row][col],int x ,int y)
{
	int i = 0;    //i和j控制着行列
	int j = 0;
	for(i = 0;i<x;i++)
	{
		if(board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')  //判断是不是有行上相邻的三个棋子是相同的,如果是相同的就输出其中一个所代表的是什么图形,那么这个图形就获胜。
		{
			return board[i][0];
		}
	}
	for(j = 0;j<y;j++)
	{
		if(board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[0][j] != ' ')  //判断列上相邻的是不是一样的,如果一样,就输出其中一个。那个输出的就是获胜的。
		{
			return board[0][j];
		}
	}
	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];
	}
	if(1 == full(board,row,col))   //当以上几种都没有发生的时候,我们就只剩下两种情况,一种是还没下完,一种是打成平手。所以我们利用自定义函数full()来判断这个函数。
	{
		return 'p';  //当棋盘都满时,我们可以输出平
	}
	else
	{
		return 'c'; //当棋盘没满的时候,我们就输出继续。让电脑和玩家继续下。
	}
}



int full(char board[row][col],int x,int y)  //判断棋盘是不是下满了。
{
	int i = 0;
	int j = 0;
	for(i = 0;i < x;i++)
	{
		for(j = 0;j < y;j++)
		{
			if(board[i][j] == ' ') //判断是不是有空格。如果有就是没下满
			{
				return 0;
			}
		}
	}
	return 1;

当我们完成所有的一个个小部件之后我们就要组合一下。
组合代码

void game()
{
	char ret;    //用于存储判断输赢函数的输出结果
	char board[row][col] = {0};  //定义数组
	cshboard(board,row,col);  //初始化棋盘
	dyboard(board,row,col);   //打印棋盘函数
	while(1)   //利用循环,将游戏开始。while(1)。是为了保证循环一直继续,直到遇到break;
	{
		playermove(board,row,col);  //首先玩家先下棋
		dyboard(board,row,col);   //下好棋子之后我们要打印一遍棋盘,看棋子下在了哪里。
		ret = pdsy(board,row,col);   //判断我们下的子之后,会不会赢。
		if(ret != 'c')    //如果输出的不是C时,就结束循环,说明有结果了。
		{
			break;
		}
		computermove(board,row,col);   //电脑下棋,同上。
		dyboard(board,row,col);
		ret = pdsy(board,row,col);
		if(ret != 'c')
		{
			break;
		}
	}
	if(ret == '#')   //判断是谁获得胜利。
	{
		printf("电脑赢了!\n");
	}
	else if(ret == '*')
	{
		printf("玩家赢了!\n");
	}
	else if(ret == 'p')
	{
		printf("平局\n");
	}
}

综上所述,所有函数就结合在了一起。三子棋也就出来。
接下来是完整代码
完整代码

//game.h 文件里的函数

#include<stdio.h>
#define row 3    //这是宏定义
#define col 3
void cshboard(char board[row][col] ,int x,int y);  //我们看到所有函数的定义之后都有board数组和x , y。因为我们所有的函数都是围绕着棋盘来进行的。x和y分别代表行和列。
void dyboard(char board[row][col] ,int x,int y);
void playermove(char board[row][col],int x,int y);
void computermove(char board[row][col],int x,int y);
char pdsy(char board[row][col],int x,int y);
int full(char board[row][col],int x,int y);



//game.c文件里的函数,这里有各种小函数。

#include"game.h"
#include<time.h>  //time函数所要用到的头文件
#include<stdlib.h>  //srand函数所要用到的有文件
void cshboard(char board[row][col] ,int x,int y) 
{
	int i = 0;
	int j = 0;
	for(i = 0;i<x;i++)
	{
		for(j = 0 ; j < y ; j++)
		{
			board[i][j] = ' ';
		}
	}
}
void dyboard(char board[row][col] ,int x,int y)
{
	int i = 0;
	int j = 0;
	for(i = 0;i < x;i++)
	{
		for(j = 0 ; j<y;j++)
		{
			printf(" %c " , board[i][j]);
			if(j<y-1)
			{
				printf("|");
			}
		}
		printf("\n");
		for(j = 0;j <y;j++)
		{
			printf("---");
			if(j<y-1)
			{
				printf("|");
			}
		}
		printf("\n");
	}
}
void playermove(char board[row][col],int x,int y)
{
	int ROW = 0;
	int COL = 0;
	while(1)
	{
		printf("玩家走\n请输入坐标。\n");
		scanf("%d %d" , &ROW , &COL);
		if(ROW>=1 && ROW<=x && COL>= 1 && COL<= y)
		{
			if(board[ROW-1][COL-1] == ' ')
			{
				board[ROW-1][COL-1] = '*';
				break;
			}
			else
			{
				printf("该坐标被占用\n");
			}
		}
		else
		{
			printf("输入错误坐标。\n");
		}
	}
}
void computermove(char board[row][col],int x,int y)
{
	int ROW = 0;
	int COL = 0;
	printf("电脑走\n");
	while(1)
	{
		ROW = rand()%row;
		COL = rand()%col;
		if(board[ROW][COL] == ' ')
		{
			board[ROW][COL] = '#';
			break;
		}
	}
}
char pdsy(char board[row][col],int x ,int y)
{
	int i = 0;
	int j = 0;
	for(i = 0;i<x;i++)
	{
		if(board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
		{
			return board[i][0];
		}
	}
	for(j = 0;j<y;j++)
	{
		if(board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[0][j] != ' ')
		{
			return board[0][j];
		}
	}
	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];
	}
	if(1 == full(board,row,col))
	{
		return 'p';
	}
	else
	{
		return 'c';
	}
}
int full(char board[row][col],int x,int y)
{
	int i = 0;
	int j = 0;
	for(i = 0;i < x;i++)
	{
		for(j = 0;j < y;j++)
		{
			if(board[i][j] == ' ')
			{
				return 0;
			}
		}
	}
	return 1;
}




//三子棋实现.c的文件的代码,组合,game.c文件里面的所有函数。

#include"game.h"
#include"game.c" 
void menu()
{
	printf("**********************\n");
	printf("*** 1:play  0:exit ***\n");
	printf("**********************\n");
}
void game()
{
	char ret;
	char board[row][col] = {0};
	cshboard(board,row,col);
	dyboard(board,row,col);
	while(1)
	{
		playermove(board,row,col);
		dyboard(board,row,col);
		ret = pdsy(board,row,col);
		if(ret != 'c')
		{
			break;
		}
		computermove(board,row,col);
		dyboard(board,row,col);
		ret = pdsy(board,row,col);
		if(ret != 'c')
		{
			break;
		}
	}
	if(ret == '#')
	{
		printf("电脑赢了!\n");
	}
	else if(ret == '*')
	{
		printf("玩家赢了!\n");
	}
	else if(ret == 'p')
	{
		printf("平局\n");
	}
}
int main()
{
	int m = 0;
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		printf("请输入你的选择\n");
		scanf("%d" , &m);
		switch(m)
		{
			case 1:
				game();
				break;
			case 0:
				printf("退出游戏\n");
				break;
			default:
				printf("输入错误字符\n");
				break;
		}
	}while(m);
	return 0;
}

以上就能发现,一个大的工程就是把大事化小,小事化了。三子棋实现的过程十分简单,至少没有什么大的问题,那么从此可以发现,人生何不是如此,我们四处奔波,遇到的大大小小的事情,最后都汇在一起成为人。
谢谢大家的阅读,我是Jack Chao。我爱代码,爱人生。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值