三子棋(井字棋)游戏-C语言超详细解析!(附源代码)

一、开始写游戏之前,我们要注意:

(这样写便于修改,提高代码可读性)

  1. 首先是自己最先创建,包含主函数的.c文件,例如在此游戏中是test.c。
  2. 我们通常会新建一个头文件,例如此游戏新建game.h,此头文件通常用来完成函数声明、头文件的引用、宏定义变量。
  3. 新建一个.c文件,例如在此游戏新建game.c,编写涉及到的功能函数实现。

二、思路

  1. 我们可以先编写让玩家进行输入(决定是否进行游戏,例如:进行输入1,不进行输入0,(这里运用switch语句进行判断选择))。
  2. 如果用户输入1,则我们进入游戏。
  3. 我们都知道三子棋游戏是需要玩家输入(下棋),接着是电脑自动输入(下棋),(或者电脑先下,玩家后下,这里我们设置的是玩家先下)那么我们下棋之前每一个格子里面肯定都是空的。
  4. 所以,进入游戏之后的第一步,我们要初始化棋盘,并且将其打印出来,这样我们可以清楚的看到棋盘的样子。
  5. 接着我们定义函数让玩家进行输入。
  6. 打印棋盘(这样可以清楚地看到玩家输入之后棋盘的样子)。
  7. 接着定义函数让电脑进行输入。
  8. 打印棋盘(这样可以清楚地看到电脑输入之后棋盘的样子)
  9. 如果这样打印,那么我们会发现一个问题,那就是当棋盘下满之后,还是继续的状态。这个时候我们就知道我们需要判断是电脑赢还是玩家赢或者是平局。
  10. 然后在玩家输入并且打印棋盘之后我们就需要定义一个判断输赢的函数去判断(因为一直处于玩家输完电脑输入的状态,随时有可能玩家赢)。
  11. 同理,在电脑输入并且打印棋盘之后,我们需要用定义输赢的那个函数去判断。

简单来说,步骤如下:

  1. 棋盘的初始化;
  2. 打印棋盘;
  3. 玩家下棋;
  4. 打印玩家下了之后的棋盘;
  5. 判断输赢;
  6. 电脑下棋;
  7. 打印电脑下了之后的棋盘;
  8. 判断输赢。

三、详细步骤

1、菜单界面

定义一个菜单函数,放到main()函数中。其中 1 表示 游戏开始(进入游戏),0表示不玩游戏(退出游戏)。(其中srand()是随机数发生器的初始化函数,在电脑自动输入时候会用到;并且御用switch语句来判断)

void menu()
{
	printf("------------------------------\n");
	printf("-----------请输入:-----------\n");
	printf("------游戏开始(输入1):-----\n");
	printf("------不玩游戏(输入0):-----\n");
	printf("------------------------------\n");
}
int main()
{
	int a;
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		printf("请输入:\n");
		scanf("%d", &a);
		switch (a)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	}while (a);
	return 0;
}

2、创建棋盘

定义函数game(),在其中创建棋盘。使用3行3列的二维数组来表示,元素类型是char。

 接着新建game.h,此头文件通常用来完成函数声明、头文件的引用、宏定义变量。在其中定义行和列的大小(这个例子是三行三列):

 【注意】#pragma once是保证无论头文件被引用多少次,都只读取一次。

3、棋盘初始化

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

 4、打印棋盘

