三子棋游戏(保姆式教程)

想必大家都玩过三子棋游戏,就是说两个人在九宫格上面选一个空白部分,将其填上一个自己的符号,当你的符号连续三个连在一起就赢了(可以是: 横三行、竖三列、正对角线、反斜角线)就是如下红色部分相连的 。接下来让我分享下我的思路。(今天的代码分为三个部分,game.h头文件函数的声明存放部分,game.c是游戏的具体实现,test.c是我们的一个游戏的大概逻辑)

目录

🤞1)打印菜单栏

🤞2)定义字符数组和初始化九宫格

🤞3)打印棋盘

🤞3)玩家下棋

🤞4)电脑下棋

🤞5)判断部分

🤞6)game.h的全部代码

🤞7)game.c的全部代码 

🤞8)test.c的全部代码


1)打印菜单栏

菜单栏(menu)的打印方法是跟我写过的上一篇里猜数字游戏是一样的,这里我就再写一遍吧。首先我们都知道进游戏就会有个菜单让你选择玩和不玩游戏,不管三七二十一,kakaka先打印出来菜单,这里我们给两个选择1就是玩游戏,0就是退出游戏。代码如下:

//test.c源文件中的代码
void menu()
{
	printf("**********************************\n");
	printf("************  1.play  ************\n");
	printf("************  0.exit  ************\n");
	printf("**********************************\n");

}

这里之前要先写一个主函数,去调用这个菜单,(因为是不管怎样都要打印一遍,所以用do whiel 循环)代码如下:

//test.c源文件中的代码
int main()
{

	do
	{
		menu();   //菜单栏打印

	} while ();
	return 0;
}

调用完菜单之后我们就要选择这两个,既然要选择 ,我们就要输入,我们定义一个变量为 input 代码如下:

//test.c源文件中的代码
int main()
{
	int input = 0;
	
	do
	{
		menu();

		printf("请选择:>");

		scanf("%d", &input);

	} while ();
	return 0;
}

选择完之后我们就要接收进来,根据选择的数字来做出相应的事情,这里就用到switch(),case语句实现,代码如下:

//test.c源文件中的代码
int main()
{
	int input = 0;
	
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1 :
			game();   //选择1,就玩游戏,所以这里提供一个实现游戏代码的函数
			break;
		case 0 :
			printf("退出游戏成功\n");
			break;
		default :
			printf("选择错误,请重新选择>\n");
			break;
		}
	} while (input); //根据输入0和1去判断循不循环
	return 0;
}

接下来就是具体实现游戏的代码,首先下棋,我们知道要有一个九宫格棋盘(这里只说三子棋的棋盘),棋盘上不能有任何一个字符(棋盘初始化部分),有了棋盘就是我们在棋盘中填入我们的专属字符,所以要定义一个字符数组,然后就是玩家下棋,然后电脑下棋,然后判断部分,到底是谁赢或着是平局,或者还没下完,然后继续玩游戏。所以先来定义字符数组和初始化九宫格

2)定义字符数组和初始化九宫格

//test.c源文件中的代码
void game()
{
	
	char board[ROW][COL] = { 0 };  //这里代码还是在test.c中
	InitBoard(board,ROW,COL);  //ROW,COL分别表示行和列(定义在头文件)
                               //这样可以让我们随心所欲的设置棋盘的行和列

}
//game.h头文件中的代码:

#define ROW 3
#define COL 3

//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col);

初始化是将九宫格中全是空格部分即代码如下:

//game.c源文件中的代码
void InitBoard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < col; j++)
		{
			board[i][j] = ' ';  //这里容易写成双引号,注意这里是单引号,字符形式
		}
	}
}

3)打印棋盘

首先要知棋盘的样子(一下图片是我们假设的棋盘样式),可看出一行的部分有九个减号,一列有三个竖杠,我们可以看到空格部分有三个,我们可以把我们要输入的字符放在中间,即就有一个空格一个字符一个空格一个竖杠,可以组成一个部分循环打印它,但注意这里只有两个竖杠,所以给条件要控制竖杠的打印,接下来就是打印横着的三个杠,只有两行所以也要个条件控制行部分的打印。

 代码如下:

//test.c源文件中的代码:
void game()
{
	char board[ROW][COL] = { 0 };

	InitBoard(board,ROW,COL);

	DisplayBoard(board, ROW, COL); //打印棋盘
}

//game.h头文件中的代码

#define ROW 3
#define COL 3

//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col);
//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col);
//game.c源文件中的代码

void DisplayBoard(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++)
		{
			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");
		}
	}
}

3)玩家下棋

玩家下棋,玩家我们知道玩家不像我们的程序员,并不知道我们的行和列是由0开始的,所以定义下标时要注意,我们先定义两个变量,我们知道玩家不可能一把只能走一步,所以我们要写一个循环,这里注意,玩家在下坐标时只能有1-3的数字,所以你的坐标元素必须满足这个区间才行,不满足即是非法坐标,提示一下,满足了我们的区间,我们就又要判断那个坐标是否被下过了,没下过才能落子,下过了,就提示一句该坐标已被占用。

代码如下:

//test.c源文件中的代码

void game()
{
	char ret = 0;
	char board[ROW][COL] = { 0 };
	InitBoard(board,ROW,COL);
	DisplayBoard(board, ROW, COL);
	while (1)
	{
		PlayerBoard(board, ROW, COL);
		DisplayBoard(board, ROW, COL);  //下完棋就要打印一次棋盘,这样才能看见棋子落在哪里
	}
	

//game.h头文件中的代码

#define ROW 3
#define COL 3

//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col);
//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col);
//玩家下棋
void PlayerBoard(char board[ROW][COL], int row, int col);
//game.c源文件中的代码

void PlayerBoard(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	while (1)
	{
		printf("玩家请下棋:>");
		scanf("%d%d", &x, &y);
		if (x >= 1 && x <= 3 && y >= 1 && y <= 3)
		{
			if (board[x - 1][y - 1] == ' ')
			{
				board[x - 1][y - 1] = '*';   //我们定义*为玩家的棋子
				break;
			}
			else
			{
				printf("该坐标已被占用,请重新输入\n");
			}
		}
		else
		{
			printf("非法坐标,请重新输入\n");
		}
	}
}

4)电脑下棋

