C语言实现三子棋和扫雷

前期规划

      由于需要使用很多函数,我们将创建很多文件,有一个存放主函数的text.h,将其他的一些函数放到game1.c(三子棋)game2.c(扫雷),在game1.h(三子棋)game2.h(扫雷)中声明,以便在text.h中使用。

创建主函数,设计流程

        由于想实现两个游戏,并且在以后有新游戏也可以加到里面,所以我想到了用swtih来完成分支。

代码如下

int main()
{
	int x = 0;
	do
	{
		printf("请选择想要游玩的项目>:");
		scanf("%d", &x);//选择游戏
		switch (x)
		{
			case 1:
			{
                printf("三子棋");   
				break;
			}
			case 2:
			{
                printf("扫雷");
				break;
			}

			default:
			{
				printf("未找到此游戏\n");
				printf("请重新选择\n");
				break;
			}

		}
	} while (x);

	return 0;
}

菜单

玩家看不到代码,那么我们加上一个菜单放在选择游戏前面。

代码如下

void menu()
{
	printf("╔══════════╗\n");
	printf("║ 1.三子棋 ║\n");
	printf("║══════════║\n");
	printf("║ 2.扫  雷 ║\n");
	printf("║══════════║\n");
	printf("║ 0.退  出 ║\n");
	printf("╚══════════╝\n");
}

在屏幕上显示的效果应该是这样的。

现在,让我们完成游戏的部分吧。

三子棋

创建棋盘

        三子棋要一个3x3的棋盘,并且要四条先把棋盘分割成九个区域,那么我们可以用二维数组来完成它

代码如下

#define ROW 3
#define COL 3
char three[ROW][COL] = { 0 };

初始化棋盘

棋盘创建好了,先将棋盘初始化。

代码如下

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

打印棋盘

棋盘创建好了,但是还是要在屏幕上打印出来,并且要把四条线也打印出来。

代码如下

//打印棋盘
void print(char three[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	system("cls");
	printf(" ");
	for (j = 0; j < col; j++)//打印横坐标
	{
		printf("% d ",j+1);
		if (j < col - 1)
		{
			printf(" ");
		}
	}
	printf("\n");
	for (i = 0; i < row; i++)//打印棋盘
	{
		printf("%d", i+1);//打印纵坐标

		for (j = 0; j < col; j++)
		{
			printf(" %c ", three[i][j]);
			if (j < col - 1)//如果打印的是最后一列,那么不打印
			{
				printf("|");
			}
		}
		printf("\n");
		if (i < row - 1)//如果打印的是最后一行,那么不打印
		{
			printf(" ");//因为纵坐标把棋盘向右挤了一格,这里加一个空格填充
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)
				{
					printf("|");
				}
			}
			printf("\n");
		}
	}
}

让我们来看看我们的棋盘吧。

 玩家下棋

        现在该我们下棋了,由于我们一开始初始化棋盘,棋盘里面没有东西,我们可以对此进行判断,当只有数组里面为空格时才可以输入,不仅如此,我们还要判断输入的坐标是不是一个正确的坐标,都满足时才允许玩家下棋。

代码如下

void play(char three[ROW][COL], int row, int col)
{
	int x = 0;//行
	int y = 0;//列
	printf("玩家回合\n");
	printf("输入坐标>:");
	while (1)
	{
		scanf("%d %d", &x, &y);
		if (x <= row && y <= row && x >= 1 && y >= 1)//判断坐标是否正确
		{
			if (three[x-1][y-1] == ' ')//判断坐标是否被占用
			{
				three[x-1][y-1] = '#';//玩家的棋子
				break;
			}
			else
			{
				printf("该坐标已被输入,请重新输入");
			}
		}
		else
		{
			printf("没有这个坐标,请重新输入");
		}
	}
}

 电脑下棋

       玩家下完了,总得给电脑也下吧,但是怎么能让电脑也学会下棋呢,函数rand()可以产生随机数,我们用srand((int)time(NULL))来让rand()的初始值发生改变。电脑每次就能给出不一样的值,我们可以确定随机数的范围,那我们只需要判断坐标有没有被占用就好了。

代码如下

void computer(char three[ROW][COL], int row, int col)
{
	srand((int)time(NULL));
	while (1)
	{
		int x = rand() % row;
		int y = rand() % col;
		if (three[x][y] == ' ')
		{
			three[x][y] = '*';
			break;
		}
	}
}

