IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 用c语言实现三子棋小游戏 -> 正文阅读

[C++知识库]用c语言实现三子棋小游戏


目录

前言

本文适合有一定c语言基础的小伙伴,基础稍微薄弱的可能看着会有点吃力,但并不会影响对思路的把握。这类型的程序要求有一些基础,它可以体现你对所学知识的整体掌握程度??在阅读本文前,希望你们已经掌握了以下知识包括???头文件?源文件定义及作用? ? 函数及函数传参函数传参????循环? 数组(二维数组)

正文

引入

代码程序化

1.菜单 menu()

2.棋盘 Board()

3.下棋? Move()

4.判断规则或者叫游戏规则? Judge()

后话




前言


本文适合有一定c语言基础的小伙伴,基础稍微薄弱的可能看着会有点吃力,但并不会影响对思路的把握。这类型的程序要求有一些基础,它可以体现你对所学知识的整体掌握程度??在阅读本文前,希望你们已经掌握了以下知识
包括???头文件?源文件定义及作用? ? 函数及函数传参函数传参????循环? 数组(二维数组)

本文将展示写程序的思路,以及代码实现



正文

引入

三子棋应该具有哪些要素?或者说你想设计一个小游戏,你希望它有什么功能呢?

以三子棋为例,我觉得应该有以下的功能

1.菜单

2.棋盘

3.玩家和电脑下棋

4.判断规则

ok,功能已经想好了,那就开始把它们用程序写出来


代码程序化

1.菜单 menu()

代码如下:

void menu()
{
?? ?printf("************三子棋游戏************\n");
?? ?printf("****** 1. play *** 0. exit ******\n");
?? ?printf("*********************************\n");

}菜单可以自己设计,你觉得好看就行


2.棋盘 Board()

你觉得棋盘有该有哪些功能?

我觉得应该有初始化功能 InitializeBoard()? ?和? ? 显示功能DisplayBoard()

于是我们有了以下代码

 ?? ?//用数组来存放我们要下的棋子
?? ?char Board[ROW][COL] = { 0 };
//棋盘初始化 ? 数组里面的元素为空格,视觉上看起来棋盘是空的
void InitializeBoard(char Board[ROW][COL], int row, int col)?
{
?? ?int i = 0;?
?? ?int j = 0;
?? ?for (i = 0; i < row; i++)
?? ?{

?? ??? ?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++)//打印第i行的内容
?? ??? ?{
?? ??? ??? ?//打印数据行
?? ??? ??? ?printf(" %c ", Board[i][j]);//对应下图的1号绿色圆角方框
?? ??? ??? ?if (j < col - 1)//最后一列不用打印"|"
?? ??? ??? ?{
?? ??? ??? ??? ?printf("|");
?? ??? ??? ?}
?? ??? ?}
?? ??? ?printf("\n");//换行准备打印分割行
?? ??? ?//打印分割行
?? ??? ?if (i < row - 1)//最后一行不用答应分割行
?? ??? ?{?? ??? ??? ?
?? ??? ??? ?for (j = 0; j < col; j++)
?? ??? ??? ?{
?? ??? ??? ??? ?printf("---");
?? ??? ??? ??? ?if (j < col - 1)
?? ??? ??? ??? ?{
?? ??? ??? ??? ??? ?printf("|");
?? ??? ??? ??? ?}
?? ??? ??? ?}
?? ??? ??? ?printf("\n");
?? ??? ?}
?? ?}
}看到这里可能有小伙伴会对DisplayBoard()的写法有点疑问,希望下面的这张图能打消你的疑虑

左边红色的椭圆代表Board[i][j],右边的1号绿色圆角方框代表"? ? Board[i][j]? ? ? "对应代码的??" %c "(注意中间空白是一个空格哦)? ? 2号方框代表竖着的分割线 对应代码中的? ? "|"? ,那么3号方框代表什么应该知道了吧,没错,就是代码中的"---"

为什么要这么设置呢?那是因为这才是打印出棋盘的最小"循环单元"这里就不细述原因了,毕竟这不是代码的重点.如果有疑惑的话可以私信我哦

3.下棋? Move()

有两个玩家(玩家和电脑)那就自然有两个函数啦

玩家下棋PlayerMove()? ?和? 电脑下棋ComputerMove()

因为我们在上面已经将棋盘的元素初始化为空格了所以要想下棋的话 就把棋盘上对应坐标的空格替换成代表玩家棋子的字符? "*"? ?"#"就行啦,这里呢我们用"*"代表玩家的棋子,"#"代表电脑的棋子,当然你想用什么表示就用什么表示,只要是个字符就可以了.

