栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C语言实现三子棋小游戏(初级:人vs笨笨机器人)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C语言实现三子棋小游戏(初级:人vs笨笨机器人)

目录

游戏效果展示:

 游戏设计思路

模块化设计

打印菜单

初始化棋盘

 打印棋盘

方法一:(棋盘被固定死了,只能是三子棋)

方法二:(更灵活,棋盘可以任意扩大,变为五子棋棋盘等) 

玩家下棋

电脑下棋

判断输赢

方法一:(只适用于三子棋)

方法二:(这种做法适用于n子棋) 

 整体代码

test.c

 game.h

 game.c

游戏效果展示:

 游戏设计思路

模块化设计

为了让程序一目了然,采用了分模块的方式 ,分成3个模块:

test.c    测试游戏的逻辑

game.c 游戏代码的实现

game.h 游戏代码的声明(包括函数声明,符号定义,库函数头文件的包含)

   

打印菜单

进入游戏之后首先要打印菜单,所以写了个menu函数。

有了菜单,玩家就可以选择是否进行游戏了(scanf),根据选择情况(input的值)决定走switch的哪条语句。

因为游戏不是只玩一把就不玩了,所以菜单的打印和选择是个循环。

又因为游戏至少要进来一次,菜单至少要打印一次,所以用了do...while循环。 

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

int main()
{
	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;
}

初始化棋盘

进入游戏,玩家下棋前,我们需要一个棋盘,并且需要对棋盘初始化,是为了方便对后面玩家和电脑下的棋子的存储。

我们下的棋子需要被存储下来,因为是三子棋,所以我们需要一个3*3的二维数组。

我们约定一下,玩家下棋是‘*’,电脑下棋是‘#’,所以数组是个二维字符数组。

为了方便之后可能会想将三子棋改成五子棋或更大, 所以用了符号定义,如下:

#define ROW 3
#define COL 3
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] = ' ';
		}
	}
}

 打印棋盘

方法一:(棋盘被固定死了,只能是三子棋)
void DisplayBoard(char board[ROW][COL], int row, int col)
{
	//方法一:
	int i = 0;
	for (i = 0; i < row; i++)
	{
		printf(" %c | %c | %c n", board[i][0], board[i][1], board[i][2]);
		if (i < col - 1)
		{
			printf("---|---|---n");
		}
	}
}

方法二:(更灵活,棋盘可以任意扩大,变为五子棋棋盘等) 
void DisplayBoard(char board[ROW][COL], int row, int col)
{
	//方法二:
	int i = 0;
	for (i = 0; i < row; i++)
	{
		//printf(" %c | %c | %c n", board[i][0], board[i][1], board[i][2]);
		int j = 0;
		for (j = 0; j < col; j++)
		{
			printf(" %c ",board[i][j]);
			if (j < col - 1)
			{
				printf("|");
			}
		}
		printf("n");
		
		if (i < col - 1)
		{
			//printf("---|---|---n");
			int j = 0;
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)
				{
					printf("|");
				}
			}
			printf("n");
		}
	}
}

玩家下棋

因为是二维数组,所以数组下标是从0开始的,但是玩家可能不是程序员,不知道数组的下标,输入的坐标是从1开始的,所以这里把下标定义从1开始。

void PlayerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	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] != ' ')//这里注意,玩家输入的是1-3,但是对应在程序里的是0-2,所以别忘记减1
			{
				printf("坐标被占用,不能下棋,请选择其它位置n");
			}
			else
			{
				board[x-1][y-1] = '*';
				break;
			}
		}
		else
		{
			printf("坐标非法n");
		}
	}
}

电脑下棋

电脑有点笨,它的下棋方法是先用时间戳生成一个随机数,并把随机数的范围控制在0~2,它会随机下在一个没有被占用的棋盘上的坐标。

srand函数是在主函数里面设置的 

int main()
{
	srand((unsigned int)time(NULL));//设置随机数的生成起点,引入时间戳的概念
    
    return 0;
}
void ComputerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("电脑下棋:n");
	while (1)
	{
		x = rand() % 3;
		y = rand() % 3;
		if (board[x][y] != ' ')
		{
			;
		}
		else
		{
			board[x][y ] = '#';
			break;
		}
	}
}

判断输赢

 

电脑或玩家赢的情况有三种:行,列,或对角线落满相同棋子;

当棋盘已经落满棋子但谁也没有赢时,为平局;

当棋盘还没有落满棋子并且谁也没有赢时,游戏继续。

