C语言程序设计 | 三子棋游戏

三子棋是黑白棋的一种。三子棋是一种民间传统游戏,又叫九宫棋、圈圈叉叉、一条龙、井字棋等。将正方形对角线连起来,相对两边依次摆上三个双方棋子,只要将一方自己的三个棋子走成一条线,就能获胜。
以上介绍来自百度百科

下面来以我自己的理解讲解如何用C语言来实现三子棋
(可拓展棋盘,改变棋子数为n字棋)

对于一款游戏,首先我们必须要有一个可视化的菜单,供玩家选择进入游戏或者退出游戏。

void Menu_Game()
{
	printf("*****************************************\n");
	printf("*********      1.开始游戏       *********\n");
	printf("*********      0.结束游戏       *********\n");
	printf("*****************************************\n");
}

同时我们需要接收玩家的输入,进行相应的操作,我们可以运用switch语句来完成这个菜单。同时,当玩家输入错误时我们应该让他重新输入,而当他游戏结束时,也应当让他选择继续游戏或者进行下一次游戏

	do
	{
		Menu_Game();
		printf("请输入您的选择:\n");
		scanf("%d", &n);

		switch (n)
		{
		case 1:
			Game(Checkerboard, ROW, COL);
			break;
		case 0:
			printf("结束游戏\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}

	} while (n);

如果想用C语言来实现三子棋,我们可以想到用一个二维数组来作为这个三子棋的棋盘,为了方便棋盘的拓展,我们可以用宏来定义棋盘的行数和列数以及棋子数

#define ROW 3
#define COL 3
#define CHESS_NUMBER 3

下面就可以开始具体来写游戏的实现方法,首先我们需要给数组初始化,让棋盘置空,可以遍历一次数组来让所有元素都为空格。

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

然后我们需要一个函数,能够显示我们的棋盘,让我们能够看清游戏的局势,当然这个棋盘也要有一定的美观。
![在这里插入图片描述](https://img-blog.csdnimg.cn/2019101020453066.pngC语言程序设计 | 三子棋游戏_第1张图片

void Show_Checkerboard(char Checkerboard[ROW][COL], int row, int col)
{
	int i, j;
	for (i = 0; i < row; i++)
	{
		printf("---");
		printf("|");
	}
	printf("\n");
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			printf(" %c ", Checkerboard[i][j]);
				printf("|");
		}
		printf("\n");
		for (j = 0; j < col; j++)
		{
			printf("---");
				printf("|");
		}
		printf("\n");
	}
}

棋盘做好了,下一步就应该让玩家和电脑在棋盘中下棋,我们先从玩家的下棋开始实现。
我们需要让玩家输入他要下的位置,同时我们还要判断他输入的位置是否合法,当他输入的位置不存在的时候我们可以输出一个输入错误,提示他重新输入,同时还需要判断他输入的位置是否被占用,如果被占用同样提示一遍并让其重新输入。而当他输入成功时,我们可以用符号 ‘*’来代替他的棋子,将星号保存在对应的位置,代码如下:

void Player_Move(char Checkerboard[ROW][COL], int row, int col)
{
	int x, y;
	while (1)
	{
		printf("请输入您要下的位置:\n");
		scanf("%d%d", &x, &y);
		if (x > 0 && x <= ROW && y > 0 && y <= COL)
		{

			if (Checkerboard[x - 1][y - 1] == ' ')
			{
				Checkerboard[x - 1][y - 1] = '*';
				break;
			}
			else
			{
				printf("该坐标已被输入\n");
			}
		}
		else
		{
			printf("输入错误,请重新输入\n");
		}
	}

}

接下来就应该写电脑的落子,对于电脑的落子,我们需要保证其具有一定的随机性,所以我们需要用到几个函数,rand(),time(),srand(),
rand 提供随机数
time 为随机数设置范围
srand 作为随机数的设置器,保证数字每一次都不同
同时我们还需要引入对应头文件

#include
#include

我们用 rand()分别与行数列数取余数,得到随机的位置,并对其判断是否被占用,如果被占用则重新取随机数。当成功时,将一个#符号作为电脑的棋子保存入棋盘。
代码如下:

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

下棋的步骤完成了,下面就应该判断游戏的结束条件。游戏的结束条件有三种,胜利,失败,平局。而平局的标准就是所有棋子下满但没有人取得胜利,所以我们可以先从这方面入手,我们只需要遍历棋盘,查看棋盘是否存在空位置,若不存在则为下满,我们可以返回一个N 既NOT,若下满则返回F 既FULL。

char Full_Checkerboard(char Checkerboard[ROW][COL], int row, int col)
{
	int i, j;
	for (i = 0; i < row; i++)
		for (j = 0; j < col; j++)
			if (Checkerboard[i][j] == ' ')
				return 'N';
	return 'F';
}

然后我们接下来就可以判断究竟是电脑获胜还是玩家获胜,首先,要连成三子,我们可以行,可以列,可以左右对角线四种情况,当连成三子且不为空位置时,返回其中一个棋子,根据返回的是代表玩家的*还是代表电脑的#来判断胜负。
首先来写行的判断
为了能拓展至n子,我们要考虑其的泛用性,所以我们需要一个flag变量作为计数器,当达成

Checkerboard[i][j] == Checkerboard[i + 1][j]) && (Checkerboard[i][j] != ' '

这个条件时,计数器加一,而不达成时,计数器清空,这样就可以保证为连续的子.因为我们每一次与下一项进行对比,则需要判断棋子数-1次达成条件,所以当计数器与我们的棋子数-1相同时,则说明达成胜利条件,返回其中一个子。
同理对于列我们需要判断

Checkerboard[i][j] == Checkerboard[i + 1][j]) && (Checkerboard[i][j] != ' '

对于左对角线

Checkerboard[i][j] == Checkerboard[i + 1][j + 1]) && (Checkerboard[i][j] != ' '

右对角线

Checkerboard[i][j] == Checkerboard[i + 1][j - 1]) && (Checkerboard[i][j] != ' '

当以上四个条件没有达成时,我们还需要判断是否下满,既平局,如果所有条件没有达成,则说明游戏没有结束,返回一个N
代码如下:

char Win_Game(char Checkerboard[ROW][COL], int row, int col)
{
	int i, j, flag = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col - 1; j++)
		{
			if ((Checkerboard[i][j] == Checkerboard[i][j + 1]) && (Checkerboard[i][j] != ' '))
			{
				flag++;
			}
			else if (flag == CHESS_NUMBER - 1)
				return Checkerboard[i][j];
			else
			{
				flag = 0;
			}
		}
	}
	//判断行是否三子

	for (i = 0; i < row - 1; i++)
	{
		for (j = 0; j < col; j++)
		{
			if ((Checkerboard[i][j] == Checkerboard[i + 1][j]) && (Checkerboard[i][j] != ' '))
			{
				flag++;
			}
			else
			{
				flag = 0;
			}
			if (flag == CHESS_NUMBER - 1)
				return Checkerboard[i][j];
		}
	}
	//判断列是否三子 

	flag = 0;
	for (i = 0, j = 0; i < row - 1, j < col - 1; i++, j++)
	{
		if ((Checkerboard[i][j] == Checkerboard[i + 1][j + 1]) && (Checkerboard[i][j] != ' '))
		{
			flag++;
		}
		else
		{
			flag = 0;
		}
		if (flag == CHESS_NUMBER - 1)
			return Checkerboard[i][j];
	}
	//判断左对角线是否三子

	flag = 0;
	for (i = 0, j = row - 1; i < row - 1, j>0; i++, j--)
	{
		if ((Checkerboard[i][j] == Checkerboard[i + 1][j - 1]) && (Checkerboard[i][j] != ' '))
		{
			flag++;
		}
		else
		{
			flag = 0;
		}
		if (flag == CHESS_NUMBER - 1)
			return Checkerboard[i][j];
	}
	//判断右对角线是否三子

	if (Full_Checkerboard(Checkerboard, ROW, COL) == 'F')
		return 'F';
	//判断棋盘是否下满
	
	return 'N';
}
//判断游戏胜负情况

