c语言实践项目:三子棋(肯定能看懂)

本文详细介绍了如何使用C语言实现三子棋游戏,包括初始化棋盘、电脑和玩家下棋、检查结果、判断胜负等功能。通过创建头文件和源文件组织代码,实现游戏流程。同时,指出了代码存在的问题,如电脑下棋速度变慢等,并邀请读者提供改进建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天我们来完成一个项目 用c语言实现三子棋

先说一下代码的基本逻辑

1.显示棋盘
2. 电脑或玩家下棋
3. 检查结果
4. 电脑或玩家下棋
5. 检查结果
6. 判断胜负

下面是代码实操

添加头文件

由于函数较多,写在一起比较乱,首先我们先创建一个头文件命名为game.h 再定义一个源文件 game.c ,为了方便使用,我们再写一个公共的头文件库 untili.h,这样我们在使用的时候通过引用untili就相当于引用全部的头文件了,最后创建一个源文件,是我们的主函数,命名为gamemain.c,这里的操作放出来一个,以此类推
添加一个头文件game.h

这就是创建完成的结果
下面我们开始写函数

0.主要函数以及头文件

#game.h

#ifndef _GAME_H_
#define _GAME_H_

#include"untili.h"
void InitGame();
void ShowchessBoard();
void ComputerChoice();
bool IsFull();
char CheckResult();
void gamerchoice();
void startgame();
//int  VictoryJudgment(char winner);


#endif /* _GAME_H_ */

untili.h

#ifndef _UTILI_H_
#define _UTILI_H_
#include<stdio.h>
#include"time.h"
#include<stdbool.h>
#include<stdlib.h>

#endif /* _UTILI_H_ */

1.显示棋盘

void InitGame()
{
	for (int i = 0; i < ROW; ++i)
	{
		for (int j = 0; j < COL; ++j)
		{
			chess_board[i][j] = ' ';
		}
	}
}
void ShowchessBoard()
{
	for (int i = 0; i < ROW; ++i)
	{
		printf("| %c | %c | %c |\n", chess_board[i][0],
			chess_board[i][1],
			chess_board[i][2]);
		if (i + 1 != ROW)
			printf(" --- --- ---\n");
	}
}

数组的定义和宏请参考开头的函数表(row和col都是3)
InitGame()的作用是把一个3*3的二维数组全都变成空格,方便落子
ShowchessBoard()的作用则是围成一个棋盘的形状

2.电脑下棋

在这里,我们先让电脑下棋,到全部完成一会是可以选择谁先下的

void ComputerChoice()
{
	int x, y;
	while (1)
	{
		srand(time(0));
		x = rand() % ROW;
		y = rand() % COL;
		if (chess_board[x][y] == ' ')
		{
			chess_board[x][y] = 'x';
			break;
		}
	}
}

ComputerChoice()函数中使用了一个用时间随机种子产生随机数的方法,在使用这个方法之前我们先要引用一个头文件 stdio<time.h>
**srand(time(0));**就是用时间做随机种子,好处就是没有任何一个时刻的时间是相同的,所以我们可以放心他产生的随机数都是完全随机的。**x = rand() % ROW;**的意思就是产生一个0-ROW之间的随机数(0,1,2)。
在这里我们进行了一个判断,如果随机出来的数组元素里边是空格的话,我们就让他为’x’代表电脑下在了这里。

3.检查结果

在电脑或者我们每次下完棋以后,必须进行一次检查,检查有没有人胜出,或者是和棋,三子棋的规则是横竖斜三个连成一片就算赢,所以我们判断的逻辑就是,判断横着竖着斜着的连着的三个元素是不是一样。代码如下

bool IsFull()
{
	for (int i = 0; i < ROW; ++i)
	{
		for (int j = 0; j < COL; ++j)
		{
			if (chess_board[i][j] == ' ')
			{
				return false;
			}
		}
		
	}
	return true;

}
char CheckResult()
{
	for (int i = 0; i < ROW; ++i)
	{
		if (chess_board[i][0] != ' ' && chess_board[i][0] == chess_board[i][1]
			&& chess_board[i][0] == chess_board[i][2])
		{
			return chess_board[i][0];
		}
		for (int i = 0; i < ROW; ++i)
		{
			if (chess_board[0][i] != ' ' && chess_board[0][i] == chess_board[1][i]
				&& chess_board[0][i] == chess_board[2][i])
			{
				return chess_board[0][i];
			}
		}
		if (chess_board[1][1] != ' '
			&& chess_board[0][0] == chess_board[1][1]
			&& chess_board[0][0] == chess_board[2][2])
			return chess_board[1][1];
		if (chess_board[1][1] != ' '
			&& chess_board[0][2] == chess_board[1][1]
			&& chess_board[0][2] == chess_board[2][0])
			return chess_board[1][1];
	}
	if (IsFull())
		return 'h';
		return 'c';
}

在这里char CheckResult()函数的作用就是刚才说的判断横竖斜,这里不再赘述,我们说一下
IsFull()函数,这个函数的作用是判断有没有产生平局,产生了就返回真,没产生就返回假,他是通过循环遍历数组,看数组中还有没有空格,有,就是还没有和棋。
返回’x’电脑赢
返回’o’玩家赢
返回’c’继续(棋盘没满)
返回’h’和棋(棋盘满了)

4.玩家下棋

 void gamerchoice()
{
	printf("请您落子\n");
	int x, y;
	while (1)
	{
		printf("您输入的坐标为:");
		scanf_s("%d %d", &x, &y);
		if (chess_board[x][y] == ' ')
		{
			chess_board[x][y] = 'o';
			break;
		}
		else
		{
			printf("您输入的位置已落子,请重新输入");
		}
	}
}

