网络版五子棋

一、前言

五子棋是是一种两人对弈的纯策略型棋类游戏,通常双方分别使用黑白两色的棋子,下在棋盘直线与横线的交叉点上,先形成5子连线者获胜,它容易上手,老少皆宜,而且趣味横生,一起来看一下如何用C语言实现五子棋的对弈。

二、五子棋模块

(1)初始化:把每一个点置为 +

void Init(char map[ROW][COL])
{
	memset(map, '+', ROW*COL*sizeof(char));
	FILE* fp = fopen("./test.c", "a+");
	if (fp == NULL)
	{
		printf("fopen error\n");
	}
	else
	{
		fputs("Test1: game init is OK!", fp);
	}
}

(2)打印

void Print(char map[ROW][COL])
{
	int i = 0, j = 0, k = 0;
	printf("    Y--------------------------->\n");
	printf("    ");
	for (k = 0; k < COL; k++)
	{
		if (k >= 0 && k <= 8)
			printf("%d ", k + 1);
		else
			printf("%d", k + 1);
	}
	putchar('\n');
	for (i = 0; i < ROW; i++)
	{
		printf("X");
		if (i >= 0 && i <= 8)
			printf("0%d ", i + 1);
		else
			printf("%d ", i + 1);
		for (j = 0; j < ROW; j++)
		{
			putchar(map[i][j]);
			if (j<(ROW - 1))
				putchar('-');
		}
		putchar('\n');
	}
}

(3)玩家走棋

int Play(char map[ROW][COL], wuziqi *game)
{
	if (NULL == game)
	{
		return -1;
	}
	int x, y;
	int res;
	printf("输入x, y:");
	scanf("%d %d", &x, &y);
	if (x<0 || y<0 || x>COL || y>ROW)
	{
		printf("输入错误,请重新输入\n");
		while ((getchar()) != '\n');
		res = Play(map, game);
		if (res == 1)
			return 1;
	}
	x--;
	y--;
	if (map[x][y] == '+')
	{
		map[x][y] = BLACK_FLAG;
		game->row = x;
		game->col = y;
	}
	else
	{
		printf("输入错误,请重新输入\n");
		while ((getchar()) != '\n');
		Play(map, game);
		if (res == 1)
			return 1;
	}
	return 1;
}

(4)电脑走棋:电脑走棋主要分为以下几个模块

a. 横

int Row(char map[ROW][COL], int row, int col, char whoFlag)
{
	int spaceNum = 0;//空白数
	int count = 1;//几连,包含当前要下的子
	int leftHad = 0;//左边是否有同子
	int x = row;
	int y = col;
	int liveLeft = 0;
	int liveRight = 0;
	if (map[row][col] != '+')
	{
		return 0;
	}
	while (y>0 && (map[x][y - 1] == '+' || map[x][y - 1] == whoFlag))
	{
		if (map[x][y - 1] == '+' && spaceNum < 1)
		{
			//第一个空白
			if (map[x][y - 2] != whoFlag)
			{
				liveLeft = 1;
				break;
			}
			spaceNum++;
			y--;
		}
		else if (map[x][y - 1] == whoFlag)
		{
			leftHad = 1;
			y--;
			count++;
		}
		else
		{
			//第2个空白
			liveLeft = 1;
			break;
		}
	}
	//如果左边没有同色子,设置空白数为0
	if (!leftHad)
	{
		spaceNum = 0;
	}
	y = col;
	while (y<14 && (map[x][y + 1] == '+' || map[x][y + 1] == whoFlag))
	{
		if (map[x][y + 1] == '+' && spaceNum < 1)
		{
			//第一个空白
			if (map[x][y + 2] != whoFlag)
			{
				liveRight = 1;
				break;
			}
			spaceNum++;
			y++;
		}
		else if (map[x][y + 1] == '+' && spaceNum > 0)
		{
			//第2个空白
			liveRight = 1;
			break;
		}
		else
		{
			y++;
			count++;
		}
	}
	return Result(liveLeft, liveRight, count, spaceNum, whoFlag);
}

b. 竖

