C语言小项目之三子棋

这篇具有很好参考价值的文章主要介绍了C语言小项目之三子棋。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

💓博主CSDN主页:杭电码农-NEO💓

⏩专栏分类:C语言学习分享⏪

🚚代码仓库:NEO的学习日记🚚

🌹关注我🫵带你学习更多C语言知识
  🔝🔝


C语言小项目之三子棋


1. 前言📕

我们学习完数组之后,可以自己做一些小游戏来巩固我们的知识,
这里的三子棋就是其中一个偏简单的小游戏.详细的实现请看下面的分析

C语言小项目之三子棋


2. 思路分析📕

2.1 创建文件📗

  • 我们之前写代码的时候实现的功能很单一,就直接创建一个test.c文件,所有代码都在这个文件里面实现就可以了.

  • 但是当我们真正要做一个项目的时候,不管项目大或小,我们都要让我们的这个项目看起来更加规范,并且我们在实现完功能后我们希望自己能运行一下代码看看我们写的对不对.

  • 所以这里就引出了一个写项目常见的手段:创建多个文件夹分别实现不同的功能

C语言小项目之三子棋
这里在源文件中,我们需要自己定义三个文件,分别是:

  • game.c,用来实现游戏功能的文件📖
  • game.h,用来声明函数和包含头文件的文件📖
  • test.c,用来测试我们写的代码正确与否的文件📖

在本次游戏设计中,使用到了3个文件,为什么不能放在一个文件中?三子棋的实现需要多个模块的功能相互串联,多个文件可以分别处理各自模块的功能,能更好处理各个模块之间的逻辑并且便于后期调试,也使得代码的可读性提高。

我们可以将test.c文件与其他两个源文件区别开来,方便观察:

如何将不同源文件分开


2.2 实现功能需要的函数📗

众所周知啊,玩三子棋的时候是在九宫格中玩的,所以这里我们需要定义一个3×3的数组来充当我们的九宫格,这里数组中可能会存放我们下的棋子,所以我们在每次开始游戏之前都应该初始化一下数组内容

我们下棋当然要能看见棋盘了,并且要看见我们下的棋和电脑下的棋,所以这里我们需要一个打印功能

下棋分玩家下棋和电脑下棋,并且有先后顺序,所以这里我们需要单独完成两个功能:电脑随机下一个位置,玩家从键盘输入想要下的位置

根据上面的一些写法,我们现在可以暂时总结出我们需要的函数有:

  • InitBoard,初始化棋盘
  • DisplayBoard,打印棋盘
  • PlayerMove,玩家下棋
  • ComputerMove,电脑下棋

这名字你可以自己修改,但是应该要包含上面这些功能


2.3 main函数代码思考📗

  • 我们希望玩家自行选择想不想要玩游戏,假如有些人玩了一把不过瘾还想玩一把,亦或者是有人玩了一把腻了不想玩了,都是玩家自己决定的.

  • 所以我们可以在main函数中设计一个switch语句,用于判断玩家的输入,继续玩下去可以输入1,不想玩了可以输入0退出.

  • 并且main函数中应该创建3×3的数组来代表九宫格,以便被各个函数所调用并且我们下棋想要用*和#的话,应该创建一个二维的字符型数组

有了大致的思路后,接下来我们就一边写代码一边解释和思考


3. 代码实现📕

3.1 main函数📗

void menu()//菜单,选择1或0.
{
	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;
}

在main函数中,我们想要实现刚刚想到的功能,所以这里我们使用do…while语句,保证语句至少执行一次,当我们输入1时,才会进入到我们的游戏中,这里我暂且把游戏的实现代码放在void game(void)中.


3.2 game.h源文件📗

我们在test.c和game.c文件中都使用了printf和scanf等库函数,所以我们将常见的头文件包含在game.h中,再在game.c和test.c中包含game.h的文件即可

#include<stdio.h>
#include<stdlib.h>//电脑下棋生成随机数需要引用的头文件
#include<time.h>
#define row 3//将数组的行和列用define宏定义
#define col 3

//初始化棋盘
void InitBoard(char board[row][col], int r, int c);
//打印棋盘
void DisplayBoard(char board[row][col], int r, int c);
//玩家下棋
void PlayerMove(char board[row][col], int r, int c);
//电脑下棋
void ComputerMove(char board[row][col], int r, int c);

引用了常见的头文件后,我们还需要在game.h文件中声明我们之前提到过的函数,这里的r和c代表二维数组的行数也列数


3.3 初始化函数📗

我们想要在每次开始游戏之前将棋盘上所有数据清除,就是将棋盘初始化,将数组所有元素初始化为空格:

void InitBoard(char board[row][col], int r, int c)
{
	for (int i = 0; i < r; i++)
	{
		for (int j = 0; j < c; j++)
		{
			board[i][j] = ' ';
		}
	}
}

3.4 打印棋盘📗

如果我们直接将二维数组中所有元素都打印出来,它看起来并不是很美观,所以这里我们加上一些分割线和换行,使我们的九宫格更加立体.如下

C语言小项目之三子棋

void DisplayBoard(char board[row][col], int r, int c)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		//1. 打印数据
		int j = 0;
		for (j = 0; j < col; j++)
		{
			printf(" %c ", board[i][j]);
			if (j < col - 1)
				printf("|");
		}
		printf("\n");
		//2. 打印分割线
		if (i < row - 1)
		{
			int j = 0;
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)
					printf("|");
			}
			printf("\n");
		}
	}
}

当然 ! 如果你是自己玩,并且不是颜控,直接把数组打印出来也是欸有任何问题的


3.5 玩家下棋📗

玩家下棋时需要注意,玩家有可能输入的坐标位置已经有棋子了,或者输入的坐标位置在九宫格之外,所以这里当玩家键盘输入后,我们应该判断下棋的位置是否正确,如果输入的位置不正确,我们将一直重复这个过程直到输入正确的位置,所以这里我们给一个while(1)语句,恒为真,当输入坐标合法时才跳出while语句

void PlayerMove(char board[row][col], int r, int c)
{
	while (1)
	{
		printf("请选择下棋的坐标:");
		int x, y;
		scanf("%d %d", &x, &y);
		if (x > row || y > col)
		{
			printf("坐标选择越界\n");
		}
		else if (board[x - 1][y - 1] == ' ')
		{
			board[x - 1][y - 1] = '*';//将玩家输入的正确坐标赋值'*'后,break跳出while循环
			break;//如果这里不跳出循环,玩家会一直下棋
		}
		else
		{
			printf("此位置已有棋子\n");
		}
	}
}

并且我们知道,数组的下标是从0开始的,但是不是每一个玩三子棋的人都是程序员,所以我们应该将玩家输入的横纵坐标减一得到它在数组中的位置,比如:玩家输入 2 3,就是下在第二行第三列,但是数组的第二行第三列是board [ 1 ] [ 2 ];


3.6 电脑下棋📗

这里的电脑下棋是生成随机位置下棋,是不具有智能化手段的,所以这里我们首先要生成两个随机数来作为下子的横纵坐标,这里我们用到库函数rand(),rand是生成随机数的函数,它生成的数可大可小,所以这里生成的随机数有可能超出我们棋盘的范围,这里我们的棋盘是九宫格,3×3的棋盘,所以我们希望它生成的坐标在0~2之间来满足要求所以我们这样写:

int x=rand()%3;//横坐标
int y=rand()%3;//纵坐标

因为一个数对三取余一定比三要小,它只能为0 1 2,这正和我意.所以我们常常在rand()函数后面加一个取余操作来确定我们生成的随机数在一个范围内

void ComputerMove(char board[row][col], int r, int c)
{
	
	while (1)
	{
		int x, y;
	    printf("电脑下棋:\n");
		x = rand() % row;
		y = rand() % col;
		if (board[x - 1][y - 1] == ' ')//判断生成的随机位置是是不是没有下过数据
		{
			board[x - 1][y - 1] = '#';
			break;
		}
	}
}

这里和玩家下棋一样,生成了3以内的两个数字后,要判断这个位置是否已经下过棋子了,只有生成了正确的位置,才会跳出while循环


3.7 game函数的设计📗

我们的思路是.先初始化棋盘,然后再将棋盘打印出来后,让玩家开始下棋,玩家下了一个子后立马又打印棋盘,并且判断输赢,如果没赢,那么电脑再继续下棋,下子后马上又打印棋盘,并且判断电脑是否赢了,.所以这个地方我们还需要设计一个判断输赢的函数,并且还有一个问题就是当棋盘下满棋子了还没有人赢,那么这就是平局,所以我们还需要写一个函数来判断棋盘是否已满

但是不管怎么样我们先把游戏的大致过程给写出来:

void game()
{
	char board[row][col] = { 0 };//定义一个二维数组
	//初始化棋盘
	InitBoard(board, row, col);
	//打印棋盘
	DisplayBoard(board, row, col);
	//下棋
	char ret = 0;//ret用来判断对局是否结束
	while (1)
	{
		//玩家下棋
		PlayerMove(board, row, col);
		DisplayBoard(board, row, col);//下子后立马打印棋盘
		//判断输赢
		ret = IsWin(board, row, col);//判断输赢函数返回的是C,证明没有人赢,游戏继续
		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");
}

3.8 判断棋盘是否满格📗

int IsFull(char board[row][col], int r, int c)
{
	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;//棋盘满了
}

只有棋盘中有空格就证明棋盘没有被下满,如果九宫格遍历完都没有空格,证明棋盘满了.这里的返回值你可以自行设定,你甚至可以写成布尔值true或false.🎉🎉🎉


3.9 判断输赢📗

我们首先要知道什么情况下算赢了:

C语言小项目之三子棋
一共有八种情况,一个正方形的四条边加中间一个"米"字,都是赢.所以我们这样来设计代码:

char IsWin(char board[row][col], int r, int c)
{
	//赢
	//行
	int i = 0;
	for (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];//我们返回这三个元素中任意一个元素,如果玩家赢那么game函数就接受到'*',如果电脑赢就接受到'#'
		}
	}
	//列
	for (i = 0; i < col; i++)
	{
		if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')//列的判断和行一样
		{
			return board[0][i];
		}
	}
	//对角线
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
		return board[1][1];
	if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
		return board[1][1];

	//平局
	if (IsFull(board, row, col) == 1)//如果IsFull返回1,证明棋盘满了,平局
	{
		return 'Q';
	}
	//继续
	return 'C';//返回C代表没有人赢并且棋盘没有满,就继续下子
}

这里我们将判断输赢函数的返回值设计为 ’ * ’ ,‘#’ ,‘Q’ ,和’C’,其实还是有目的的,game函数的ret如果接受到判断输赢函数的返回值如果不是’C’了,证明有输赢产生,但是我并不知道是玩家赢还是电脑赢,这里玩家下子是’ * ‘,电脑下子是’ # ',所以最后我们只需要判断返回值是什么就可以判断谁赢了.


接下来我们运行看看:

三子棋下棋文章来源地址https://www.toymoban.com/news/detail-444261.html

4. 所有代码📕

  • test.c
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:6031)
#include"game.h"

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

void 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");
}

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	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.c
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:6031)
#include"game.h"

void InitBoard(char board[row][col], int r, int c)
{
	for (int i = 0; i < r; i++)
	{
		for (int j = 0; j < c; j++)
		{
			board[i][j] = ' ';
		}
	}
}

void DisplayBoard(char board[row][col], int r, int c)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		//1. 打印数据
		int j = 0;
		for (j = 0; j < col; j++)
		{
			printf(" %c ", board[i][j]);
			if (j < col - 1)
				printf("|");
		}
		printf("\n");
		//2. 打印分割线
		if (i < row - 1)
		{
			//printf("---|---|---\n");
			int j = 0;
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)
					printf("|");
			}
			printf("\n");
		}
	}
}


void PlayerMove(char board[row][col], int r, int c)
{
	
	while (1)
	{
		printf("请选择下棋的坐标:");
		int x, y;
		scanf("%d %d", &x, &y);
		if (x > row || y > col)
		{
			printf("坐标选择越界\n");
		}
		else if (board[x - 1][y - 1] == ' ')
		{
			board[x - 1][y - 1] = '*';
			break;
		}
		else
		{
			printf("此位置已有棋子\n");
		}
	}
}

void ComputerMove(char board[row][col], int r, int c)
{
	
	while (1)
	{
		int x, y;
	    printf("电脑下棋:\n");
		x = rand() % row;
		y = rand() % col;
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
}

int IsFull(char board[row][col], int r, int c)
{
	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 r, int c)
{
	//赢
	//行
	int i = 0;
	for (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];
		}
	}
	//列
	for (i = 0; i < col; i++)
	{
		if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
		{
			return board[0][i];
		}
	}
	//对角线
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
		return board[1][1];
	if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
		return board[1][1];

	//平局
	if (IsFull(board, row, col) == 1)
	{
		return 'Q';
	}
	//继续
	return 'C';
}



  • game.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define row 3
#define col 3

//初始化棋盘
void InitBoard(char board[row][col], int r, int c);
//打印棋盘
void DisplayBoard(char board[row][col], int r, int c);
//玩家下棋
void PlayerMove(char board[row][col], int r, int c);
//电脑下棋
void ComputerMove(char board[row][col], int r, int c);

char IsWin(char board[row][col], int r, int c);

int IsFull(char board[row][col], int r, int c);



