小游戏——————三子棋(保姆级教学)

今天我给大家带来一个小游戏,三子棋的简单实现。跟着本篇文章,你也可以做出属于你自己的三子棋。

                                                        游戏的整体思路

1.text.c————用来测试游戏

2.game.c————游戏功能的实现

3.game.h————游戏功能的声明

‘*’代表着玩家下的棋(也表示赢),‘#’代表电脑下的棋(也表示赢),‘Q’表示和棋,‘C’表示继续,

text.c————我们用来测试游戏,我们玩游戏时都会先玩一把,所以我们会选择用do while的循环来解决,当我们第一次进入时,就应该有一个菜单来问我们是否玩游戏,这就用到了我们的menu函数,然后我们可以根据我们选择来选择是否玩游戏。

int main()
{
	int input = 0;

	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;
}

我们定义了一个int类型的临时变量input,然后我们根据input的不同来选择是否进行游戏,当我们选择1时,我们就玩游戏,选择0时就选择退出游戏,如果不是这2个数就重新选择。

  • 这是我们来实现menu函数,我们只需要打印菜单就行,所以我们不需要传参和返回值,直接printf就可以了
void menu()
{
	printf("*************************\n");
	printf("********  1.play  *******\n");
	printf("********  0.exit  *******\n");
	printf("*************************\n");
}

  • 这样一看,我们就完成了菜单的打印。当我们选择1时,我们就进入了switch的选择,进入了game函数。
  • void game()
    {
    	char board[ROW][COL] = { 0 };
    	InitBoard(board, ROW, COL);
    	DisplayBoard(board, ROW, COL);
    	char ret = 0;
    	while (1)
    	{
    		PlayerMove(board, ROW, COL);
    		DisplayBoard(board, ROW, COL);
    		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");
    }

    我们先定义一个3行3列的二维数组,为了我们代码的可读性,我们就可以将行改为ROW,列对应为COL,这是我们就可以在game.h中#define了

  •  game. h

#pragma once

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

#define ROW 3
#define COL 3

game.h中,我们是把库函数都放在了game.h中,然后我们用#define定义了一下ROW ,COL的数,这样当我们想把棋盘改为5x5的时候,只需要改变game.h的值就可以实现所有的改变。

回到text.c中,我们定义完char类型的二维数组,我们就要初始化它,将二维数组全部初始化为‘ ’。  这时我们就需要在game.h中声明一下InitBoard的函数,将我们的二维数组、行、列全部传进去。

 game.h中我们就可以这样声明

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

我们想,把棋盘初始化后,是不是要显示棋盘,我们就要用到我们的DisPlayBoard的函数,目标是实现这个图。

 

 我们发现第一行是由空格和|组成的,我们row是3,然而我们最后一列没有|,我们就可以分别来实现它,而第二行就是___和|组成的,最后一列也是没有|。这时可以实现DisPlayBoard函数了,代码如下。

void DisplayBoard(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++)
		{
			printf(" %c ", board[i][j]);
			if (j <col  - 1)
			{
				printf("|");
			}
		}
		printf("\n");
	
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)//col-1 == 2
					printf("|");
			}
			printf("\n");
	}
}

当然,我们也要在game.h中声明这个函数,当我们实现完显示棋盘的函数,这时我们就可以来实现用户走的函数了,我们可以定义一个PlayerMove的函数,定义一个电脑移动的函数(ComputerMove),我们在game.h中声明一下,然后就可以在game.c中实现了


void PlayerMove(char board[ROW][COL], int row, int col)
{
	int pos_x = 0;
	int pos_y = 0;
	printf("玩家输入:>");
	while (1)
	{
		printf("请输入棋盘坐标\n");
		scanf("%d %d", &pos_x, &pos_y);
		if (pos_x >= 1 && pos_x <= row && pos_y >= 1 && pos_y <= col)
		{
			if (board[pos_x-1][pos_y-1] == ' ')
			{
				board[pos_x-1][pos_y-1] = '*';
				break;
			}
			else
			{
				printf("pos is occupied\n");
			}
		}
		else
		{
			printf("pos is error\n");

		}
	}
}

 我们定义pos_x和pos_y来表示要走的位置,我们落的棋子就必须在棋盘中,这就有了第一个if的判断,第二个if判断中如果落得那个位置是‘ ’,就代表了那个位置没有人下,我们就可以把“*”下在那个位置,然后挑出循环,如果下的位置有人落了,我们就要重新下,循环一下就可以实现了。但请注意,我下的位置是[pos_x-1][pos_y],这是因为我们的数组下标是从0开始的,而用户玩的时候,以为的1行1列就是我们的0行0列,所以我们都要-1,。