我们约定:
玩家赢 - 返回‘*’
电脑赢 - 返回‘#’
平局 - 返回‘Q’
继续 - 返回‘C’

方法一:(只适用于三子棋)
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;
}

char Iswin(char board[ROW][COL], int row, int col)
{
	int i = 0;
    //行
	for (i = 0;i 

方法二:(这种做法适用于n子棋) 
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;
}

char IsWin(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;

	//行相等
	for (i = 0; i < row; i++)
	{
		int count = 0;
		for (j = 0; j < col-1; j++)
		{
			if (board[i][j] == board[i][j + 1] && board[i][j] != ' ')
		       count++;
		    else
			   break;
		}
		if (count == col - 1)
			return board[i][j];
	}
	//列相等
	for (j = 0; j < row; j++)
	{
		int count = 0;
		for (i = 0; i < col-1; i++)
		{
			if (board[i][j] == board[i+1][j] && board[i][j] != ' ')
				count++;
			else
				break;
		}
		if (count == col - 1)
			return board[i][j];
	}
	//对角线相等
	
		int count = 0;
		for (i = 0,j = 0; i0; i++, j--)
		{
			if (board[i][j] == board[i + 1][j-1] && board[i][j] != ' ')
				count++;
			else
				break;
		}
		if (count == col - 1)
			return board[i][j];
		//判断平局
		if (IsFull(board, ROW, COL))
			return 'Q';
		else
			return 'C';
	
}

 整体代码

test.c
#include "game.h"

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

game()
{
	//创建一个二维数组用来存放下的棋子
	char board[ROW][COL] = { 0 };
	//初始化棋盘的数据为空格
	InitBoard(board, ROW, COL);
	//打印棋盘
	DisplayBoard(board, ROW, COL);
	char ret = 0;
	while (1)
	{
		//玩家下棋
		PlayerMove(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		//判断输赢
		ret = IsWin(board, ROW, COL);
		if (ret != 'C')
			break;
		//电脑下棋
		ComputerMove(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		//判断输赢
		ret = IsWin(board, ROW, COL);
		if (ret != 'C')
			break;

	}
	if (ret == '*')
		printf("玩家赢n");
	else if (ret == '#')
		printf("电脑赢n");
	else
		printf("平局n");
	DisplayBoard(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;
}

 game.h
#include 
#include 
#include 

#define ROW 3
#define COL 3
//初始化棋盘的数据为空格

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

//打印棋盘

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

//玩家下棋

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

//电脑下棋

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

//判断输赢

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

 game.c
#include "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] = ' ';
		}
	}
}

//打印棋盘

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]);
			if (j < col - 1)
			{
				printf("|");
			}
		}
		printf("n");
		
		if (i < col - 1)
		{
			int j = 0;
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)
				{
					printf("|");
				}
			}
			printf("n");
		}
	}
}

//玩家下棋

void PlayerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	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] != ' ')//这里注意,玩家输入的是1-3,但是对应在程序里的是0-2,所以别忘记减1
			{
				printf("坐标被占用,不能下棋,请选择其它位置n");
			}
			else
			{
				board[x-1][y-1] = '*';
				break;
			}
		}
		else
		{
			printf("坐标非法n");
		}
	}
}

//电脑下棋

void ComputerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("电脑下棋:n");
	while (1)
	{
		x = rand() % 3;
		y = rand() % 3;
		if (board[x][y] != ' ')
		{
			;
		}
		else
		{
			board[x][y ] = '#';
			break;
		}
	}
}

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

char IsWin(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;

	//行相等
	for (i = 0; i < row; i++)
	{
		int count = 0;
		for (j = 0; j < col-1; j++)
		{
			if (board[i][j] == board[i][j + 1] && board[i][j] != ' ')
		       count++;
		    else
			   break;
		}
		if (count == col - 1)
			return board[i][j];
	}
	//列相等
	for (j = 0; j < row; j++)
	{
		int count = 0;
		for (i = 0; i < col-1; i++)
		{
			if (board[i][j] == board[i+1][j] && board[i][j] != ' ')
				count++;
			else
				break;
		}
		if (count == col - 1)
			return board[i][j];
	}
	//对角线
	
		int count = 0;
		for (i = 0,j = 0; i0; i++, j--)
		{
			if (board[i][j] == board[i + 1][j-1] && board[i][j] != ' ')
				count++;
			else
				break;
		}
		if (count == col - 1)
			return board[i][j];
		//判断平局
		if (IsFull(board, ROW, COL))
			return 'Q';
		else
			return 'C';
	
}

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1001942.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号