到了这里,关于C语言小项目之三子棋的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 三子棋(c语言)

    三子棋是一种民间传统游戏,又叫九宫棋、圈圈叉叉棋、一条龙、井字棋等。游戏规则是双方对战,双方依次在9宫格棋盘上摆放棋子,率先将自己的三个棋子走成一条线就视为胜利。但因棋盘太小,三子棋在很多时候会出现和棋的局面。 先开一个test.c文件用来进行游戏的逻

    2024年02月03日
    浏览(22)
  • c语言——三子棋

    三个文件: 其中.cpp文件用于游戏具体函数设计,.h文件为游戏的函数声明,test.cpp文件用于测试游戏运行。  需要用到的头文件: 运行结果: 棋盘是一个3*3的平面,可以用二维数组接收,编译器不支持变长数组,我们可以用define定义数组的下标(行和列),之后有大用。 打印:

    2024年02月13日
    浏览(23)
  • C语言——三子棋游戏

    更多C语言实战项目,欢迎浏览C语言——扫雷游戏 控制台实现 游戏提供一个菜单界面,可以根据用户输入来决定“开始游戏”或者“退出游戏” 通过字符‘|’和‘-’来组成一个可视化棋盘 选择开始游戏后,玩家优先落子,落子位置用字符‘X’表示,之后是电脑随机落子,

    2024年02月07日
    浏览(31)
  • 初阶C语言——三子棋

    我们今天讲一个小游戏,三子棋大家应该都玩过吧,就是行和列,或者对角线上有一样大的字符时,就为获胜,今天我们就来写这样的一个代码实现这样的功能 首先我们要创建两个源文件和一个头文件 头文件game.h用来包含我们的头文件和函数的声明以及一些定义 game.c来实现

    2024年02月13日
    浏览(26)
  • 三子棋/井字棋(C语言)

    目录 game.h如下: game.c如下: text.c如下: 这个游戏需要用到三个文件 game.h头文件用来申明函数和导包 #pragma once #define ROW 3 #define COL 3 #include stdlib.h #include time.h #include stdio.h //初始化棋盘的函数 void InitBoard(char board[ROW][COL], int row, int col); //打印棋盘的函数 void DisplayBoard(char board[ROW

    2024年01月20日
    浏览(42)
  • C语言之三子棋游戏

    #define _CRT_SECURE_NO_WARNINGS 1 //测试三子棋 #include\\\"game.h\\\" void menu() {          printf(\\\"**********************************n\\\");     printf(\\\"*****  1.play    0.exit       ****n\\\");     printf(\\\"**********************************n\\\"); } void game()//游戏算法实现 {     char ret = 0;     //数组-存放走出的棋盘信息

    2024年01月21日
    浏览(28)
  • C语言:三子棋小游戏

    目标很简单:实现一个 三子棋小游戏。三子棋大家都玩过,规则就不提及了。本博文中实现的三子棋在对局中,电脑落子是随机的,不具有智能性,玩家的落子位置使用键盘输入坐标。下面开始详细介绍如何实现一个简单的三子棋游戏。 想要实现一个小游戏,第一件事就是

    2024年02月09日
    浏览(46)
  • 三子棋小游戏---(C语言)

    目录 前言: 1.菜单的打印 2.三子棋构思 3.实现三子棋 3.1使用宏的方式定义数组 3.2打印棋盘 3.3玩家下棋 3.4电脑随机下棋 3.5判断结局 4.源码 4.1test.c 4.2game.c  4.3game.h  ❤博主CSDN:啊苏要学习   ▶专栏分类:C语言◀   C语言的学习,是为我们今后学习其它语言打好基础,C生万物

    2024年02月03日
    浏览(71)
  • C语言三子棋小游戏

    哈喽,大家好,今天我们要利用之前所学习的C语言知识来写一个三子棋小游戏。 目录 1.游戏 2.函数部分 2.1.菜单 2.2.初始化棋盘 2.3.打印棋盘 2.4.玩家下棋 2.5.电脑下棋 2.6.判断输赢 2.7.判断棋盘是否已满 3.完整代码展示 今天我们写的代码分为三个文件来写,分别是: game.h 用来

    2024年02月04日
    浏览(33)
  • 【C语言】三子棋游戏——超细教学

    🚩 纸上得来终觉浅, 绝知此事要躬行。 🌟主页:June-Frost 🚀专栏:C语言 🔥该篇将结合之前的知识来实现 三子棋游戏。 通过迭代保证每次玩完游戏后可以再来一局或者退出。 博主将会对上图每一个板块进行函数实现。 选择是否玩游戏 该板块的循环部分将会使用do while

    2024年02月11日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包