这样,所有的游戏函数完成了,我们就要开始游戏控制函数的编写。
我们需要一个循环,让玩家和电脑下棋,当游戏没有结束的时候循环就不会跳出。而每一次我们需要让玩家和电脑分别下棋,并且显示棋盘的情况,以及判断是否胜利,因为前面我们完成了所有的游戏函数的编写,在这里直接调用就可以完成了

void Game(char Checkerboard[ROW][COL], int row, int col)
{
	char flag = 'N';
	srand((unsigned int)time(NULL));
	//设置随机数 
	Init_Checkerboard(Checkerboard, ROW, COL);
	Show_Checkerboard(Checkerboard, ROW, COL);
	while (1)
	{
		printf("现在是你的回合\n");
		Player_Move(Checkerboard, ROW, COL);
		Show_Checkerboard(Checkerboard, ROW, COL);
		if ((flag = Win_Game(Checkerboard, ROW, COL)) != 'N')
			break;

		printf("现在是对手的回合\n");
		Computer_Move(Checkerboard, ROW, COL);
		Show_Checkerboard(Checkerboard, ROW, COL);
		if ((flag = Win_Game(Checkerboard, ROW, COL)) != 'N')
			break;

	}
	if (flag == '*')
	{
		printf("玩家获胜\n");
	}
	else if (flag == '#')
	{
		printf("电脑获胜\n");
	}
	else if (flag == 'F')
	{
		printf("棋盘满,平局\n");
	}
}