玩家下棋的方式和电脑区别就在于一个随机产生,一个主动输入,这里不再赘述

5.再次检查结果

和上一次判断完全相同

6.判断胜负以及game.c全局代码

判断胜负我们可以用一个char类型的变量来储存检查结果返回的值

game.c全局代码如下

#include"game.h"

#define ROW 3
#define COL 3
static char chess_board[ROW][COL];
// 基本逻辑
//1.登陆界面
//  (1)显示棋盘
void InitGame()
{
	for (int i = 0; i < ROW; ++i)
	{
		for (int j = 0; j < COL; ++j)
		{
			chess_board[i][j] = ' ';
		}
	}
}
void ShowchessBoard()
{
	for (int i = 0; i < ROW; ++i)
	{
		printf("| %c | %c | %c |\n", chess_board[i][0],
			chess_board[i][1],
			chess_board[i][2]);
		if (i + 1 != ROW)
			printf(" --- --- ---\n");
	}
}
//2.电脑下棋
void ComputerChoice()
{
	int x, y;
	while (1)
	{
		srand(time(0));
		x = rand() % ROW;
		y = rand() % COL;
		if (chess_board[x][y] == ' ')
		{
			chess_board[x][y] = 'x';
			break;
		}
	}
}
//3.判断输赢
// 返回'x'电脑赢
// 返回'o'玩家赢
// 返回'c'继续(棋盘没满)
// 返回'h'和棋(棋盘满了)
bool IsFull()
{
	for (int i = 0; i < ROW; ++i)
	{
		for (int j = 0; j < COL; ++j)
		{
			if (chess_board[i][j] == ' ')
			{
				return false;
			}
		}
		
	}
	return true;

}

char CheckResult()
{
	for (int i = 0; i < ROW; ++i)
	{
		if (chess_board[i][0] != ' ' && chess_board[i][0] == chess_board[i][1]
			&& chess_board[i][0] == chess_board[i][2])
		{
			return chess_board[i][0];
		}
		for (int i = 0; i < ROW; ++i)
		{
			if (chess_board[0][i] != ' ' && chess_board[0][i] == chess_board[1][i]
				&& chess_board[0][i] == chess_board[2][i])
			{
				return chess_board[0][i];
			}
		}
		if (chess_board[1][1] != ' '
			&& chess_board[0][0] == chess_board[1][1]
			&& chess_board[0][0] == chess_board[2][2])
			return chess_board[1][1];
		if (chess_board[1][1] != ' '
			&& chess_board[0][2] == chess_board[1][1]
			&& chess_board[0][2] == chess_board[2][0])
			return chess_board[1][1];
	}
	if (IsFull())
		return 'h';
		return 'c';
}
//4.玩家下棋
 void gamerchoice()
{
	printf("请您落子\n");
	int x, y;
	while (1)
	{
		printf("您输入的坐标为:");
		scanf_s("%d %d", &x, &y);
		if (chess_board[x][y] == ' ')
		{
			chess_board[x][y] = 'o';
			break;
		}
		else
		{
			printf("您输入的位置已落子,请重新输入");
		}
	}
}
//5.判断输赢
//6.游戏界面

 void startgame()
 {
	 InitGame();
	 char winner;
	 int mode;
	 printf("请选择您的游戏模式 :输入 1 您先下,输入 0 电脑先下\n"); 
	 scanf_s("%d", &mode);
	 while(1)
	 {
		 if (mode) 
		 {
			 ShowchessBoard();
			 gamerchoice();
			 winner = CheckResult();
			 if (winner != 'c')
				 break;
			 ComputerChoice();
			 winner = CheckResult();
			 if (winner != 'c')
				 break;
		 }
		 else
		 {
			 ComputerChoice();
			 ShowchessBoard();
			 winner = CheckResult();
			 if (winner != 'c')
				 break;
			 gamerchoice();
			 winner = CheckResult();
			 if (winner != 'c')
				 break;
		 }
	 }
	  ShowchessBoard();
	  if (winner == 'x')
	  {
		  printf("很遗憾,您输了,是否再来一局: 输入:1再来,输入:0结束\n");
	  }
	  if (winner == 'o')
	  {
		  printf("恭喜您,您赢了,是否再来一局: 输入:1再来,输入:0结束\n");
	  }
	  if (winner == 'h')
	  {
		  printf("双方棋逢对手,是否再来一局: 输入:1再来,输入:0结束\n");
	  }
	 
 }

在这里我们实现了一个功能就是选择模式,是电脑先下还是玩家先下,但是操作过程比较简陋,希望各位看官能指导一下

7.登录界面

登录界面的操作比较简单.

int main()
{
	int choose;
	int select = 1;
	while (select)
	{
		printf("*******************************\n");
		printf("*        简 易 三 子 棋       *\n");
		printf("*******************************\n");
		printf("*  [1] Play        [0] Exit   *\n");
		printf("*******************************\n");
		printf("请选择:>");
		scanf_s("%d", &select);
		if (select == 0)
		{
			break;
		}
		if (select != 1)
		{
			printf("error again\n");
			continue;
		}
		do {
			startgame();
			scanf_s("%d", &choose);
			system("cls");
		   } while (choose);
	}
	printf("************ GoodBye *********\n");
	return 0;
}

在gamemain.c这个主函数中,我们主要实现了几点功能,一个是显示了游戏的登录界面
另一个重要功能就是通过do while循环来控制游戏次数,可以多次进行游戏:

总结

到这里呢,我们的三子棋项目就算完成了,但是还有几点问题
1.发现使用时间做随机种子电脑下的越来越慢了,到最后程序几乎就停住了
2.代码不够简洁
3.还有些功能可以开发出来(比如计分板)
有任何不明白的地方都可以在评论区中提出,还请各位给上珍贵的指导意见。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值