【C语言】保姆级三子棋教程

①前言

三子棋,民间传统游戏,又叫九宫棋、圈圈叉叉、一条龙等。将正方形对角线连起来,相对两边依次摆上三个双方棋子,只要将自己的三个棋子走成一条线,对方就算输了。如果两个人都掌握了技巧,那么一般来说就是平棋。它最大的好处就是随便找个地方就可以玩这个简单而有趣的游戏了。
在这里插入图片描述

已知三子棋的规则后,我们该如何用C语言实现呢?接着往下看看吧!

②游戏实现步骤

1.创建菜单界面,输入1或0来控制“开始游戏”或是“结束游戏”
2.棋盘初始化
3.打印棋盘
4.玩家下棋,判断是否需要继续下棋(返回*表示玩家赢,Q表示平局,C表示继续下棋)
5.电脑下棋,判断是否需要继续下棋(返回#表示电脑赢,Q和C同上)

1.menu菜单界面

菜单界面就像餐厅里服务员递给你的菜单,根据菜单里的内容进行选择
选择1,开始游戏;选择0,结束游戏

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

2.实现多子棋

如果只想让程序实现三子棋的功能,下图board数组中的行和列均用3即可
但是如果想实现多子棋,例如五子棋,仅仅改变下图行和列的3显然是不够的

	char board[3][3] = {
    
     0 };

因此,不妨用 #define宏定义

#define ROW 3
#define COL 3

好处: 方便程序的修改,若想改变ROW和COL的值,只需要在#define宏定义中将ROW和COL的值修改,无需全文查找修改

3.初始化棋盘

使得数组最开始存放的全为空格,为稍后的打印棋盘做准备

void Initiate_board(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] = ' ';
}

4.打印棋盘

打印3*3的棋盘,需要打印5行(除了3行存储的数组外,还需两行间隔行,用—|—|—充当),打印5列(3列存储的数组外,还需两列间隔列,用 | 间隔)

在这里插入图片描述

先打印列,将上图的3,4看成一组,分隔列的列数=COL-1

for (j = 0; j < col; j++)
		{
    
    
			printf(" %c ", board[i][j]);//%c两边有空格,更美观
			if (j < col - 1)
				printf("|");
		}

打印行时,将1,2看成一组,分割行的行数=ROW-1

打印棋盘的完整代码

void Display_board(char board[ROW][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");
	}
}

5.玩家下棋

站在玩家的角度,棋盘的行列从1开始
因此,横表标x满足 1<=x<=row, 纵坐标y满足 1<=y<=col
但从数组的角度,行列从0开始
所以在代码实现中要将输入的行和列的值都减去1

注意:
若输入的坐标不满足上述条件或者输入的坐标已被占用会被提示并要重新输入