电脑下棋的方式就比较简单,我们可以随机生成的坐标在区间范围内,随机生成数字的方式我已经在上一篇猜数字游戏中讲过了,这里就不讲了,电脑落子也要落在空格处,所以就找空格部分落

代码如下:

//test.c源文件中的代码

void game()
{
	char ret = 0;
	char board[ROW][COL] = { 0 };
	InitBoard(board,ROW,COL);
	DisplayBoard(board, ROW, COL);
	while (1)
	{
		PlayerBoard(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
	
		ComputerBoard(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
    }
	

}
//game.h头文件中的代码

#define ROW 3
#define COL 3

//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col);
//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col);
//玩家下棋
void PlayerBoard(char board[ROW][COL], int row, int col);
//电脑下棋
void ComputerBoard(char board[ROW][COL], int row, int col);

//game.c源文件中的代码

void ComputerBoard(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;

	while (1)
	{
		printf("电脑下棋:>\n");
		x = rand() % row;
		y = rand() % col;
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';   //规定#为电脑下的棋子
			break;
		}
	}
}

5)判断部分

有四种情况就是玩家赢,电脑赢,平局,继续游戏,我们可以有一个返回值,根据返回值来判读,比如,玩家赢我们就返回’*‘,电脑赢我们就返回’#‘,平局就返回’Q‘,还要继续游戏就根据'C'来判断

//test.c源文件中的代码

void game()
{
	char ret = 0;
	char board[ROW][COL] = { 0 };
	InitBoard(board,ROW,COL);
	DisplayBoard(board, ROW, COL);
	while (1)
	{
		PlayerBoard(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		ret = is_win(board, ROW, COL);
		if (ret != 'C')             //如果等于C了,说明还可以继续玩游戏,不等于了就退出循环
		{
			break;
		}
		ComputerBoard(board, ROW, COL);
		DisplayBoard(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");
	}
}

//game.h头文件中的代码

#define ROW 3
#define COL 3

//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col);
//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col);
//玩家下棋
void PlayerBoard(char board[ROW][COL], int row, int col);
//电脑下棋
void ComputerBoard(char board[ROW][COL], int row, int col);

//判断输赢的情况
//玩家赢  就返回  '*'
//电脑赢  就返回  '#'
//平局    就返回  'Q'
//继续玩  就返回  'C'
char is_win(char board[ROW][COL], int row, int col);
//game.c源文件中的代码

int is_full(char board[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 (board[i][j] == ' ')
			{
				return 0;
			}
		}
	}
	return 1;
}

char is_win(char board[ROW][COL], int row, int col)
{
	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 (1 == is_full(board, ROW, COL))
	{
		return 'Q';           //返回Q说明棋盘已经满了,并且没人输赢,即平局
	}
	else
	{
		return 'C';           //返回C说明棋盘没有满,游戏继续
	}
}

6)game.h的全部代码

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

#define ROW 3
#define COL 3

//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col);
//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col);
//玩家下棋
void PlayerBoard(char board[ROW][COL], int row, int col);
//电脑下棋
void ComputerBoard(char board[ROW][COL], int row, int col);

//判断输赢的情况
//玩家赢  就返回  '*'
//电脑赢  就返回  '#'
//平局    就返回  'Q'
//继续玩  就返回  'C'
char is_win(char board[ROW][COL], int row, int col);

7)game.c的全部代码 

#include "game.h"

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

void DisplayBoard(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++)
		{
			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 PlayerBoard(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	while (1)
	{
		printf("玩家请下棋:>");
		scanf("%d%d", &x, &y);
		if (x >= 1 && x <= 3 && y >= 1 && y <= 3)
		{
			if (board[x - 1][y - 1] == ' ')
			{
				board[x - 1][y - 1] = '*';
				break;
			}
			else
			{
				printf("该坐标已被占用,请重新输入\n");
			}
		}
		else
		{
			printf("非法坐标,请重新输入\n");
		}
	}
}
void ComputerBoard(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;

	while (1)
	{
		printf("电脑下棋:>\n");
		x = rand() % row;
		y = rand() % col;
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
}


 // 返回 1 表示棋盘满了
 // 返回 0 表示棋盘没满
int is_full(char board[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 (board[i][j] == ' ')
			{
				return 0;
			}
		}
	}
	return 1;
}

char is_win(char board[ROW][COL], int row, int col)
{
	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 (1 == is_full(board, ROW, COL))
	{
		return 'Q';           //返回Q说明棋盘已经满了,并且没人输赢,即平局
	}
	else
	{
		return 'C';           //返回C说明棋盘没有满,游戏继续
	}
}

8)test.c的全部代码

#include "game.h"
void menu()
{
	printf("**********************************\n");
	printf("************  1.play  ************\n");
	printf("************  0.exit  ************\n");
	printf("**********************************\n");

}
void game()
{
	char ret = 0;
	char board[ROW][COL] = { 0 };
	InitBoard(board,ROW,COL);
	DisplayBoard(board, ROW, COL);
	while (1)
	{
		PlayerBoard(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		ret = is_win(board, ROW, COL);
		if (ret != 'C')
		{
			break;
		}
		ComputerBoard(board, ROW, COL);
		DisplayBoard(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 = 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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值