void Playboard(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.玩家落子需要在棋盘范围内。
2.玩家要在棋盘上空的地方落子。
3.如果输入的坐标不满足要重新输入。

void Playmove(char board[ROW][COL], int row, int col)
{
	printf("玩家走\n");
	int x, y;
	while (1)
	{
		scanf("%d %d", &x, &y);//输入要走的坐标
		if (x >= 1 && x <= row && y >= 1 && y <= row)
		{
			if (board[x - 1][y - 1] == ' ')
			{
				board[x - 1][y - 1] = '*';
				break;
			}
			else
			{
				printf("坐标被占用\n");
			}
		}
		else
		{
			printf("非法坐标\n");
		}
	}

}

6、电脑下棋

【注意】
1.要在主函数中使用srand((unsigned int)time(0)),将时间作为随机数种子,确保得到的行列坐标是真随机。
2.要在棋盘上空的地方下棋。

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

7、判断输赢

调用Iswin()函数,此处约定返回结果的含义:

  1. ‘*’ 表示玩家获胜
  2. ‘#’ 表示电脑获胜
  3. ’ p’ 表示平局
  4.  'c'表示对局继续

我们要判断的方面:

  1. 判定所有的行
  2. 判定所有的列
  3. 判定两条对角线

第一种:

【注意】:

箭头指向的代码不要放在判断在 一行/列 电脑或者玩家是否赢 的else if后面(如下):

 因为如果放在此处,只要打印的棋盘里面有一处是空,那么即使一行/列都是*或#,也不会显示玩家/电脑赢。

char Iswin(char board[ROW][COL], int row, int col)
{
	int i, j;
	for (i = 0; i < row; i++)//行
	{
		if ((board[i][0] == '*') && (board[i][1] == '*') && (board[i][2] == '*'))
		{
			return '*';//玩家获胜
		}
		else if ((board[i][0] == '#') && (board[i][1] == '#') && (board[i][2] == '#'))
		{
			return '#';//电脑获胜
		}
	}
	for (i = 0; i < col; i++)//列
	{
		if ((board[0][i] == '*') && (board[1][i] == '*') && (board[2][i] == '*'))
		{
			return '*';
		}
		else if ((board[0][i] == '#') && (board[1][i] == '#') && (board[2][i] == '#'))
		{
			return '#';
		}
	}
	//对角线
	if (((board[0][0] == '*') && (board[1][1] == '*') && (board[2][2] == '*')) || ((board[0][2] == '*') && (board[1][1] == '*') && (board[2][0] == '*')))
		return '*';
	else if (((board[0][0] == '#') && (board[1][1] == '#') && (board[2][2] == '#')) || ((board[0][2] == '#') && (board[1][1] == '#') && (board[2][0] == '#')))
		return '#';
	else
	{
		for (i = 0; i < row; i++)
		{
			for (j = 0; j < col; j++)
			{
				if (board[i][j] == ' ')
					return 'c';
			}
		}
		return 'p';
	}
}

第二种:

int IsFull(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;
}
char Iswin(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][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 (IsFull(board, row, col))
	{
		return 'p';
	}
	return 'c';
}

四、代码

game.h头文件:

#pragma once

#define ROW 3
#define COL 3
#include <stdio.h>
#include "game.h"
#include <time.h>
#include <stdlib.h>

void Initboard(char board[ROW][COL],int row ,int col);//初始化空格
void Playboard(char board[ROW][COL],int row, int col);//打印棋盘
void Playmove(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);//假设玩家赢了 返回* 电脑赢了 返回# 平局 返回 p 都没赢 c

game.c源文件:

#define _CRT_SECURE_NO_WARNINGS
#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 Playboard(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 Playmove(char board[ROW][COL], int row, int col)
{
	printf("玩家走\n");
	int x, y;
	while (1)
	{
		scanf("%d %d", &x, &y);//输入要走的坐标
		if (x >= 1 && x <= row && y >= 1 && y <= row)
		{
			if (board[x - 1][y - 1] == ' ')
			{
				board[x - 1][y - 1] = '*';
				break;
			}
			else
			{
				printf("坐标被占用\n");
			}
		}
		else
		{
			printf("非法坐标\n");
		}
	}

}
void Computermove(char board[ROW][COL], int row, int col)
{
	printf("电脑走\n");
	int x, y;
	while (1)
	{
		x = rand() % row;
		y = rand() % col;
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
}
char Iswin(char board[ROW][COL], int row, int col)
{
	int i, j;
	for (i = 0; i < row; i++)//行
	{
		if ((board[i][0] == '*') && (board[i][1] == '*') && (board[i][2] == '*'))
		{
			return '*';//玩家获胜
		}
		else if ((board[i][0] == '#') && (board[i][1] == '#') && (board[i][2] == '#'))
		{
			return '#';//电脑获胜
		}
	}
	for (i = 0; i < col; i++)//列
	{
		if ((board[0][i] == '*') && (board[1][i] == '*') && (board[2][i] == '*'))
		{
			return '*';
		}
		else if ((board[0][i] == '#') && (board[1][i] == '#') && (board[2][i] == '#'))
		{
			return '#';
		}
	}
	//对角线
	if (((board[0][0] == '*') && (board[1][1] == '*') && (board[2][2] == '*')) || ((board[0][2] == '*') && (board[1][1] == '*') && (board[2][0] == '*')))
		return '*';
	else if (((board[0][0] == '#') && (board[1][1] == '#') && (board[2][2] == '#')) || ((board[0][2] == '#') && (board[1][1] == '#') && (board[2][0] == '#')))
		return '#';
	else
	{
		for (i = 0; i < row; i++)
		{
			for (j = 0; j < col; j++)
			{
				if (board[i][j] == ' ')
					return 'c';
			}
		}
		return 'p';
	}
}

test.c源文件:

//三子棋游戏
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"

void menu()
{
	printf("------------------------------\n");
	printf("-----------请输入:-----------\n");
	printf("------游戏开始(输入1):-----\n");
	printf("------不玩游戏(输入0):-----\n");
	printf("------------------------------\n");
}
void game()
{
	//三子棋
	char board[ROW][COL];//棋盘数组
	Initboard(board, ROW, COL);	//初始化棋盘
	Playboard(board, ROW, COL);//打印棋盘
	char ret;
	while (1)
	{
		Playmove(board, ROW, COL);//人走
		Playboard(board, ROW, COL);//打印棋盘
		ret = Iswin(board, ROW, COL);
		if (ret != 'c')
		{
			break;
		}
		Computermove(board, ROW, COL);//电脑走
		Playboard(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 a;
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		printf("请输入:\n");
		scanf("%d", &a);
		switch (a)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	}while (a);
	return 0;
}

四、实现结果

玩家赢:

电脑赢:

 平局:

 退出游戏:

五、源代码链接 

https://gitee.com/ltianyuu/c-language/tree/master/test-7-27-3

最后:创作不易,希望大家给博主能点个赞啦!谢谢!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值