判断胜负

        电脑也学会下棋了,我们在case语句中加一个循环,一遍一遍把棋盘下满,或者是有获胜者,当我们就该判断谁是获胜者了。为此,我们设定C为继续下棋的标志,而'#'为玩家获胜,'*'为电脑获胜,平局时返回Q。

代码如下

char win(char three[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	for (x = 0; x < row; x++)//横
	{
		if (three[x][0] == three[x][1] && three[x][0] == three[x][2] && three[x][0] != ' ')
		{
			return three[x][0];
		}
	}
	for (x = 0; x < col; x++)//列
	{
		if (three[0][x] == three[1][x]&& three[0][x] == three[2][x] && three[0][x] != ' ')
		{

			return three[0][x];
		}
	}

	if (three[0][0] == three[1][1] && three[1][1] == three[2][2] && three[1][1] != ' ')//对角线
	{
		return three[1][1];
	}
	if (three[0][2] == three[1][1] && three[1][1] == three[2][0] && three[1][1] != ' ')//对角线
	{
		return three[1][1];
	}
	for (x = 0; x < row; x++)
	{
		for (y = 0; y < col; y++)
		{
			if (three[x][y] == ' ')//检查棋盘是否满了
			{
				return 'C';
			}
		}
	}
	return 'S';
}

三子棋代码

有了返回值,我们就要进行判断了,在把之前的整合一下,三子棋游戏就完成了。

代码如下

int main()
{
	int x = 0;
	do
	{
		menu();
		printf("请选择想要游玩的项目>:");
		scanf("%d", &x);
		switch (x)
		{
			case 1:
			{
				char i = ' ';
				char three[ROW][COL];//创建二维数组
				init(three, ROW, COL);//初始化二维数组
				while (1)
				{
					print(three, ROW, COL);//打印棋盘
					play(three, ROW, COL);//玩家下棋
					print(three, ROW, COL);//打印棋盘
					i=win(three, ROW, COL);//判断输赢
					if (i != 'C')
					{
						break;
					}
					computer(three, ROW, COL);//电脑下棋
					print(three, ROW, COL);//打印棋盘
					i = win(three, ROW, COL); //判断输赢
					if (i != 'C')
					{
						break;
					}
				}
				if ('#' == i)
				{
					printf("玩家胜利\n");
				}
				else if ('*' == i)
				{
					printf("电脑胜利\n");
				}
				else if ('S' == i)
				{
					printf("平局\n");
				}
				break;
			}
			case 2:
			{
                pritnf("扫雷");
				break;
			}

			default:
			{
				system("cls");
				printf("未找到此游戏\n");
				printf("请重新选择\n");
				break;
			}

		}
	} while (x);
	return 0;
}

扫雷

创建棋盘

        同样的,扫雷也需要一个棋盘,但是在四周容易越界访问,为了避免这个问题,我们可以将四周都扩大一格,并且只访问中间的。

        棋盘的问题解决了,但是在布雷的过程中将雷设置1,安全的地方设置成0的时候。排雷是,如果排雷的位置周围正好只有一个雷,那个这个位置也会被改成1,那么就有歧义了。我们可以创建两个棋盘,一个棋盘放雷,另一个棋盘放排雷的信息。

代码如下

#define towrow towrows-2
#define towcol towcols-2
#define towrows 11
#define towcols 11
char bomb[towrows][towcols];//雷棋盘
char find[towrows][towcols];//玩家排雷棋盘

初始化棋盘

         同样的,我们要初始化棋盘,但两个棋盘初始化内容不一致,解决方法很简单,加一个参数就好了。

代码如下

void init(char bomb[ROWS][COLS], int row, int col, char sel)
{
	int x = 0;
	int y = 0;
	for (x = 0; x < row; x++)
	{
		for (y = 0; y < col; y++)
		{
			bomb[x][y] = sel;
		}
	}
}

打印棋盘

现在,让我们把棋盘打印出来看看。

代码如下

void print2(char bomb[towrows][towrows], int row, int col)
{
	int x = 0;
	int y = 0;
	system("cls");
	printf("  ");
	for (x = 1; x <= col; x++)
	{
		printf("%d ", x);//横坐标打印
	}
	printf("\n");
	for (x = 1; x <= row; x++)
	{
		printf("%d ", x);//纵坐标打印
		for (y = 1; y <= col; y++)
		{
			printf("%c ", bomb[x][y]);
		}
		printf("\n");
	}
}

效果是这样的

 布雷

我们教会了电脑怎么产生随机数,现在就再麻烦它帮我们布一下雷吧

代码如下

#define bombs 10
void boom(char bomb[towrows][towcols], int row, int col)
{
	int x = 0;
	int y = 0;
	int z = bombs;
	srand((int)time(NULL));
	while (z)
	{
		x = rand() % row+1;
		y = rand() % col+1;
		if ('0' == bomb[x][y])
		{
			bomb[x][y] = '1';
			z--;
		}
	}
}

判断部分

        雷布置完了,现在就该排雷了。我们每输进去一个坐标,电脑应该是首先判断这个坐标是不是已经被排了。如果没有排,那么我们该判断这个坐标是不是雷,如果是,那么游戏结束,跳出循环。如果不是,计算周围八个位置的雷,并将周围雷的数量写入数组中,当把所有不是雷的区域排干净后,游戏胜利跳出循环。

代码如下

void find_bomb(char bomb[towrows][towcols],char find[towrows][towcols],int row,int col)
{
	int x = 0;
	int y = 0;
	int count = 0;
	while (count < row * col - bombs)
	{
		printf("请输入排查雷的坐标:");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if ('*' == find[x][y])
			{
				if ('1' == bomb[x][y])
				{
					end_printf(bomb, find, x, y);
					printf("游戏结束\n");
					break;
				}
				else
				{

					find[x][y] = get_bomb(bomb, x, y) + '0';
					count++;
					print2(find, towrow, towcol);
				}
			}
			else
			{
				printf("该区域已被排查过");
			}
		}
		else
		{
			printf("超出棋盘范围\n");
		}
	}
	if (!(count < row * col - bombs))
	{
		printf("恭喜你,游戏胜利\n");
	}
}

