C语言三子棋实现

C语言三子棋实现

今天我们来完成一个小案例,编写三子棋游戏。本文将会讲解三子棋的实现过程。

集成开发环境:vs2019

C语言三子棋实现_第1张图片

1.功能模块分析

 三子棋就是在3*3的格子中,填入○或者×,看行或列或斜对角是否是一样的图形,就判定为赢。
 要完成这样一个程序,我们会在vs2019中,使用到一个头文件,一个测试文件,一个函数功能实现文件。下图game.h是头文件,game.c是游戏函数的实现文件,test.c是测试文件。
C语言三子棋实现_第2张图片

首先我们先搭建初始框架,将菜单栏先完成。

1.菜单栏模块

这里菜单栏模块比较简单,是通过用户输入相应数字来执行游戏的对应流程。通过switch流程分支,和输入的input来判断当前程序的状态。

int main(){
	int input = 0;
	int main(){
	int input = 0;
	srand((unsigned int)time(NULL));
	do {
		menu();
		printf("请输入选项:\n");
		scanf("%d", &input);
		switch (input)
		{
			case 1:
				game();
				break;
			case 0:
				printf("退出游戏\n");
				break;
			default:
				printf("输入有误,请重新输入\n");
				break;
		}
	} while(input);
	return 0;
}
	
	
	} while(input);
	return 0;
}

2.初始化棋盘和打印棋盘

 在输入数字后,就要加载棋盘到控制台。
 初始化棋盘我们需要用到二维数组,为了之后能够修改棋盘行和列的大小,这里没有把数字写死,而是通过在头文件定义的方式,让我们能够修改数字得到我们想要的棋盘大小。
在这里插入图片描述

 这里是3 * 3的棋盘,后续如果用户想要n * n的棋盘也可以修改。
 初始化棋盘我们要遍历数组,把数组内容重置为空格。
C语言三子棋实现_第3张图片

//初始化棋盘如下

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

 重置好棋盘后,需要显示棋盘,这里以3*3的棋盘为例,我们把棋盘分别打印,先打印数据和竖线(|),如下图红圈圈出来的样子。我们先以一行为例,遍历数组先打印数据,然后打印竖线,保持一个数据一个竖线的样子,当然最后一个竖线不需要打印。
C语言三子棋实现_第4张图片

//这里的代码就是控制一行数据一行竖线的打印,整一行打印完后换行。
int i = 0;
	for (i = 0; i < row; i++) {
		int j = 0;
		for (j = 0; j < col; j++) {
			printf(" %c ", arr[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");
	}
}

C语言三子棋实现_第5张图片

//棋盘打印代码如下

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

3.下棋模块

棋盘初始化好之后,之后就要下棋,下棋分为玩家下棋和电脑下棋。
下棋就要判断两个条件:1.下棋的坐标是否合理 2.棋子下到的地方是不是空的
 我们使用的是二维数组,数组下标是从0开始的,而用户并不知道这个规则,所以我们需要在用户输入的坐标基础上减去1,坐标的输入需要大于1并且在行列范围以内,输入后判断数组是否为空。

	if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (arr[x - 1][y - 1] == ' ')
			{
				arr[x - 1][y - 1] = '*';
				break;
			}
			else
			{
				printf("该坐标被占用,请重新输入\n");
			}
		}
		else
		{
			printf("坐标非法,重新输入\n");
		}

电脑下棋,我们采用取模的方式让坐标限制在0-2之间,这样输入的坐标就不会越界

	 	int x = rand() % row;
		int y = rand() % col;
		if (arr[x][y] == ' ')
		{
			arr[x][y] = '#';
			break;
		}

4.判断胜负模块

 上面的工作都完成后,我们可以在棋盘下棋,但还需要一个判断胜负的模块,不然格子都下满了,只能死循环了。
在玩家下棋和电脑下棋之间需要一个函数来判断胜负,我们可以定一个规则:
‘ * ’是玩家赢
‘ # ’是电脑赢
‘Q’ 是平局
‘C’ 是继续游戏

while (1)
	{
		ret = is_win(arr, ROW, COL);
		if (ret != 'C')
			break;   //如果ret不等于C就会跳出循环,这时候只会有输赢和平局三种结果

		computer_move(arr, ROW, COL);
		dis_arr(arr, ROW, COL);

		ret = is_win(arr, ROW, COL);
		if (ret != 'C')
			break;   //如果ret不等于C就会跳出循环,这时候只会有输赢和平局三种结果
 
	}
	if (ret == '*')
	{
		printf("玩家赢\n");
	}
	else if (ret == '#')
	{
		printf("电脑赢\n");
	}
	else if (ret == 'Q')
	{
		printf("平局\n");
	}
}
//让ret返回当前胜负状态
char ret = is_win(arr, ROW, COL);
char is_win(char arr[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		if (arr[i][0] == arr[i][1] && arr[i][1] == arr[i][2] && arr[i][0] != ' ')  //判断一行是否相等
		{
			return arr[i][0];
		}
	}

	for (i = 0; i < col; i++)
	{ 
		if (arr[0][i] == arr[1][i] && arr[1][i] == arr[2][i] && arr[0][i] != ' ')  //判断一列是否相等
		{
			return arr[0][i];
		}
	}

	if (arr[0][0] == arr[1][1] && arr[1][1] == arr[2][2] && arr[1][1] != ' ') //判断斜对角是否相等
	{
		return arr[1][1];
	}

	if (arr[0][2] == arr[1][1] && arr[1][1] == arr[2][0] && arr[1][1] != ' ') //判断斜对角是否相等
	{
		return arr[1][1];
	}

	//判断平局
	if (is_full(arr, row, col) == 1)
	{
		return 'Q';
	}

	//继续
	return 'C';
}

