c语言之五子棋

拿一个例子来写写,看看自己的实力,实力之一学就会,一写就废系列。。。。。。看了别人写的三子棋,写了一遍,自己魔改了一下,写了一个双人对战的五子棋。

这是三子棋的代码逻辑:

代码分成三个文件,头文件game.h,存放函数声明和包含的库函数。源文件game.c存放游戏过程中调用的函数,test.c存放主函数即三子棋的运行逻辑;

头文件:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 3
#define COL 3
void initialize_board(char board[ROW][COL], int row, int col);

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

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

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

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

先是需要有三子棋的主菜单,接着就是三子棋游戏部分。首先初始化棋盘,用二维数组设计棋盘,数组中的每个元素其实就对应一个棋盘格,为了让玩家看到棋盘是空的,所以初始化数组就用空格,再就是通过打印分割线,设计棋盘线,这样就能看到棋盘是一格一格的了,设计好了棋盘就需要把整个棋盘打印出来,之后就是玩家下棋,判断输赢,打印棋盘,电脑下棋,判断输赢,打印棋盘,写成死循环,直到电脑和玩家有一方赢就退出循环,逻辑运行代码如下:

#include "game.h"
//三子棋的首菜单
void menu(void)
{
	printf("*****************************\n");
	printf("********1.开始游戏***********\n");
	printf("********0.退出游戏***********\n");
	printf("*****************************\n");
}

void game(void)
{
	char ret = 0;
	char board[ROW][COL] = {0};
	//初始化棋盘,不初始化棋盘,后面打印棋盘格,会对不齐
	initialize_board(board, ROW, COL);
	//打印棋盘格
	display_board(board, ROW, COL);
	//开始下棋
	while (1)
	{
		player_play(board, ROW, COL);
		//需要判断输赢
		ret = iswin(board, ROW, COL);
		if (ret != 'c')
			break;
		display_board(board, ROW, COL);
		computer_play(board, ROW, COL);
		//需要判断输赢
		ret = iswin(board, ROW, COL);
		if (ret != 'c')
			break;
		display_board(board, ROW, COL);
	}
	if (ret == '*')
		printf("玩家赢了\n");
	else if (ret == '#')
		printf("电脑赢了\n");
	else
		printf("平局\n");
	display_board(board, ROW, COL);
}


int main()
{
	srand((unsigned int)time(NULL));//设置随机数的生成起点
	
	int input = 0;
	do
	{
		menu();
		printf("请选择:");
		scanf("%d",&input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输入不对,请重新选择\n");
			break;
		}
	} while (input);
	return 0;
}

其中的每一个逻辑写成一个函数;其中电脑下棋函数是找棋盘上为空格的地方随机下棋,奈何水平有限,还不会算法,还在初学阶段,能实现随机下棋的这个函数都理解了好一会,rand函数其实也并不能随机,在程序的生命周期里,调用一次rand函数能生成一个与上一次不同的数,但是当程序生命周期结束,在新的一次程序生命周期中调用一次rand函数和上一次程序运行生成的数字是相同的,并没有产生随机数。

srand((unsigned int)time(NULL));//设置随机数的生成起点

rand能产生随机数是基于生成起点的时间来决定的,与srand函数配合使用,srand函数就是设置rand函数随机数的生成起点,电脑并不能想人脑一样凭空就能冒出一个想法,这里指人其实可以凭空想出一个数,这才是随机数,而电脑只能是寻求事件的规律,按照这个规律一丝不苟的执行,对于电脑来说,通过时间所记率的数字是永远不会重复的,记录的这个数字叫时间戳。每执行一次程序,时间必定不同,就会产生不同的时间戳,就能产生不同随机数的生成起点,最终产生伪随机数,我理解的叫伪随机数。time函数返回的类型是无符号整形,所以用(unsigned int)强制类型转换。time函数和指针有关,后面再深入研究一下;

等后期技术深入了再对电脑下棋进行调整一下,不说人工智能水平,至少做到能下赢人的水平。