到这里游戏就彻底完成了
C语言程序设计 | 三子棋游戏_第2张图片
如果需要改成n子棋,我们只需要在头文件中修改棋子数量和棋盘大小即可
如8x8的五子棋
C语言程序设计 | 三子棋游戏_第3张图片
下面展示完整的代码

头文件head.h

#define _CRT_SECURE_NO_WARNINGS
#pragma once
#include
#include
#include
#define ROW 3
#define COL 3
#define CHESS_NUMBER 3

void Menu_Game();

void Init_Checkerboard(char Checkerboard[ROW][COL], int row, int col);

void Show_Checkerboard(char Checkerboard[ROW][COL], int row, int col);

void Player_Move(char Checkerboard[ROW][COL], int row, int col);

void Computer_Move(char Checkerboard[ROW][COL], int row, int col);

char Full_Checkerboard(char Checkerboard[ROW][COL], int row, int col);

char Win_Game(char Checkerboard[ROW][COL], int row, int col);

void Game(char Checkerboard[ROW][COL], int row, int col);

游戏文件 game.c

#include "head.h"

void Menu_Game()
{
	printf("*****************************************\n");
	printf("*********      1.开始游戏       *********\n");
	printf("*********      0.结束游戏       *********\n");
	printf("*****************************************\n");
}

void Init_Checkerboard(char Checkerboard[ROW][COL], int row, int col)
{
	int i, j;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			Checkerboard[i][j] = ' ';
		}
	}
}
//初始化棋盘

void Show_Checkerboard(char Checkerboard[ROW][COL], int row, int col)
{
	int i, j;
	for (i = 0; i < row; i++)
	{
		printf("---");
		printf("|");
	}
	printf("\n");
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			printf(" %c ", Checkerboard[i][j]);
				printf("|");
		}
		printf("\n");
		for (j = 0; j < col; j++)
		{
			printf("---");
				printf("|");
		}
		printf("\n");
	}
}
//显示棋盘


void Player_Move(char Checkerboard[ROW][COL], int row, int col)
{
	int x, y;
	while (1)
	{
		printf("请输入您要下的位置:\n");
		scanf("%d%d", &x, &y);
		if (x > 0 && x <= ROW && x > 0 && x <= ROW)
		{

			if (Checkerboard[x - 1][y - 1] == ' ')
			{
				Checkerboard[x - 1][y - 1] = '*';
				break;
			}
			else
			{
				printf("该坐标已被输入\n");
			}
		}
		else
		{
			printf("输入错误,请重新输入\n");
		}
	}

}
//玩家移动

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



}
//电脑移动