int Col(char map[ROW][COL], int row, int col, char whoFlag)
{
	int spaceNum = 0;//空白数
	int count = 1;//几连,包含当前要下的子
	int topHad = 0;//上边是否有同子
	int x = row;
	int y = col;
	int liveLeft = 0;
	int liveRight = 0;
	if (map[row][col] != '+')
	{
		return 0;
	}
	while (x > 0 && (map[x - 1][y] == '+' || map[x - 1][y] == whoFlag))
	{
		if (map[x - 1][y] == '+' && spaceNum < 1)
		{
			//第一个空白 
			if (map[x - 2][y] != whoFlag)
			{
				liveLeft = 1;
				break;
			}
			spaceNum++;
			x--;
		}
		else if (map[x - 1][y] == whoFlag)
		{
			topHad = 1;
			x--;
			count++;
		}
		else
		{
			//第2个空白 
			liveLeft = 1;
			break;
		}
	}
	//如果左边没有同色子,设置空白数为0
	if (!topHad)
	{
		spaceNum = 0;
	}
	x = row;
	while (x < 14 && (map[x + 1][y] == '+' || map[x + 1][y] == whoFlag))
	{
		if (map[x + 1][y] == '+' && spaceNum < 1)
		{
			//第一个空白
			if (map[x + 2][y] != whoFlag)
			{
				liveRight = 1;
				break;
			}
			spaceNum++;
			x++;
		}
		else if (map[x + 1][y] == '+' && spaceNum > 0)
		{
			//第2个空白
			liveRight = 1;
			break;
		}
		else
		{
			x++;
			count++;
		}
	}
	return Result(liveLeft, liveRight, count, spaceNum, whoFlag);
}

c. 左斜

int zuoxie(char map[ROW][COL], int row, int col, char whoFlag)
{
	int spaceNum = 0;//空白数
	int count = 1;//几连,包含当前要下的子
	int topHad = 0;//上边是否有同子
	int x = row;
	int y = col;
	int liveLeft = 0;
	int liveRight = 0;
	if (map[row][col] != '+')
	{
		return 0;
	}
	//向下
	while (x < 14 && y>0 && (map[x + 1][y - 1] == '+' || map[x + 1][y - 1] == whoFlag))
	{
		if (map[x + 1][y - 1] == '+' && spaceNum < 1)
		{
			//第一个空白
			if (map[x + 2][y - 2] != whoFlag)
			{
				liveLeft = 1;
				break;
			}
			spaceNum++;
			x++;
			y--;
		}
		else if (map[x + 1][y - 1] == whoFlag)
		{
			topHad = 1;
			x++;
			y--;
			count++;
		}
		else
		{
			//第2个空白 
			liveLeft = 1;
			break;
		}
	}
	//如果上边没有同色子,设置空白数为0 
	if (!topHad)
	{
		spaceNum = 0;
	}
	x = row;
	y = col;
	//向上 
	while (x > 0 && y < 14 && (map[x - 1][y + 1] == '+' || map[x - 1][y + 1] == whoFlag))
	{
		if (map[x - 1][y + 1] == '+' && spaceNum < 1)
		{
			//第一个空白
			if (map[x - 2][y + 2] != whoFlag)
			{
				liveRight = 1;
				break;
			}
			spaceNum++;
			x--;
			y++;
		}
		else if (map[x - 1][y + 1] == '+' && spaceNum > 0)
		{
			//第2个空白
			liveRight = 1;
			break;
		}
		else
		{
			x--;
			y++;
			count++;
		}
	}
	return Result(liveLeft, liveRight, count, spaceNum, whoFlag);
}

d. 右斜

int youxie(char map[ROW][COL], int row, int col, char whoFlag)
{
	int spaceNum = 0;//空白数 
	int count = 1;//几连,包含当前要下的子 
	int topHad = 0;//上边是否有同子 
	int x = row;
	int y = col;
	int liveLeft = 0;
	int liveRight = 0;
	if (map[row][col] != '+')
	{
		return 0;
	}
	//向上
	while (x > 0 && y > 0 && (map[x - 1][y - 1] == '+' || map[x - 1][y - 1] == whoFlag))
	{
		if (map[x - 1][y - 1] == '+' && spaceNum < 1)
		{
			//第一个空白
			if (map[x - 2][y - 2] != whoFlag)
			{
				liveLeft = 1;
				break;
			}
			spaceNum++;
			x--;
			y--;
		}
		else if (map[x - 1][y - 1] == whoFlag)
		{
			topHad = 1;
			x--;
			y--;
			count++;
		}
		else
		{
			//第2个空白
			liveLeft = 1;
			break;
		}
	}
	//如果上边没有同色子,设置空白数为0
	if (!topHad)
	{
		spaceNum = 0;
	}
	x = row;
	y = col;
	//向下
	while (x < 14 && y < 14 && (map[x + 1][y + 1] == '+' || map[x + 1][y + 1] == whoFlag))
	{
		if (map[x + 1][y + 1] == '+' && spaceNum < 1)
		{
			//第一个空白
			if (map[x + 2][y + 2] != whoFlag)
			{
				liveRight = 1;
				break;
			}
			spaceNum++;
			x++;
			y++;
		}
		else if (map[x + 1][y + 1] == '+' && spaceNum > 0)
		{
			//第2个空白
			liveRight = 1;
			break;
		}
		else
		{
			x++;
			y++;
			count++;
		}
	}
	return Result(liveLeft, liveRight, count, spaceNum, whoFlag);
}

