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

【C语言】-- 模拟实现三子棋

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

【C语言】-- 模拟实现三子棋

目录

1.功能需求分析

2.功能设计与实现

1.主体框架test.c

2.功能实现game.c

3.头文件game.h

3.结果展示


        模拟实现简版三子棋小项目涉及了综合知识点,主要有函数、数组,也有分支循环的运用,还有多文件操作。很好地将所学知识点结合运用,主要考察的是整体结构设计和设计函数的逻辑。

1.功能需求分析

三子棋主要有以下几个功能模块:

  1. 棋盘初始化 
  2. 玩家走
  3. 电脑走
  4. 判断状态
  5. 显示棋盘

2.功能设计与实现

1.主体框架test.c
void menu()
{
	printf("*****************************************n");
	printf("************   1.开始游戏   **************n");
	printf("************   0.离开游戏   **************n");
	printf("*****************************************n");
}
void game()
{
	//定义棋盘
	char board[ROW][COL]={0};

	//初始化棋盘
	initboard(board, ROW, COL);

	//打印棋盘
	printboard(board, ROW, COL);

	//棋子移动
	char ret = 0;//记录棋局的状态
	while (1)
	{
		playermove(board, ROW, COL);//玩家走
		printboard(board, ROW, COL);//显示棋盘内容
		ret = is_win(board, ROW, COL);//棋局的状态
		if (ret != 'C')
			break;
		computermove(board, ROW, COL);//电脑走
		printboard(board, ROW, COL);//显示棋盘内容
		printf("n");
		ret = is_win(board, ROW, COL);//棋局的状态
		if (ret != 'C')
			break;
	}
	if (ret == '*')
	{
		printf("玩家赢!n");

	}
	else if (ret == '#')
	{
		printf("电脑赢!n");

	}
	else if (ret == 'Q')
	{
		printf("平局!n");

	}
	printboard(board, ROW, COL);
	printf("n");
	printf("请选择是否重新游戏?n");
}
int main()
{
	int input = 0;
	do
	{
		srand((unsigned int)time(NULL));
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("离开游戏n");
			break;
		default:
			printf("输入错误,请重新选择!n");
			break;
		}
	} while (input);
	return 0;
}

2.功能实现game.c

实现所需功能:

  1. 棋盘初始化 
  2. 玩家走
  3. 电脑走
  4. 判断状态--已优化
  5. 显示棋盘--已优化

功能模块注解:对于功能3,只是实现了随机下棋:对于功能4和5,都可以适配N子棋

        1.棋盘初始化--将所有位置初始化为空格,开始要空棋盘

void initboard(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] = ' ';
		}
	}
}

        2.打印棋盘--让你知道棋盘的状态

void printboard(char board[ROW][COL], int row, int col)
{
	//注:
	//理解为ROW行,每一行其实又包括两行(两个部分),第一行为“棋子”和分割(|),第二行为“---”和分割(|)
	//其中每行的末尾不需分割(|),最后一行没有“---”和分割(|),即没有(第二部分)

	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)//每行的第一个部分
		{
			printf(" %c ", board[i][j]);
			if (j < col - 1)
			{
				printf("|");//每行的末尾不需分割(|)
			}
		}
		printf("n");//将本来一行的内容分开
		if (i < row - 1)
		{
			for (int j = 0; j < col; j++)//每行的第二个部分
			{
				printf("---");
				if (j < col - 1)
				{
					printf("|");
				}
			}
			printf("n");
		}


	}
}

        3.玩家走

void playermove(char board[ROW][COL], int row, int col)
{
	//玩家走要考虑提示走的对不对
	//对--坐标在范围内且坐标未被访问过
	//错--一是不在坐标范围内,二是坐标已被占用

	while (1)
	{
		int x = 0, y = 0;
		printf("玩家走:");
		scanf("%d %d", &x, &y);
		if (1 <= x && x <= row && 1 <= y && y <= col)//输入范围要合法
		{
			//考虑玩家下棋的坐标是从1开始的,所以要减一以满足数组的下标;坐标不仅要合法还要不能重复走
			if (board[x - 1][y - 1] == ' ')
			{
				board[x - 1][y - 1] = '*';
				break;
			}
			else
			{
				printf("坐标已被占用,请重新输入!");
			}
		}
		else
		{
			printf("非法输入,请重新输入!n");
		}
	}
}

        4.电脑走--随机

void computermove(char board[ROW][COL], int row, int col)
{
	while (1)
	{
		int x = rand() % row;
		int y = rand() % col;
		if (board[x][y] == ' ')
		{
			printf("电脑走:n");
			board[x][y] = '#';
			break;
		}
	}
}

        5.判断局势

返回值注解:'Q':平局; 'C':继续下棋;

                       '#':电脑赢; '*' :玩家赢

int is_full(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;
}
char is_win(char board[ROW][COL], int row, int col)
{
	//判断行
	//注解:遍历整个二维数组,两两比较,遍历范围少一列,因为当遍历到倒数第二列时,比较的是最后两列的内容。
	//所以以比较到最后两个时,判断列+1等于最后最后一列作为输出条件。
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col - 1; j++)
		{
			if (board[i][j] == board[i][j + 1] && board[i][j] != ' ')//两两比较,要考虑这一行还没下棋的情况(' ')
			{
				if ((j + 1 == col - 1))//遍历到最后一列,说明这一行都是一样的,赢了
				{
					return board[i][j];
				}
			}
			else
			{
				break;
			}
		}
	}

	//判断列
	for (int j = 0; j < col; j++)
	{
		for (int i = 0; i < row - 1; i++)
		{
			if (board[i][j] == board[i + 1][j] && board[i][j] != ' ')
			{
				if (i + 1 == row - 1)
				{
					return board[i][j];
				}
			}
			else
			{
				break;
			}
		}
	}

	//判断正对角
	for (int i = 0, j = 0; i < row - 1; i++, j++)
	{
		if (board[i][j] == board[i + 1][j + 1] && board[i][j] != ' ')
		{
			if (i + 1 == row - 1)
			{
				return board[i][j];
			}
		}
		else
		{
			break;
		}
	}

	//判断副对角
	for (int i = 0, j = row - 1; i < row - 1; i++, j--)
	{
		if (board[i][j] == board[i + 1][j - 1] && board[i][j] != ' ')
		{
			if (i + 1 == row - 1)
			{
				return board[i][j];
			}
		}
		else
		{
			break;
		}
	}

	//判断平局--无位置可下棋则为平局
	int tmp = is_full(board, ROW, COL);
	if (tmp == 1)
		return 'Q';//平局
	else
		return 'C';//继续下棋

}

3.头文件game.h

        包含.c文件所需的库函数、宏定义以及各功能函数的声明

#pragma once
#include 
#include 
#include 

//行和列宏定义
#define ROW 3
#define COL 3

//函数声明
void initboard(char board[ROW][COL], int row, int col);
void printboard(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 is_win(char board[ROW][COL], int row, int col);

3.结果展示

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

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

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