char Full_Checkerboard(char Checkerboard[ROW][COL], int row, int col)
{
	int i, j;
	for (i = 0; i < row; i++)
		for (j = 0; j < col; j++)
			if (Checkerboard[i][j] == ' ')
				return 'N';
	return 'F';
}
//判断棋盘是否下满 

char Win_Game(char Checkerboard[ROW][COL], int row, int col)
{
	int i, j, flag = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col - 1; j++)
		{
			if ((Checkerboard[i][j] == Checkerboard[i][j + 1]) && (Checkerboard[i][j] != ' '))
			{
				flag++;
			}
			else if (flag == CHESS_NUMBER - 1)
				return Checkerboard[i][j];
			else
			{
				flag = 0;
			}
		}
	}
	//判断行是否三子

	for (i = 0; i < row - 1; i++)
	{
		for (j = 0; j < col; j++)
		{
			if ((Checkerboard[i][j] == Checkerboard[i + 1][j]) && (Checkerboard[i][j] != ' '))
			{
				flag++;
			}
			else
			{
				flag = 0;
			}
			if (flag == CHESS_NUMBER - 1)
				return Checkerboard[i][j];
		}
	}
	//判断列是否三子 

	flag = 0;
	for (i = 0, j = 0; i < row - 1, j < col - 1; i++, j++)
	{
		if ((Checkerboard[i][j] == Checkerboard[i + 1][j + 1]) && (Checkerboard[i][j] != ' '))
		{
			flag++;
		}
		else
		{
			flag = 0;
		}
		if (flag == CHESS_NUMBER - 1)
			return Checkerboard[i][j];
	}
	//判断左对角线是否三子

	flag = 0;
	for (i = 0, j = row - 1; i < row - 1, j>0; i++, j--)
	{
		if ((Checkerboard[i][j] == Checkerboard[i + 1][j - 1]) && (Checkerboard[i][j] != ' '))
		{
			flag++;
		}
		else
		{
			flag = 0;
		}
		if (flag == CHESS_NUMBER - 1)
			return Checkerboard[i][j];
	}
	//判断右对角线是否三子

	if (Full_Checkerboard(Checkerboard, ROW, COL) == 'F')
		return 'F';
	//判断棋盘是否下满

	return 'N';
}
//判断游戏胜负情况

void Game(char Checkerboard[ROW][COL], int row, int col)
{
	char flag = 'N';
	srand((unsigned int)time(NULL));
	//设置随机数 
	Init_Checkerboard(Checkerboard, ROW, COL);
	Show_Checkerboard(Checkerboard, ROW, COL);
	while (1)
	{
		printf("现在是你的回合\n");
		Player_Move(Checkerboard, ROW, COL);
		Show_Checkerboard(Checkerboard, ROW, COL);
		if ((flag = Win_Game(Checkerboard, ROW, COL)) != 'N')
			break;

		printf("现在是对手的回合\n");
		Computer_Move(Checkerboard, ROW, COL);
		Show_Checkerboard(Checkerboard, ROW, COL);
		if ((flag = Win_Game(Checkerboard, ROW, COL)) != 'N')
			break;

	}
	if (flag == '*')
	{
		printf("玩家获胜\n");
	}
	else if (flag == '#')
	{
		printf("电脑获胜\n");
	}
	else if (flag == 'F')
	{
		printf("棋盘满,平局\n");
	}
}

测试文件 test.c

#include "head.h"

int main()
{
	int n;
	char Checkerboard[ROW][COL] = { 0 };
	srand((int)time(NULL));
	do
	{
		Menu_Game();
		printf("请输入您的选择:\n");
		scanf("%d", &n);

		switch (n)
		{
		case 1:
			Game(Checkerboard, ROW, COL);
			break;
		case 0:
			printf("结束游戏\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}

	} while (n);

	return 0;
}

这是个很简单的小游戏,总代码数在270行左右,很容易就可以实现。
代码链接:https://github.com/HONGYU-LEE/test/tree/master/project/tic-tac-toe

你可能感兴趣的:(C语言程序设计,三子棋,C语言,游戏,c,程序设计)