判断四周的雷

        数字字符的ascii码是连续的,将周围的八个数字加起来再减去8个字符0就可以得到周围就几个雷了。

代码如下

int get_bomb(char bomb[towrows][towcols], int row, int col)
{
	return (bomb[row-1][col-1]+
			bomb[row-1][col]+
			bomb[row - 1][col + 1]+
			bomb[row][col - 1]+
			bomb[row][col + 1]+
			bomb[row + 1][col - 1]+
			bomb[row + 1][col]+
			bomb[row + 1][col + 1] - 8 * '0');
}

在游戏失败时,标记踩的是哪一个雷,并且加了一个动画,

代码如下

void end_printf(char bomb[towrows][towcols], char find[towrows][towcols], int x, int y)
{
	find[x][y] = '#';//踩的雷改成#,其他的改成*
	int i = 0;
	int j = 0;
	for (i = 1;i<towrow + towcol; i++)
	{
		for (j = i; j >= 0; j--)
		{
			if (x + j >= 1 && x + j <= 9 && y + i - j >= 1 && y + i - j <= 9)
			 {
				 lost(bomb, find, x + j, y + i - j);
			 }
			if (x - j >= 1 && x - j <= 9 && y + i - j >= 1 && y + i - j <= 9)
			{
				lost(bomb, find, x - j, y + i - j);
			}
			if (x + j >= 1 && x + j <= 9 && y - i + j >= 1 && y - i + j <= 9)
			{
				lost(bomb, find, x + j, y - i + j);

			}
			if (x - j >= 1 && x - j <= 9 && y - i + j >= 1 && y - i + j <= 9)
			{
				lost(bomb, find, x - j, y - i + j);
			}
		}

		print2(find, towrow, towcol);
		Sleep(200);
	}
}
void lost(char bomb[towrows][towcols], char find[towrows][towcols], int x, int y)
{
			if ('0' == bomb[x][y])
			{
				find[x][y] = get_bomb(bomb, x, y)+'0';
			}
			else if ('#' == find[x][y])
			{
				;
			}
			else
			{
				find[x][y] = '*';
			}
}

好了,现在我们完成了两个游戏的制作,下面是代码

text.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"game.h"
#include"扫雷.h"


void menu()
{
	printf("╔══════════╗\n");
	printf("║ 1.三子棋 ║\n");
	printf("║══════════║\n");
	printf("║ 2.扫  雷 ║\n");
	printf("║══════════║\n");
	printf("║ 0.退  出 ║\n");
	printf("╚══════════╝\n");
}