void ComputerMove(char board[ROW][COL], int row, int col)
{
	printf("电脑输入:>\n");
	while (1)
	{
		int pos_x = rand() % row;//0-row-1
		int pos_y = rand() % col;//0-col-1
		if (board[pos_x][pos_y] == ' ')
			board[pos_x][pos_y] = '#';
		break;
	}
}

 电脑下的棋子当然要下在棋盘内,所以我们用到了%row,表示着0-row-1的位置,我们要在棋盘内随机落子,我们就要用到rand函数,rand函数就要用到srand函数,我们可以把srand放在main函数中,

	srand(((unsigned int)time(NULL)));

这个代表着时间戳,我们显示生活中的时间都是一直在走的,这样我们就可以实现随机落子了,我们用srand函数中用到了time的类型我们就把它置位空,类型强转为(unsigned int),注意,我们的srand要把它放在while函数之前,不能放在while函数中,我们可以这样理解,如果我们把srand函数放在whlie函数中,我们是不是每次循环的时候,时间都要重新设定一下,这样就不符合我们的定义了。

然后就是我们的IsWin函数了,我们把board,row,col传参传过去,我们要实现IsWin函数,老方法需要我们在game.h中声明一下,在game.c中实现函数

char IsWin(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][1] != ' ')
			return board[i][0];//返回谁赢  '*' '#' 'Q' 'C'
	}
	for (i = 0; i < row; 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[i][i];
	if (board[3][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
		return board[1][1];
	if ((IsFull(board, row, col)) == 1)
		return 'Q';

		return 'C';
}

 我们定义一个int类型的变零i,然后我们用for循环,进入第一个if判断,如果连着3个都相等,而且都不等于‘ ’,我们就可以返回board【i】【0】,代表着谁连3个就谁赢,第二个if判断就是判断列是否相等,第三个和第四个是判断斜对角是否3个连着的。

  • 当棋盘满了的时候,我们就返回了‘Q’,代表着和棋,如果上述三个都不满足,就表示继续下棋。
  • IsFull函数需要我们遍历一下,用for循环,代码如下,
    int IsFull(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;
    		}
    	}
    	//返回为1  if才会进去
    	return 1;
    }

    如果我们的3行3列棋盘都没有‘ ’的时候就代表着满了返回1,如果有一个等于‘ ’,我们就返回0,我们的IsFull函数就根据我们返回值来判断棋盘是否为空。

  •  最后,附上game.c的代码
#define _CRT_SECURE_NO_WARNINGS 1

#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;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < col; j++)
		{
			printf(" %c ", board[i][j]);
			if (j <col  - 1)
			{
				printf("|");
			}
		}
		printf("\n");
	
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)//col-1 == 2
					printf("|");
			}
			printf("\n");
	}
}

void PlayerMove(char board[ROW][COL], int row, int col)
{
	int pos_x = 0;
	int pos_y = 0;
	printf("玩家输入:>");
	while (1)
	{
		printf("请输入棋盘坐标\n");
		scanf("%d %d", &pos_x, &pos_y);
		if (pos_x >= 1 && pos_x <= row && pos_y >= 1 && pos_y <= col)
		{
			if (board[pos_x-1][pos_y-1] == ' ')
			{
				board[pos_x-1][pos_y-1] = '*';
				break;
			}
			else
			{
				printf("pos is occupied\n");
			}
		}
		else
		{
			printf("pos is error\n");

		}
	}
}

int IsFull(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;
		}
	}
	//返回为1  if才会进去
	return 1;
}

void ComputerMove(char board[ROW][COL], int row, int col)
{
	printf("电脑输入:>\n");
	while (1)
	{
		int pos_x = rand() % row;//0-row-1
		int pos_y = rand() % col;//0-col-1
		if (board[pos_x][pos_y] == ' ')
			board[pos_x][pos_y] = '#';
		break;
	}
}

char IsWin(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][1] != ' ')
			return board[i][0];//返回谁赢  '*' '#' 'Q' 'C'
	}
	for (i = 0; i < row; 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[i][i];
	if (board[3][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
		return board[1][1];
	if ((IsFull(board, row, col)) == 1)
		return 'Q';

		return 'C';
}
  • game.h的代码
#pragma once

#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 PlayerMove(char board[ROW][COL], int row, int col);
void ComputerMove(char board[ROW][COL], int row, int col);
char IsWin(char board[ROW][COL], int row, int col);
  • 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 board[ROW][COL] = { 0 };
	InitBoard(board, ROW, COL);
	DisplayBoard(board, ROW, COL);
	char ret = 0;
	while (1)
	{
		PlayerMove(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		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()
{
	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;
}

最后:这样我们就实现了简单的三子棋,当然我们也有问题,当我们的棋盘变成10x10时,我们IsWin的判断就有问题了,我们也只能判断3子棋,如果有兴趣,可以适当改一下代码,让它变成多子棋。 

猜你喜欢

转载自blog.csdn.net/m0_72165281/article/details/130648167
今日推荐