#include "game.h"
//初始化棋盘
void initialize_board(char board[ROW][COL], int row, int col)
{

	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			board[i][j] = ' ';
		}
	}
}

//打印棋盘
void display_board(char board[ROW][COL], int row, int col)
{
	for (int i = 0; i < row; i++)//控制行
	{
		for (int j = 0; j < col; j++)//控制列
		{
			//打印数据
			printf(" %c ", board[i][j]);
			if (j < col - 1)
				printf("%c",'|');

		}
		printf("\n");
		//打印分割线
		if (i < row - 1)
		{
			for (int j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)
					printf("%c",'|');
			}
			printf("\n");
		}
	}
}

//玩家下棋
void player_play(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("玩家请下棋\n");
	printf("\n");
	while (1)
	{
		printf("请输入坐标:");
		scanf("%d %d", &x, &y);
		//坐标范围的判定
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			//判断棋盘上的坐标是否已经被下棋
			if (board[x - 1][y - 1] == ' ')
			{
				board[x - 1][y - 1] = '*';
				break;
			}
			else
				printf("坐标被占用,不能下棋!\n");
		}
		else
			printf("超出范围,请重新输入!\n");
	}
}

//电脑下棋
//找没有下棋的坐标随机下棋
void computer_play(char board[ROW][COL], int row, int col)
{
	printf("电脑已下棋\n");
	int x = 0;
	int y = 0;
	while (1)
	{
		x = rand() % ROW;
		y = rand() % COL;
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}

}
//棋盘满了返回1,没满返回0
int boardfull(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;
}

/*
判断输赢
玩家赢		*
电脑赢		#
平局		q
游戏继续	    c
*/
char iswin(char board[ROW][COL], int row, int col)
{
//行连满3枚棋
	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];

//列连满3枚棋
	for (int j = 0; j < col; j++)
		if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[0][j] != ' ')
			return board[0][j];
//对角线连满3枚棋
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
		return board[0][0];
	if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')
		return board[0][2];
//没有连满3枚棋
	if (boardfull(board, row, col))
		//棋盘满了就是平局
		return 'q';
	else
		return 'c';
}

以下是完整五子棋代码:

为了游戏的拓展性,也可以是双人对战的N字棋,N颗棋子相连就可以获胜的游戏规则,修改头文件CHESSNUM符号常量就可以变成N子棋,棋盘的大小也可以改变。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 15
#define COL 15
#define CHESSNUM 5
void initialize_board(char board[ROW][COL], int row, int col);

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

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

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

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

//初始化棋盘
void initialize_board(char board[ROW][COL], int row, int col)
{

	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			board[i][j] = ' ';
		}
	}
}

//打印棋盘
void display_board(char board[ROW][COL], int row, int col)
{
	//第一行打印棋盘x坐标
	for (int m = 0; m < col; m++)
		printf("  %2d", m + 1);
	printf("\n");
	for (int i = 0; i < row; i++)//控制行
	{
		//第一列打印棋盘y坐标
		printf("%2d", i + 1);
		for (int j = 0; j < col; j++)//控制列
		{
			//打印数据
			printf(" %c ", board[i][j]);
			if (j < col - 1)
				printf("%c", '|');
		}
		printf("\n");
		//打印分割线
		if (i < row - 1)
		{
			printf("  ");
			for (int j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)
					printf("%c", '|');
			}
			printf("\n");
		}
	}
}

//玩家下棋
void player_play(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("\n");
	printf("玩家1请下棋\n");
	while (1)
	{
		printf("请输入坐标:");
		scanf("%d.%d", &x, &y);
		//坐标范围的判定
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			//判断棋盘上的坐标是否已经被下棋
			if (board[x - 1][y - 1] == ' ')
			{
				board[x - 1][y - 1] = '*';
				break;
			}
			else
				printf("坐标被占用,不能下棋!\n");
		}
		else
			printf("超出范围,请重新输入!\n");
	}
}