int main()
{
	int x = 0;
	do
	{
		menu();
		printf("请选择想要游玩的项目>:");
		scanf("%d", &x);
		switch (x)
		{
			case 1:
			{
				char i = ' ';
				char three[ROW][COL] = { 0 };//创建二维数组
				init(three, ROW, COL);//初始化二维数组
				while (1)
				{
					print(three, ROW, COL);//打印棋盘
					play(three, ROW, COL);//玩家下棋
					print(three, ROW, COL);//打印棋盘
					i=win(three, ROW, COL);//判断输赢
					if (i != 'C')
					{
						break;
					}
					computer(three, ROW, COL);//电脑下棋
					print(three, ROW, COL);//打印棋盘
					i = win(three, ROW, COL); //判断输赢
					if (i != 'C')
					{
						break;
					}
				}
				if ('#' == i)
				{
					printf("玩家胜利\n");
				}
				else if ('*' == i)
				{
					printf("电脑胜利\n");
				}
				else if ('S' == i)
				{
					printf("平局\n");
				}
				break;
			}
			case 2:
			{
				char bomb[towrows][towcols];//雷棋盘
				char find[towrows][towcols];//玩家排雷棋盘
				init2(bomb, towrows, towcols,'0');//初始化雷棋盘
				init2(find, towrows, towcols, '*');//初始化玩家排雷棋盘
				boom(bomb, towrow, towcol);//布雷
				print2(find, towrow, towcol);//打印棋盘
				find_bomb(bomb, find, towrow,towcol);//排雷
				break;
			}

			default:
			{
				system("cls");
				printf("未找到此游戏\n");
				printf("请重新选择\n");
				break;
			}

		}
	} while (x);

	return 0;
}

game1.h(三子棋)

#include<stdio.h>
#include<time.h>
#include<Windows.h>
#include<stdlib.h>
#define ROW 3
#define COL 3
void init(char three[ROW][COL], int row, int col);//格式化数组
void print(char three[ROW][COL], int row, int col);//打印棋盘
void play(char three[ROW][COL], int row, int col);//玩家输入
void computer(char three[ROW][COL], int row, int col);//电脑输入
char win(char three[ROW][COL], int row, int col);//判断输赢

game1.c(三子棋)

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"


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

void print(char three[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	system("cls");
	printf(" ");
	for (j = 0; j < col; j++)//打印坐标
	{
		printf("% d ",j+1);
		if (j < col - 1)
		{
			printf(" ");
		}
	}
	printf("\n");
	for (i = 0; i < row; i++)//打印棋盘
	{
		printf("%d", i+1);

		for (j = 0; j < col; j++)
		{
			printf(" %c ", three[i][j]);
			if (j < col - 1)
			{
				printf("|");
			}
		}
		printf("\n");
		if (i < row - 1)
		{
			printf(" ");
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)
				{
					printf("|");
				}
			}
			printf("\n");
		}
	}
}

