C语言初级小游戏——三子棋

目录

前言

一、游戏的设计思路

1.游戏模式

 2.设计模块

 二、分层说明

1.game.h文件

1.1 在此文件中,我们对其它需要在此游戏中实现的功能所对应的函数库进行了包含

1.2 进行符号定义

1.3 函数声明

2.game.c文件

2.1 对二维字符数组进行初始化

2.2 展示棋盘

2.3 玩家下棋

2.4 电脑下棋

2.5 判断棋局是否为满

2.6 判断是否赢了

3.test.c文件

3.1 main函数

3.2 menu函数

3.3 game函数

三、完整代码展示

1.test.c文件

2.game.h文件

3.game.c文件

 四、游戏效果图


前言

用写小游戏的方式,可以更快,更高效且有趣地学习C语言!!!

一、游戏的设计思路

1.游戏模式

 2.设计模块

 二、分层说明

1.game.h文件

1.1 在此文件中,我们对其它需要在此游戏中实现的功能所对应的函数库进行了包含

//头文件包含
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

这样做的好处在于,当我们需要同时使用stdio.h、stdlib.h和time.h时,不用再到每个文件中进行文件包含,我们只需写一句#include"game.h"就行,如在test.c文件中进行文件包含。

1.2 进行符号定义

为什么需要符号定义呢?这是因为我们这里的符号ROW,COL对应了二维字符数组的大小,如果当我们想改变该字符数组的大小时,只需在改动game.h文件中的ROW和COL的值,就可以改变在此游戏中,所对应的字符数组大小,不用再一个一个数字去修改。

//符号定义
#define ROW 3
#define COL 3

1.3 函数声明

在game.h文件中进行函数声明后,在其他.c文件中想用调用在game.h声明过的函数,只需要将game.h进行一个文件包含就行了。如:#include"game.h"

//函数声明
//初始化二维字符数组
void InitBoard(char[][COL], int, int);

//展示棋盘
void DisplayBoard(char[][COL], int, int);

//玩家下棋
void PlayerMove(char[][COL], int, int);

//电脑下棋
void ComputerMove(char[][COL], int, int);

//判断输赢
char IsWin(char[][COL], int, int);

2.game.c文件

在此文件中,主要是编辑了一些关于棋局实现,玩家下棋,电脑下棋,棋局展示代码等等。

2.1 对二维字符数组进行初始化

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

2.2 展示棋盘

void DisplayBoard(char board[][COL], int row, int col) {
	int i, j;
	for (i = 0;i < row;i++) {
		for (j = 0;j < col;j++) {
			printf(" %c ", board[i][j]);
			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");
		}
	}
}

2.3 玩家下棋

void PlayerMove(char board[][COL], int row, int col) {
	//定义一个坐标x,y
	int x = 0, y = 0;
	printf("玩家走>:\n");
	while (1) {
		printf("请输入下棋的坐标>:");
		scanf("%d,%d", &x, &y);
		//判断坐标的合法性
		if (x > 0 && x <= row && y > 0 && y <= col) {
			//下棋,判断判断该坐标是否被占用了
			if (board[x - 1][y - 1] == ' ') {
				board[x - 1][y - 1] = '*';
				break;
			}
			else {
				printf("该坐标已经被占用,请重新输入!\n");
			}
		}
		else {
			printf("输入的坐标不合法,请重新输入!\n");
		}
	}
}

2.4 电脑下棋

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

这其中的rand()%row,rand()%col,体现了电脑下棋的随机性,在这里我没有设计“让电脑看起来聪明点”的算法,我们初学者先能让电脑走起来就行了。

2.5 判断棋局是否为满

int IsFull(char board[][COL], int row, int col) {
	int i, j;
	for (i = 0;i < row;i++) {
		for (j = 0;j < col;j++) {
			if (board[i][j] == ' ')
				return 0;
		}
	}
	return 1;
}

2.6 判断是否赢了

char IsWin(char board[][COL], int row, int col) {
	int i;
	//横向三个连一起为赢
	for (i = 0; i < row; i++) {
		// board[i][1] != ' ' :如果三格都是空的,那也是不行的
		if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ') {
			//电脑赢返回#
			//玩家赢返回*
			return board[i][0];
		}
	}
	//竖向三个连一起为赢
	for (i = 0;i < col; i++) {
		if (board[0][i] == board[1][i] && board[2][i] == board[1][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];
	}
	else if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ') {
		return board[1][1];
	}
	//判断平局
	//判断棋局是否为满(1为满,0为非满)
	if (IsFull(board, row, col) == 1) {
		return 'Q';
	}
	return 'C';
}

3.test.c文件

3.1 main函数

游戏的主要流程步骤,在main函数中体现出来,在main函数中,不断的调用其他函数从而来实现游戏功能。在test.c文件中,还主要编辑了菜单函数menu和游戏函数game

3.2 menu函数

void menu() {
	printf("*************************\n");
	printf("*****开始游戏输入:1*****\n");
	printf("*****结束游戏输入:0*****\n");
	printf("*************************\n");
}

3.3 game函数