完整代码:

//game.h

	#define _CRT_SECURE_NO_WARNINGS 1
	#define ROW 3
	#define COL 3
	#include
	//初始化棋盘
	void init_board(char arr[ROW][COL], int row, int col);  
	//玩家移动棋子
	void player_move(char arr[ROW][COL], int row, int col);
	//棋盘展示
	void dis_board(char arr[ROW][COL], int row, int col);
	//电脑移动棋子
	void computer_move(char arr[ROW][COL], int row, int col);
	//判断游戏状态
	char is_win(char board[ROW][COL], int row, int col);
//game.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void init_arr(char arr[ROW][COL], int row, int col) {
	int i, j;
	for (i = 0; i < row; i++) {
		for (j = 0; j < col; j++) {
			arr[i][j] = ' ';
		}
	}
}

void dis_arr(char arr[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++) {
		int j = 0;
		for (j = 0; j < col; j++) {
			printf(" %c ", arr[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 player_move(char arr[ROW][COL],int row,int col) {
	int x = 0;
	int y = 0;
	printf("玩家下棋\n");
	while (1)
	{
		printf("请输入要下棋的坐标:>");
		scanf("%d %d", &x, &y);
		//1.坐标的合法性
		//2.坐标是否被占用
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (arr[x - 1][y - 1] == ' ')
			{
				arr[x - 1][y - 1] = '*';
				break;
			}
			else
			{
				printf("该坐标被占用,请重新输入\n");
			}
		}
		else
		{
			printf("坐标非法,重新输入\n");
		}
	}
}

void computer_move(char arr[ROW][COL], int row, int col) {
	printf("电脑下棋\n");
	while (1) {
		int x = rand() % row;
		int y = rand() % col;
		if (arr[x][y] == ' ')
		{
			arr[x][y] = '#';
			break;
		}
	
	}



}
static int is_full(char arr[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < col; j++)
		{
			if (' ' == arr[i][j])
			{
				return 0;
			}
		}
	}

	return 1;
}

char is_win(char arr[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		if (arr[i][0] == arr[i][1] && arr[i][1] == arr[i][2] && arr[i][0] != ' ')
		{
			return arr[i][0];
		}
	}

	for (i = 0; i < col; i++)
	{
		if (arr[0][i] == arr[1][i] && arr[1][i] == arr[2][i] && arr[0][i] != ' ')
		{
			return arr[0][i];
		}
	}

	if (arr[0][0] == arr[1][1] && arr[1][1] == arr[2][2] && arr[1][1] != ' ')
	{
		return arr[1][1];
	}

	if (arr[0][2] == arr[1][1] && arr[1][1] == arr[2][0] && arr[1][1] != ' ')
	{
		return arr[1][1];
	}

	//判断平局
	if (is_full(arr, row, col) == 1)
	{
		return 'Q';
	}

	//继续
	return 'C';
}

//test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include
#include "game.h"
void menu() {
	printf("*********三子棋游戏********\n");
	printf("*********1.开始游戏******\n");
	printf("*********0.退出游戏******\n");

}
void game()
{
	printf("游戏开始\n");
	char ret = 0;
	//数据的存储需要一个3*3的二维数组
	char arr[ROW][COL] = { 0 };
	init_arr(arr, ROW, COL);
	dis_arr(arr, ROW, COL);
	//玩游戏
	while (1)
	{
		player_move(arr, ROW, COL);
		dis_arr(arr, ROW, COL);

		ret = is_win(arr, ROW, COL);
		if (ret != 'C')
			break;

		computer_move(arr, ROW, COL);
		dis_arr(arr, ROW, COL);

		ret = is_win(arr, ROW, COL);
		if (ret != 'C')
			break;

	}
	if (ret == '*')
	{
		printf("玩家赢\n");
	}
	else if (ret == '#')
	{
		printf("电脑赢\n");
	}
	else if (ret == 'Q')
	{
		printf("平局\n");
	}
	dis_arr(arr, ROW, COL);

}


int main(){
	int input = 0;
	srand((unsigned int)time(NULL));
	do {
		menu();
		printf("请输入选项:\n");
		scanf("%d", &input);
		switch (input)
		{
			case 1:
				game();
				break;
			case 0:
				printf("退出游戏\n");
				break;
			default:
				printf("输入有误,请重新输入\n");
				break;
		}
	
	} while(input);


	return 0;
}

2.运行效果

C语言三子棋实现_第6张图片
C语言三子棋实现_第7张图片
C语言三子棋实现_第8张图片
C语言三子棋实现_第9张图片

你可能感兴趣的:(C语言,c语言,c++,开发语言)