void play(char three[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("玩家回合\n");
	printf("输入坐标>:");
	while (1)
	{
		scanf("%d %d", &x, &y);
		if (x <= row && y <= row && x >= 1 && y >= 1)
		{
			if (three[x-1][y-1] == ' ')
			{
				three[x-1][y-1] = '#';
				break;
			}
			else
			{
				printf("该坐标已被输入,请重新输入");
			}
		}
		else
		{
			printf("没有这个坐标,请重新输入");
		}
	}
}

void computer(char three[ROW][COL], int row, int col)
{
	srand((int)time(NULL));
	while (1)
	{
		int x = rand() % row;
		int y = rand() % col;
		if (three[x][y] == ' ')
		{
			three[x][y] = '*';
			break;
		}
	}
}

char win(char three[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	for (x = 0; x < row; x++)//横
	{
		if (three[x][0] == three[x][1] && three[x][0] == three[x][2] && three[x][0] != ' ')
		{
			return three[x][0];
		}
	}
	for (x = 0; x < col; x++)//列
	{
		if (three[0][x] == three[1][x]&& three[0][x] == three[2][x] && three[0][x] != ' ')
		{

			return three[0][x];
		}
	}

	if (three[0][0] == three[1][1] && three[1][1] == three[2][2] && three[1][1] != ' ')//对角线
	{
		return three[1][1];
	}
	if (three[0][2] == three[1][1] && three[1][1] == three[2][0] && three[1][1] != ' ')//对角线
	{
		return three[1][1];
	}
	for (x = 0; x < row; x++)
	{
		for (y = 0; y < col; y++)
		{
			if (three[x][y] == ' ')
			{
				return 'C';
			}
		}
	}
	return 'S';
}













game2.h(扫雷)

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

#define towrow towrows-2
#define towcol towcols-2
#define towrows 11
#define towcols 11
#define bombs 10
void init2(char bomb[towrows][towcols], int row, int col,char sel);//初始化
void print2(char bomb[towrows][towrows], int row, int col);//打印
void boom(char bomb[towrows][towcols], int row, int col);//布雷
void find_bomb(char bomb[towrows][towcols], char find[towrows][towcols], int row, int col);//排雷
int get_bomb(char bomb[towrows][towcols], int row, int col);//得到周围雷
void lost(char bomb[towrows][towcols], char find[towrows][towcols], int x, int y);//失败
void end_printf(char bomb[towrows][towcols], char find[towrows][towcols], int x, int y);//失败动画

game2.c(扫雷)

#define _CRT_SECURE_NO_WARNINGS 1
#include"扫雷.h"

void init2(char bomb[towrows][towcols],int row,int col,char sel)
{
	int x = 0;
	int y = 0;
	for (x = 0; x < row; x++)
	{
		for (y = 0; y < col; y++)
		{
			bomb[x][y] = sel;
		}
	}
}
void print2(char bomb[towrows][towrows], int row, int col)
{
	int x = 0;
	int y = 0;
	system("cls");
	printf("  ");
	for (x = 1; x <= col; x++)
	{
		printf("%d ", x);
	}
	printf("\n");
	for (x = 1; x <= row; x++)
	{
		printf("%d ", x);
		for (y = 1; y <= col; y++)
		{
			printf("%c ", bomb[x][y]);
		}
		printf("\n");
	}
}

void boom(char bomb[towrows][towcols], int row, int col)
{
	int x = 0;
	int y = 0;
	int i = 0;
	int j = 0;
	int z = bombs;
	srand((int)time(NULL));
	while (z)
	{
		x = rand() % row+1;
		y = rand() % col+1;
		if ('0' == bomb[x][y])
		{
			bomb[x][y] = '1';
			z--;
		}
	}
}

void find_bomb(char bomb[towrows][towcols],char find[towrows][towcols],int row,int col)
{
	int x = 0;
	int y = 0;
	int count = 0;
	while (count < row * col - bombs)
	{
		printf("请输入排查雷的坐标:");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if ('*' == find[x][y])
			{
				if ('1' == bomb[x][y])
				{
					end_printf(bomb, find, x, y);
					printf("游戏结束\n");
					break;
				}
				else
				{

					find[x][y] = get_bomb(bomb, x, y) + '0';
					count++;
					print2(find, towrow, towcol);
				}
			}
			else
			{
				printf("该区域已被排查过");
			}
		}
		else
		{
			printf("超出棋盘范围\n");
		}
	}
	if (!(count < row * col - bombs))
	{
		printf("恭喜你,游戏结束\n");
	}
}

int get_bomb(char bomb[towrows][towcols], int row, int col)
{
	return (bomb[row-1][col-1]+
			bomb[row-1][col]+
			bomb[row - 1][col + 1]+
			bomb[row][col - 1]+
			bomb[row][col + 1]+
			bomb[row + 1][col - 1]+
			bomb[row + 1][col]+
			bomb[row + 1][col + 1] - 8 * '0');
}


void end_printf(char bomb[towrows][towcols], char find[towrows][towcols], int x, int y)
{
	find[x][y] = '#';
	int i = 0;
	int j = 0;
	for (i = 1;i<towrow + towcol; i++)
	{
		for (j = i; j >= 0; j--)
		{
			if (x + j >= 1 && x + j <= 9 && y + i - j >= 1 && y + i - j <= 9)
			 {
				 lost(bomb, find, x + j, y + i - j);
			 }
			if (x - j >= 1 && x - j <= 9 && y + i - j >= 1 && y + i - j <= 9)
			{
				lost(bomb, find, x - j, y + i - j);

			}
			if (x + j >= 1 && x + j <= 9 && y - i + j >= 1 && y - i + j <= 9)
			{
				lost(bomb, find, x + j, y - i + j);

			}
			if (x - j >= 1 && x - j <= 9 && y - i + j >= 1 && y - i + j <= 9)
			{
				lost(bomb, find, x - j, y - i + j);
			}
		}

		print2(find, towrow, towcol);
		Sleep(200);
	}
}
void lost(char bomb[towrows][towcols], char find[towrows][towcols], int x, int y)
{
			if ('0' == bomb[x][y])
			{
				find[x][y] = get_bomb(bomb, x, y)+'0';
			}
			else if ('#' == find[x][y])
			{
				;
			}
			else
			{
				find[x][y] = '*';
			}
}

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值