e. 结果

int Result(int left, int right, int count, int k, char num)
{
	if (count == 1)
	{
		return 1;
	}
	else if (count == 2)
	{
		if (left && right)
		{
			//左右两边都是空的
			if (k == 0)
			{
				//电脑60
				return num == WHITE_FLAG ? 60 : 50;
			}
			else
			{
				return num == WHITE_FLAG ? 40 : 35;
			}
		}
		else if (!left && !right)
		{
			return 1;
		}
		else
		{
			return 10;
		}
	}
	else if (count == 3)
	{
		if (left && right)
		{
			//左右两边都是空的
			if (k == 0)
			{
				//电脑950
				return num == WHITE_FLAG ? 950 : 700;
			}
			else
			{
				return num == WHITE_FLAG ? 900 : 650;
			}
		}
		else if (!left && !right)
		{
			return 1;
		}
		else
		{
			return 100;
		}
	}
	else if (count == 4)
	{
		if (left && right)
		{
			//左右两边都是空的
			if (k == 0)
			{
				return num == WHITE_FLAG ? 6000 : 3500;
			}
			else
			{
				return num == WHITE_FLAG ? 5000 : 3000;
			}
		}
		else if (!left && !right)
		{
			return 1;
		}
		else
		{
			if (k == 0)
			{
				return num == WHITE_FLAG ? 4000 : 800;
			}
			else{
				return num == WHITE_FLAG ? 3600 : 750;
			}
		}
	}
	else
	{
		if (k == 0)
		{
			return num == WHITE_FLAG ? 20000 : 15000;
		}
		else
		{
			return num == WHITE_FLAG ? 10000 : 3300;
		}
	}
}

f. 计算分数

void Score(char map[ROW][COL])
{
	int n = 0;
	int m = 0;
	for (n = 0; n < 15; n++)
	{
		for (m = 0; m < 15; m++)
		{
			ComputerScore[n][m] = Row(map, n, m, WHITE_FLAG) + Col(map, n, m, WHITE_FLAG) + zuoxie(map, n, m, WHITE_FLAG) + youxie(map, n, m, WHITE_FLAG);
			PlayScore[n][m] = Row(map, n, m, BLACK_FLAG) + Col(map, n, m, BLACK_FLAG) + zuoxie(map, n, m, BLACK_FLAG) + youxie(map, n, m, BLACK_FLAG);
		}
	}
}

g. 电脑走棋

void ComputerPlay(char map[ROW][COL], wuziqi *game)
{
	if (NULL == game)
	{
		return;
	}
	Score(map);

	int count = 0;
	int row = 0;
	int col = 0;
	int i = 0;
	int j = 0;
	for (i = 0; i < 15; i++)
	{
		for (j = 0; j < 15; j++)
		{
			if (ComputerScore[i][j] > count)
			{
				count = ComputerScore[i][j];
				row = i;
				col = j;
			}
			if (PlayScore[i][j] > count)
			{
				count = PlayScore[i][j];
				row = i;
				col = j;
			}
		}
	}
	if (map[row][col] == '+')
	{
		map[row][col] = WHITE_FLAG;
		game->row = row;
		game->col = col;
	}
}

(5)判断输赢

