欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

五子棋

程序员文章站 2022-06-14 11:00:36
...

直接贴代码,复制粘贴,Linux下编译运行。。。

 /****************************************
 *********** 对战版五子棋 ***************
 **************************************** 
 ************* BLUSELI ******************
 ****************************************
 ************ 2019-7-29 *****************
 ****************************************/

#include <stdio.h>
#include <stdlib.h>

#define ROW		15  //棋盘宽度
#define COL		15  //棋盘长度

#define BAK		0   //背景 打印*
#define PL1		1   //玩家1 打印#
#define PL2		2   //玩家2 打印@
#define POS1	3   //光标1 实现交替打印0
#define POS2	4   //光标2 实现交替打印O

#define POS_X	3   //光标默认位置X坐标
#define POS_Y	7   //光标默认位置y坐标

#define STEP	1   //移动步长

int temp[ROW][COL]; //棋盘
int pos_x, pos_y;   //当前光标位置
int player;			//角色

//打印棋盘,棋子,光标
void printbackplane();
//开始
void begin();
//移动光标
void move();
//下棋
void play();
//判别胜利
int victory();
//重新开始
void restart();
//自定义延迟函数
void delay();

int main()
{
	begin();	
	play();

	return 0;
}

void delay()
{
	int i=65535;
	while(i--);
}

void printbackplane()
{
	system("clear");
	printf("--------------------------------------------\n");
	printf("----------- 五子棋对战版 BluseLi------------\n");
	printf("--- wsad - 上下左右 - o - 落子 - q - 退出 --\n");
	if(player==PL1)
		printf("------------- 等待玩家PL2落子 --------------\n");
	else	
		printf("------------- 等待玩家PL1落子 --------------\n");
	printf("--------------------------------------------\n");
	for(int i=0; i<ROW; i++)
	{
		for(int j=0; j<COL; j++)
		{
			switch(temp[i][j])
			{
			case BAK:
				printf(" * ");
				break;
			case PL1:
				printf(" # ");
				break;
			case PL2:
				printf(" @ ");
				break;
			case POS1:
				printf(" 0 ");
				temp[i][j]=0;
				break;
			case POS2:
				printf(" O ");
				break;
			default:

				break;
			}		  
		}
		printf("\n");
	}
}

void begin()
{
	pos_x=POS_X, pos_y=POS_Y;
	player=PL2;	
	for(int i=0; i<ROW; i++)
	{
		for(int j=0; j<COL; j++)
		{
			temp[i][j]=BAK;
		}	  
	}
	temp[pos_x][pos_y]=POS1;
}

void move()
{
	//执行system中的内容,
	//当按下方向键 w s a d
	//后不需要按下回车
	system("stty raw echo");
	char c = getchar();
	switch(c)
	{
	case 'w':
		if(pos_x-STEP>-1)
			pos_x-=STEP;
		break;
	case 's':
		if(pos_x+STEP<COL)
			pos_x+=STEP;
		break;
	case 'a':
		if(pos_y-STEP>-1)
			pos_y-=STEP;
		break;
	case 'd':
		if(pos_y+STEP<COL)
			pos_y+=STEP;
		break;
	case 'o':
		if(player==PL1)
			player=PL2;
		else
			player=PL1;
		break;
	case 'q':
		//避免用户退出程序后,终端排版乱码
		//当执行本程序后退出,中文任然会乱码,重新打开一个终端即可恢复
		//这里给差评,哈哈,因为我也不知道这么处理
		system("stty cooked echo");
		exit(0);
		break;
	default:
		break;
	}
	system("stty cooked echo");
}

void play()
{
	static int state=PL2;
	while(1)
	{
		printbackplane();
		move();
		if(player!=state)
		{
			if(player==PL1)
			{
				if(temp[pos_x][pos_y]!=PL2)
				{
					state=PL1;
					temp[pos_x][pos_y]=PL1;
					if(victory())
					{
						restart();
					}
				}
				else
				{
					player=state;
				}		  
			}
			if(player==PL2)
			{
				if(temp[pos_x][pos_y]!=PL1)
				{	
					state=PL2;
					temp[pos_x][pos_y]=PL2;
					if(victory())
					{
						restart();
					}
				}
				else
				{
					player=state;
				}		  
			}
		}
		else
		{
			if(temp[pos_x][pos_y]==BAK)
			  temp[pos_x][pos_y]=POS1;	
		}
				
		delay();
	}
}

int victory()
{ 
	//这里代码看着比较多,其实很简单
	//就是挨个扫描棋盘,发现有5个旗子连在一起就判定为游戏结束
	int i = 0,j = 0;
	int flag = 0;
	for(i=2;i<ROW-2;i++)
	{
		for(j=2;j<COL-2;j++)
		{
			//判断左斜是否有五子相连
			if(temp[i][j]!=0&&temp[i-2][j-2]==temp[i][j]&&temp[i-1][j-1]==temp[i][j]&&temp[i+1][j+1]==temp[i][j]&&temp[i+2][j+2]==temp[i][j])
			{
				flag=1;
				break;
			}
			//判断右对角是否有五子相连
			if(temp[i][j]!=0&&temp[i+2][j-2]==temp[i][j]&&temp[i+1][j-1]==temp[i][j]&&temp[i-1][j+1]==temp[i][j]&&temp[i-2][j+2]==temp[i][j])
			{
				flag=1;
				break;
			}
		
		}
	}
	if(flag==0)
	{
		for(i=0;i<ROW;i++)
		{
			for(j=2;j<COL-2;j++)
			{
				//上面两种情况都不成立,则判断是否有横向五子相连
				if(temp[i][j]!=0&&temp[i][j-2]==temp[i][j]&&temp[i][j-1]==temp[i][j]&&temp[i][j+1]==temp[i][j]&&temp[i][j+2]==temp[i][j])
				{
					flag=1;
					break;
				}
			}
		}
	}
	if(flag==0)
	{
		//判断纵向五子相连
		for(i=2;i<ROW-2;i++)
		{
			for(j=0;j<COL;j++)
			{
				if(temp[i][j]!=0&&temp[i+2][j]==temp[i][j]&&temp[i+1][j]==temp[i][j]&&temp[i-1][j]==temp[i][j]&&temp[i-2][j]==temp[i][j])
				{
					flag=1;
					break;
				}
	
			}
		}
	}
	return flag;
}

void restart()
{
	system("clear");
	printf("--------------------------------------------\n");
	printf("--------------------------------------------\n");
	printf("----------- 五子棋对战版 BluseLi------------\n");
	printf("--------------------------------------------\n");
	printf("--------------------------------------------\n");
	if(player==PL1)
		printf("-------------- 玩家PL1胜利 ---------------\n");
	else	
		printf("-------------- 玩家PL2胜利 ---------------\n");
	printf("--------------------------------------------\n");
	printf("--------------------------------------------\n");
	printf("-------------- 是否重新开始 ----------------\n");
	printf("--------------------------------------------\n");
	printf("-------------- Y 是 -- N 否 ----------------\n");
	printf("--------------------------------------------\n");
	printf("--------------------------------------------\n");
	char c=getchar();
	if(c=='Y')
	{
		begin();
	}
	else
	{
		exit(0);
	}
}

已经落子的地方,光标移动过去不改变,以及对输入方向键后不需要按回车进行处理后会出现编码问题,还有光标闪烁,这三个地方等空了再改改。