void Player_move(char board[ROW][COL], int row, int col)
{
    
    
	int x, y;
	printf("玩家下:\n");
	while (1)
	{
    
    
		printf("请选择要下的位置:");
		scanf("%d%d", &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");
	}
}

6.电脑下棋

1.电脑下棋不需要我们手动输入,而是在合理范围内随机生成一个坐标(当然,您也可以写算法让聪明的电脑陪您玩)
2.为了生成一个随机坐标,我们需要两个随机值,随机值可由rand()函数生成
3.为了使用rand()函数,要在主函数中使用srand((unsighed int)time(NULL))
            注意:srand()函数只需调用一次

void Computer_move(char board[ROW][COL], int row, int col)
{
    
    
	int x, y;
	while (1)
	{
    
    
		x = rand() % row;
		y = rand() % col;
		if (board[x][y] == ' ')
		{
    
    
			board[x][y] = '#';
			break;
		}
	}

}

7.判断输赢

玩家赢---- *
电脑赢---- #
平   局---- Q
继   续---- C
注意:因为返回值为字符,所以要用char来接收

char Is_win(char board[ROW][COL], int row, int col)
{
    
    
	int i;
	//赢
	for (i = 0; i < row; i++)
	{
    
    
		//三横行
		if (board[i][0] == board[i][1] && board[i][0] == board[i][2] && board[i][0] != ' ')
			return board[i][0];
		//三竖列
		if (board[0][i] == board[1][i] && board[0][i] == board[2][i] && board[0][i] != ' ')
			return board[0][i];
	}

	//正对角线
	if (board[0][0] == board[1][1] && board[0][0] == board[2][2] && board[1][1] != ' ')
		return board[1][1];
	//反对角线
	if (board[2][0] == board[1][1] && board[2][0] == board[0][2] && board[1][1] != ' ')
		return board[1][1];

	//平局
	if (Is_full(board, ROW, COL))
		return 'Q';

	//继续
	return 'C';

}

8.Is full函数实现

判断棋盘是否满了,因为返回值为1或0,所以要用int来接收
如果还有空格(即未满),返回0;
满了,返回1

int Is_full(char board[ROW][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;
}

③结果演示

1.玩家赢

在这里插入图片描述

2.电脑赢

在这里插入图片描述

3.平局

在这里插入图片描述

④模块化代码实现

1.text.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"game.h"

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

void game()
{
    
    
	char ret;
	char board[ROW][COL] = {
    
     0 };
	//棋盘初始化
	Initiate_board(board, ROW, COL);
	//打印棋盘
	Display_board(board, ROW, COL);
	//下棋
	while (1)
	{
    
    
		//玩家下棋
		Player_move(board, ROW, COL);
		Display_board(board, ROW, COL);
		ret = Is_win(board, ROW, COL);
		if (ret != 'C')
			break;
		//电脑下
		Computer_move(board, ROW, COL);
		Display_board(board, ROW, COL);
		ret = Is_win(board, ROW, COL);
		if (ret != 'C')
			break;
	}
	if (ret == '*')
		printf("玩家赢\n");
	else if (ret == '#')
		printf("电脑赢\n");
	else
		printf("平局\n");


}

int main()
{
    
    
	int input;
	srand(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;
}

2.game.h

#pragma once

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

#define ROW 3
#define COL 3

//棋盘初始化
void Initiate_board(char board[ROW][COL], int row, int col);
//打印棋盘
void Display_board(char board[ROW][COL], int row, int col);
//玩家下棋
void Player_move(char board[ROW][COL], int row, int col);
//电脑下
void Computer_move(char board[ROW][COL], int row, int col);
//判断输赢
char Is_win(char board[ROW][COL], int row, int col);

3.game.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"game.h"

void Initiate_board(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 Display_board(char board[ROW][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 Player_move(char board[ROW][COL], int row, int col)
{
    
    
	int x, y;
	printf("玩家下:\n");
	while (1)
	{
    
    
		printf("请选择要下的位置:");
		scanf("%d%d", &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 Computer_move(char board[ROW][COL], int row, int col)
{
    
    
	int x, y;
	while (1)
	{
    
    
		x = rand() % row;
		y = rand() % col;
		if (board[x][y] == ' ')
		{
    
    
			board[x][y] = '#';
			break;
		}
	}

}


int Is_full(char board[ROW][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;
}

//玩家赢:*
//电脑赢:#
//平局:  Q
//继续:  C
char Is_win(char board[ROW][COL], int row, int col)
{
    
    
	int i;
	//赢
	for (i = 0; i < row; i++)
	{
    
    
		//三横行
		if (board[i][0] == board[i][1] && board[i][0] == board[i][2] && board[i][0] != ' ')
			return board[i][0];
		//三竖列
		if (board[0][i] == board[1][i] && board[0][i] == board[2][i] && board[0][i] != ' ')
			return board[0][i];
	}

	//正对角线
	if (board[0][0] == board[1][1] && board[0][0] == board[2][2] && board[1][1] != ' ')
		return board[1][1];
	//反对角线
	if (board[2][0] == board[1][1] && board[2][0] == board[0][2] && board[1][1] != ' ')
		return board[1][1];

	//平局
	if (Is_full(board, ROW, COL))
		return 'Q';

	//继续
	return 'C';

}

猜你喜欢

转载自blog.csdn.net/qq_75000174/article/details/132008363