void PlayerMove(char Board[ROW][COL], int row, int col)
{
	//用坐标来表示位置
	int x = 0;
	int y = 0;
	printf("玩家走\n");
	while (1)//考虑到玩家有可能会不小心输入错误坐标,so 应该设计while循环
	{
		printf("请输入要下的坐标:  ");
		scanf_s("%d%d", &x, &y);
		//判断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 ComputerMove(char Board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("电脑走\n");
	while (1)
	{
		//利用rand函数不断产生随机数
		x = rand() % row;
		y = rand() % col;
		if (Board[x][y] == ' ')//电脑他知道数组定义啊,so 这里直接没有减一
		{
			Board[x][y] = '#';
			break;
		}
	}

}

4.判断规则或者叫游戏规则? Judge()

三子棋三子棋,顾名思义就是三个子的棋(你小子搁着搁着呢!) 开个玩笑

判断输赢规则无非就是四条? ?三行三列两对角,只要这四条线上的棋子一致就赢了

当然还应该有个函数IsFull()共同来判断当前游戏状态 是平局呢,是玩家赢呢,是电脑赢呢,还是该继续游戏呢

代码如下

int IsFull(char Board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			if (Board[i][j] == ' ')
			{
				return 0;//没满
			}
		}
	}
	return 1;//满了
}
char Judge(char Board[ROW][COL], int row, int col)
{
	int i = 0;
	//横三行
	for (i = 0; i < row; i++)
	{
		if (Board[i][0] == Board[i][1] && Board[i][1] == Board[i][2] && Board[i][1] != ' ')
		{
			return Board[i][1];
		}
	}
	//竖三列
	for (i = 0; i < col; i++)
	{
		if (Board[0][i] == Board[1][i] && Board[1][i] == Board[2][i] && Board[1][i] != ' ')
		{
			return Board[1][i];
		}
	}
	//两个对角线
	
	if (Board[0][0] == Board[1][1] && Board[1][1] == Board[2][2] && Board[1][1] != ' ')
		return Board[1][1];

	if (Board[2][0] == Board[1][1] && Board[1][1] == Board[0][2] && Board[1][1] != ' ')
		return Board[1][1];
	//判断是否平局
	if (1 == IsFull(Board, ROW, COL))
	{
		return "Q";
	}
	//继续
	return 'C';
}

三行三列的判断上我觉得我们写的代码应该差不多

但是在两对角线的写法上有小伙伴会说,既然三行三列都可以用循环表达,那么两对角线应该也可以

for (i = 0; i < row; i++)//左上-右下
	{
		if (Board[i][i] == Board[i + 1][i + 1])
			continue;
		else
			break;
	}
	for (i = 0; i < row; i++)//左下-右上
	{
		if (Board[i][row-1-i] == Board[i + 1][row -2-i])//当i=2的时候数组会越界
			continue;
		else
			break;
	}

对,思路没问题,只是会产生越界的情况,那可不可以避免呢?答案是可以.只要在定义ROW和COL的时候,多加个2,比如,这个程序是三子棋,ROW,COL为3,只要定义它俩为5,让整个棋盘多一圈,我们在对Board[][]数组进行操作时只操作其下标中的1-3就行了.这里就只给出思路了,感兴趣的小伙伴可以自己尝试一下,我相信你要是能尝试下去就可以摸索出n子棋的写法.

全局代码如下

有三个板块,一个头文件game.h,两个源文件test.c? ?game.c

game.h

//函数声明部分

#define ROW 3
#define COL 3

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

//声明
void InitializeBoard(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);


//告诉我们四种游戏的状态
//玩家赢 - '*'
//电脑赢 - '#'
//平局   - 'Q'  用单字符表示嗷,不要为了显示你的高英语水平就用字符串,越简洁越好
//继续   - 'C'

char Judge(char Board[ROW][COL], int row, int col);

game.c

//游戏模块  函数定义

#include<stdio.h>
#include "game.h"