//玩家2下棋
void player_play2(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("\n");
	printf("玩家2请下棋\n");
	while (1)
	{
		printf("请输入坐标:");
		scanf("%d.%d", &x, &y);
		//坐标范围的判定
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			//判断棋盘上的坐标是否已经被下棋
			if (board[x - 1][y - 1] == ' ')
			{
				board[x - 1][y - 1] = '#';
				break;
			}
			else
				printf("坐标被占用,不能下棋!\n");
		}
		else
			printf("超出范围,请重新输入!\n");
	}
}

//棋盘满了返回1,没满返回0
int boardfull(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;
}

/*
判断输赢  写成可以定义连满的棋子数
玩家1赢		*
玩家2赢		#
平局		q
游戏继续	    c
*/
char iswin(char board[ROW][COL], int row, int col)
{
	//行连满
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j <= col - CHESSNUM; j++)
		{
			int count = 1;
			for (int k = 1; k < CHESSNUM; k++)
			{
				if (board[i][j] == board[i][j + k] && board[i][j] != ' ')
					count++;
			}
			if (count == CHESSNUM)
				return board[i][j];
		}
		
	}

	//列连满
	for (int i = 0; i <= row - CHESSNUM; i++)
	{
		for (int j = 0; j < col; j++)
		{
			int count = 1;
			for (int k = 1; k < CHESSNUM; k++)
			{
				if (board[i][j] == board[i + k][j] && board[i][j] != ' ')
					count++;
			}
			if (count == CHESSNUM)
				return board[i][j];
		}
	}
	//对角线连满
	for (int i = 0; i <= row - CHESSNUM; i++)
	{
		for (int j = 0; j <= col -CHESSNUM; j++)
		{
			int count = 1;
			for (int k = 1; k < CHESSNUM; k++)
			{
				if (board[i][j] == board[i + k][j + k] && board[i][j] != ' ')
					count++;
			}
			if (count == CHESSNUM)
				return board[i][j];
		}
	}
	for (int i = 0; i <= row - CHESSNUM; i++)
	{
		for (int j = col-1; j >= CHESSNUM - 1; j--)
		{
			int count = 1;
			for (int k = 1; k < CHESSNUM; k++)
			{
				if (board[i][j] == board[i + k][j - k] && board[i][j] != ' ')
					count++;
			}
			if (count == CHESSNUM)
				return board[i][j];
		}
	}
	//没有连满
	if (boardfull(board, row, col))
		//棋盘满了就是平局
		return 'q';
	else
		return 'c';
}

//首菜单
void menu(void)
{
	printf(" \n");
	printf("*****************************\n");
	printf("********1.开始游戏***********\n");
	printf("********0.退出游戏***********\n");
	printf("*****************************\n");
	printf(" \n");
}

void game(void)
{
	char ret = 0;
	char board[ROW][COL] = { 0 };
	//初始化棋盘,不初始化棋盘,后面打印棋盘格,会对不齐
	initialize_board(board, ROW, COL);
	//打印棋盘格
	display_board(board, ROW, COL);
	//开始下棋
	while (1)
	{
		player_play(board, ROW, COL);
		//需要判断输赢
		ret = iswin(board, ROW, COL);
		if (ret != 'c')
			break;
		display_board(board, ROW, COL);
		player_play2(board, ROW, COL);
		//需要判断输赢
		ret = iswin(board, ROW, COL);
		if (ret != 'c')
			break;
		display_board(board, ROW, COL);
	}
	if (ret == '*')
		printf("玩家1赢了\n");
	else if (ret == '#')
		printf("玩家2赢了\n");
	else
		printf("平局\n");
	display_board(board, ROW, COL);
}


int main()
{
	srand((unsigned int)time(NULL));//设置随机数的生成起点

	int input = 0;
	do
	{
		menu();
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输入不对,请重新选择\n");
			break;
		}
	} while (input);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值