void game() {
	//对棋局进行初始化——用二维数组
	char board[ROW][COL];
	//对棋局进行初始化
	InitBoard(board, ROW, COL);
	//展示棋局,本质是打印二维数组的内容
	DisplayBoard(board, ROW, COL);
	//ret判断谁赢的变量
	char ret = 0;
	//玩家和电脑下棋
	while (1) {
		//玩家下棋
		PlayerMove(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		/*
		ret的值为Q:平局 —— 游戏结束
		ret的值为*:玩家赢 —— 游戏结束
		ret的值为#:电脑赢 —— 游戏结束
		ret的值为C:还没有人赢 —— 游戏继续
		*/
		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");
	}
}

我们在game函数中,还调用了game.c文件中的函数,从而丰富了我们的游戏功能。这种分模块设计思想,也是以后在工作中设计一个项目的一个中心思想。

三、完整代码展示

1.test.c文件

#define _CRT_SECURE_NO_WARNINGS 1

#include"game.h"
void menu() {
	printf("*************************\n");
	printf("*****开始游戏输入:1*****\n");
	printf("*****结束游戏输入:0*****\n");
	printf("*************************\n");
}

void game() {
	//对棋局进行初始化——用二维数组
	char board[ROW][COL];
	//对棋局进行初始化
	InitBoard(board, ROW, COL);
	//展示棋局,本质是打印二维数组的内容
	DisplayBoard(board, ROW, COL);
	//ret判断谁赢的变量
	char ret = 0;
	//玩家和电脑下棋
	while (1) {
		//玩家下棋
		PlayerMove(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		/*
		ret的值为Q:平局 —— 游戏结束
		ret的值为*:玩家赢 —— 游戏结束
		ret的值为#:电脑赢 —— 游戏结束
		ret的值为C:还没有人赢 —— 游戏继续
		*/
		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() {
	//input 用来接受用户的开始游戏的指令
	int input;
	srand((unsigned int)time(NULL));
	do{
		menu();
		scanf("%d", &input);
		switch (input) {
		case 1:
			game();
			break;
		case 0:
			printf("游戏结束\n");
			break;
		default:
			printf("输入的数据有误,请重新输入!\n");
		}
//input为0是跳出循环,游戏结束;input为1或者非零数时,游戏继续
	} while (input);

	return 0;
}

2.game.h文件

#define _CRT_SECURE_NO_WARNINGS 1
//头文件包含
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
//符号定义
#define ROW 3
#define COL 3
//函数声明
//初始化二维字符数组
void InitBoard(char[][COL], int, int);

//展示棋盘
void DisplayBoard(char[][COL], int, int);

//玩家下棋
void PlayerMove(char[][COL], int, int);

//电脑下棋
void ComputerMove(char[][COL], int, int);

//判断输赢
char IsWin(char[][COL], int, int);

3.game.c文件

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"

//对二维字符数组进行初始化
void InitBoard(char board[ROW][COL], int row, int col) {
	int i, j;
	for (i = 0;i < row;i++) {
		for (j = 0;j < col;j++) {
			board[i][j] = ' ';
		}
	}
}

//展示棋盘
void DisplayBoard(char board[][COL], int row, int col) {
	int i, j;
	for (i = 0;i < row;i++) {
		for (j = 0;j < col;j++) {
			printf(" %c ", board[i][j]);
			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[][COL], int row, int col) {
	//定义一个坐标x,y
	int x = 0, y = 0;
	printf("玩家走>:\n");
	while (1) {
		printf("请输入下棋的坐标>:");
		scanf("%d,%d", &x, &y);
		//判断坐标的合法性
		if (x > 0 && x <= row && y > 0 && y <= col) {
			//下棋,判断判断该坐标是否被占用了
			if (board[x - 1][y - 1] == ' ') {
				board[x - 1][y - 1] = '*';
				break;
			}
			else {
				printf("该坐标已经被占用,请重新输入!\n");
			}
		}
		else {
			printf("输入的坐标不合法,请重新输入!\n");
		}
	}
}

//电脑下棋
void ComputerMove(char board[][COL], int row, int col) {
	printf("电脑走>:\n");
	while (1) {
		int x = rand() % row;
		int y = rand() % col;
		if (board[x][y] == ' ') {
			board[x][y] = '#';
			break;
		}
	}
}
//判断棋局是否为满
int IsFull(char board[][COL], int row, int col) {
	int i, j;
	for (i = 0;i < row;i++) {
		for (j = 0;j < col;j++) {
			if (board[i][j] == ' ')
				return 0;
		}
	}
	return 1;
}

//判断是否赢了
char IsWin(char board[][COL], int row, int col) {
	int i;
	//横向三个连一起为赢
	for (i = 0; i < row; i++) {
		// board[i][1] != ' ' :如果三格都是空的,那也是不行的
		if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ') {
			//电脑赢返回#
			//玩家赢返回*
			return board[i][0];
		}
	}
	//竖向三个连一起为赢
	for (i = 0;i < col; i++) {
		if (board[0][i] == board[1][i] && board[2][i] == board[1][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];
	}
	else if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ') {
		return board[1][1];
	}
	//判断平局
	//判断棋局是否为满(1为满,0为非满)
	if (IsFull(board, row, col) == 1) {
		return 'Q';
	}
	return 'C';
}

 四、游戏效果图

哈哈哈,看到这里不容易哇!第一次写这种游戏代码思路,不足之处,请多多指教。

大家觉得有趣,就点一波关注呗,以后还会继续更新好玩的内容!

  • 9
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木子斤欠木同

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值