void InitializeBoard(char Board[ROW][COL], int row, int col) 
{
	int i = 0; 
	int j = 0;
	for (i = 0; i < row; i++)
	{

		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++)//打印第i行的内容
		{
			//打印数据行
			printf(" %c ", Board[i][j]);//对应下图的1号绿色圆角方框
			if (j < col - 1)//最后一列不用打印"|"
			{
				printf("|");
			}
		}
		printf("\n");//换行准备打印分割行
		//打印分割行
		if (i < row - 1)//最后一行不用答应分割行
		{			
			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)//考虑到玩家有可能会不小心输入错误坐标,so 应该设计while循环
	{
		printf("请输入要下的坐标:  ");
		scanf_s("%d%d", &x, &y);
		//判断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 ComputerMove(char Board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("电脑走\n");
	while (1)
	{
		//利用rand函数不断产生随机数
		x = rand() % row;
		y = rand() % col;
		if (Board[x][y] == ' ')//电脑他知道数组定义啊,so 这里直接没有减一
		{
			Board[x][y] = '#';
			break;
		}
	}

}

//判断棋盘满没满
//返回1表示棋盘满了
//返回0,表示棋盘没满

int IsFull(char Board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			if (Board[i][j] == ' ')
			{
				return 0;//没满
			}
		}
	}
	return 1;//满了
}
//三行三列两对角
char Judge(char Board[ROW][COL], int row, int col)
{
	int i = 0;
	//横三行
	for (i = 0; i < row; i++)
	{
		if (Board[i][0] == Board[i][1] && Board[i][1] == Board[i][2] && Board[i][1] != ' ')
		{
			return Board[i][1];
		}
	}
	//竖三列
	for (i = 0; i < col; i++)
	{
		if (Board[0][i] == Board[1][i] && Board[1][i] == Board[2][i] && Board[1][i] != ' ')
		{
			return Board[1][i];
		}
	}
	//两个对角线
	
	if (Board[0][0] == Board[1][1] && Board[1][1] == Board[2][2] && Board[1][1] != ' ')
		return Board[1][1];

	if (Board[2][0] == Board[1][1] && Board[1][1] == Board[0][2] && Board[1][1] != ' ')
		return Board[1][1];
	//判断是否平局
	if (1 == IsFull(Board, ROW, COL))
	{
		return "Q";
	}
	//继续
	return 'C';
}

test.c

//来测试我们的三子棋程序  测试模块
#include "game.h"
void menu()
{
	printf("************三子棋游戏***********\n");
	printf("****** 1. play *** 0. exit ******\n");
	printf("*********************************\n");

}
void game() 
{
	//存放Judge()函数的返回值
	char ret = 0;
	//用数组来存放我们要下的棋子
	char Board[ROW][COL] = { 0 };
	//棋盘初始化   数组里面的元素为空格,视觉上看起来棋盘是空的
	InitializeBoard(Board,ROW,COL);//因为要使用这个初始化函数,就得声明,而初始化函数是game函数的一部分,所以我们应该在 game.h 这个头文件中对其进行声明
	//打印棋盘
	DisplayBoard(Board, ROW, COL);
	//下棋,也就是"填空",把已经初始化的棋盘上的   ' '   替换成玩家和电脑要走的棋子
	while (1)
	{
		//玩家走
	    PlayerMove(Board, ROW, COL);
		DisplayBoard(Board, ROW, COL);
		
		ret=Judge(Board, ROW, COL);
          //判断玩家是否赢
		if (ret != 'C')
		{
			break;
		}
		//电脑走
		ComputerMove(Board,ROW,COL);
		DisplayBoard(Board, ROW, COL);
		//判断电脑是否赢
		ret = Judge(Board, ROW, COL);
		if (ret != 'C')
		{
			break;
		}
	
	}
     //判断剩下三种情况
	if (ret == '*')
	{
		printf("玩家赢\n");
	}
	else if (ret == '#')
	{
		printf("电脑赢\n");
	}
	else
	{
		printf("平局\n");
	}
}
void test()
{ 
	int choice;
	srand((unsigned int)time(NULL));//时间戳,配合rand函数
	do
	{
		menu();
		printf("请选择:\n");
	   
		scanf_s("%d", &choice);
		switch (choice)
		{
		case 1:
			printf("开始游戏\n");//system clc
			game();
			break;
		case 0:
			printf("退出游戏");
			break;
		default:
			printf("输入无效,请重新输入\n");

		}

	} while (choice);


}


int main()
{

	test();
	return 0;
}

这个是三个文件创建好后的亚子?

?最后附上我和电脑之间的"博弈"



后话

可能有人会说要是可以鼠标点击就好了,点哪里就落子哪里,毕竟这是一个小程序,而不是一个正

真意义上的游戏,而且编者水平有限,才刚开始学,实现起来有点困难,今天埋下一个伏笔,等我

学得差不多了,我就来补上


如果有想交流的可以评论或者私信


最后希望各位小伙伴在做类似的综合性比较高的题时可以画思维导图,好处??思路清晰,不会去想

一步写一步,时刻告诉自己这一步该做什么,我要实现什么功能

全文一共八千八百多个字,看了这么久屏幕要注意保护眼睛哦

回见!

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章           查看所有文章
加:2021-09-19 07:48:45  更:2021-09-19 07:51:24 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 23:28:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码