int IsWin(char map[ROW][COL], char ch)
{
	char m = ch;
	int i, j;
	for (i = 0; i < COL; i++)
	{
		for (j = 0; j < ROW; j++)
		{
			if (map[i][j] == m)
			{
				if ((i + 4) < COL)
				{
					if (map[i + 1][j] == m && map[i + 2][j] == m && map[i + 3][j] == m && map[i + 4][j] == m)
						return 1;
				}
				if ((j + 4) < ROW)
				{
					if (map[i][j + 1] == m && map[i][j + 2] == m && map[i][j + 3] == m && map[i][j + 4] == m)
						return 1;
				}
				if ((i + 4) < COL && (j + 4) < ROW)
				{
					if (map[i + 1][j + 1] == m && map[i + 2][j + 2] == m && map[i + 3][j + 3] == m && map[i + 4][j + 4] == m)
						return 1;
				}
				if ((i + 4) < COL && (j - 4) >= 0)
				{
					if (map[i + 1][j - 1] == m && map[i + 2][j - 2] == m && map[i + 3][j - 3] == m && map[i + 4][j - 4] == m)
						return 1;
				}
			}
		}
	}
	return 0;
}

三、服务端模块

#include "wu_game.c"

int main(int argc, char*argv[])
{
	if (argc != 3)
	{
		printf("Usage: ./server [ip] [port]\n");
		return 1;
	}
	int fd = socket(AF_INET, SOCK_STREAM, 0);
	if (fd < 0)
	{
		printf("socket error\n");
		return 2;
	}
	struct sockaddr_in local;
	local.sin_family = AF_INET;
	local.sin_addr.s_addr = inet_addr(argv[1]);
	local.sin_port = htons(atoi(argv[2]));
	int ret = bind(fd, (const struct sockaddr*)&local, sizeof(local));
	if (ret < 0)
	{
		printf("bind error\n");
		return 3;
	}
	ret = listen(fd, 5);
	if (ret < 0)
	{
		printf("listen error\n");
		return 4;
	}
	char map[ROW][COL];
	while (1)
	{
		struct sockaddr_in client;
		socklen_t len = sizeof(client);
		int client_sock = accept(fd, (struct sockaddr*)&client, &len);
		if (client_sock < 0)
		{
			continue;
		}
		ssize_t s;
		wuziqi game_server, game_client;
		Init(map);
		while (1)
		{
			s = read(client_sock, (void*)&game_client, sizeof(game_client));
			if (s == 0)
			{
				printf("client quit!\n");
				close(client_sock);
				break;
			}
			map[game_client.row][game_client.col] = BLACK_FLAG;
			Print(map);
			if (IsWin(map, BLACK_FLAG))
			{
				printf("BLACK(%c) is winer!!!\n", BLACK_FLAG);
				break;
			}

			ComputerPlay(map, &game_server);
			Print(map);
			write(client_sock, (void*)&game_server, sizeof(game_server));
			if (IsWin(map, WHITE_FLAG))
			{
				printf("WHITE(%c) is winer!!!\n", WHITE_FLAG);
				break;
			}
		}
	}
	close(fd);
}

四、客户端模块

#include "wu_game.c"

void Game(int sock)
{
	wuziqi game_client, game_server;
	char map[ROW][COL];
	Init(map);
	Print(map);
	ssize_t s;
	while (1)
	{
		Play(map, &game_client);
		Print(map);
		write(sock, (void*)&game_client, sizeof(game_client));
		if (IsWin(map, BLACK_FLAG))
		{
			printf("BLACK(%c) is winer!!!\n", BLACK_FLAG);
			break;
		}
		s = read(sock, (void*)&game_server, sizeof(game_server));
		map[game_server.row][game_server.col] = WHITE_FLAG;
		if (s == 0)
		{
			printf("server quit\n");
			return;
		}
		Print(map);
		if (IsWin(map, WHITE_FLAG))
		{
			printf("WHITE(%c) is winer!!!\n", WHITE_FLAG);
			break;
		}
	}
}

int main(int argc, char*argv[])
{
	if (argc != 3)
	{
		printf("Usage: ./server [ip][port]");
		return 1;
	}
	int fd = socket(AF_INET, SOCK_STREAM, 0);
	if (fd < 0)
	{
		printf("socket error\n");
		return 2;
	}
	struct sockaddr_in client;
	client.sin_family = AF_INET;
	client.sin_addr.s_addr = inet_addr(argv[1]);
	client.sin_port = htons(atoi(argv[2]));
	int ss = connect(fd, (const struct sockaddr*)&client, sizeof(client));
	if (ss < 0)
	{
		printf("connect error\n");
		return 3;
	}
	int num;
	while (1)
	{
		menu();
		printf("please select: ");
		scanf("%d", &num);
		if (num == 1)
		{
			Game(fd);
		}
		else if (num == 0)
		{
			break;
		}
	}
	close(fd);
}

完整代码:https://github.com/MonologueX/monologue_Linux/tree/master/game

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值