小游戏---三子棋

本文详细介绍了如何使用C语言编写一个三子棋游戏,包括初始化棋盘、打印棋盘、玩家和电脑下棋的逻辑以及判断输赢的算法。游戏中的棋盘为3x3,玩家和电脑分别用*和#表示,电脑的落子是随机的。代码实现了检查行、列和对角线是否有三个相同的棋子来判断输赢。
摘要由CSDN通过智能技术生成

思想

1、棋盘大小是3*3的,所以需要一个二维数组,需要将二维数组的初始为“空格”。

2、有了内容就可以打印了,之后先让玩家开始下棋,接着电脑下棋。

3、无论是玩家下棋,还是电脑下棋,都会出现一方胜出,或平局(电脑赢、玩家赢、平局、继续下棋),进行判断(赢得方式:任意一行连成三子、任意一列连成三子或者对角线连成三子)

实现

测试:菜单打印

为了方便创建两个.c文件一个是game.c 一个是test.c 和一个.h文件 game.h

menu函数实现一个简易的菜单

这里的头文件全都引在game.h中

程序分析

开始程序:先打印菜单也就是调用 menu 函数,之后输入 1开始游戏、输入 0退出游戏、输入非法值提示。当输入 0时,while循环正好结束,当输入非 0值循环继续符合 while 循环

 

 初始化棋盘和打印棋盘

这里为了可以改变行和列,将它们的值定义在game.h里了  现在的值都为 3

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

//显示棋盘
void Displayborad(char borad[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 ", borad[i][j]);
		}
		printf("\n");
	}
}
程序分析

InisBorad 函数完成初始化数组的内容,根据分析一个初始化为“空格”(不宜观察),现在初始化为' # '是为了方便观察,将数组元素遍历进行赋值;在遍历打印

此时打印的结果为:

 这样打印如果是“空格”的话,什么都看不到,不容易落子,所以应该优化一下,打印分割行便于落子

如果可以把棋盘打印成这样就挺好的

如图画质被压缩 私信我

这里可以先打印图 a     而图 b的打印次数比图 a要少1次


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

此时打印结果为:

 虽然是打印出来了,但这太局限了,所以这样分析不对,应该再拆

如果画质被压缩 私信我

现在将图  a 和图   b再拆成为 图  a 1 和图  b  1

同样图   a  1比图  b  1 需要多打印一次

而图  a  1 中的  a  图比  b  图要多打印一次

而图  b  1 中的  a  图比  b  图要多打印一次

void Displayborad(char borad[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 ", borad[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");
	}
}

此时打印结果为:

 开始下棋

玩家下棋

这里规定玩家的棋子为   *

              电脑的棋子为   #

程序分析

既然是玩家 有可能不是程序员,所以下标应该从1开始而不是0

再判断玩家输入的坐标是合法,如果合法,要判断该坐标是否被占用,一切都满足方可落子

void PlayMove(char borad[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("玩家下棋\n");
	while (1)
	{
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (borad[x - 1][y - 1] == ' ')//判断该位置是否没落子
			{
				borad[x - 1][y - 1] = '*';//将 * 赋给坐标
				break;
			}
			else
			{
				printf("该坐标已被占用,请重新输入\n");
			}
		}
		else
		{
			printf("该坐标非法,请重新输入\n");
		}
	}
}

测试结果:

符合逻辑

电脑下棋(用随机值完成下棋 所以电脑下的棋是随机的)

后续会更新较强的电脑

void ComputerMove(char borad[ROW][COL], int row, int col)
{
	while (1)
	{
		int x = rand() % row;//rand生成的随机值模row得到的值为0到row左闭右开的区间
		int y = rand() % col;//同理
		if (x >= 0 && x < row && y >= 0 && y < col)//判断坐标的范围是否合法
		{
			if (borad[x][y] == ' ')//判断坐标是否未落子
			{
				borad[x][y] = '#';
				break;
			}
		}
	}
}
程序分析

rand函数获得随机值模 row 得到的值在 0 到 row 的左闭右开的区间

之后像判断玩家一样判断 x ,y 的坐标,但是不用提示

判断输赢

思想中提到判断输赢,有四种状态分别是 1、玩家胜出 2、电脑胜出 3、平局 4、继续下棋    那么判断输赢有三种情况分别是 1、任意一行三子相同 2、任意一列三子相同 3、对角线三子相同  这里要注意判断棋子是否相等的时候如果全是“空格”不算

//玩家赢   *
//电脑赢   #
//平局     Q
//继续     C
IsFull(char borad[ROW][COL], int row, int col);

char IsWin(char borad[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	//判断任意一行,是否有相等的棋子
	for (i = 0; i < row; i++)
	{
		if (borad[i][0] == borad[i][1] && borad[i][1] == borad[i][2] && borad[i][0] != ' ')
		{
			return borad[i][0];
		}
	}
	//判断任意一列,是否有相等的棋子
	for (j = 0; j < col; j++)
	{
		if (borad[0][j] == borad[1][j] && borad[1][j] == borad[2][j] && borad[0][j] != ' ')
		{
			return borad[0][j];
		}
	}
	//判断对角线是否有相等的棋子
	if (borad[0][0] == borad[1][1] && borad[1][1] == borad[2][2] && borad[1][1] != ' ')
	{
		return borad[0][0];
	}
	if (borad[0][2] == borad[1][1] && borad[1][1] == borad[2][0] && borad[0][2] != ' ')
	{
		return borad[0][2];
	}
	//判断平局,如果平局,就代表棋盘满了
	IsFull(borad, row, col);
}

IsFull(char borad[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			if (borad[i][j] == ' ')//如果有空格,就说明了棋盘没有满所以继续
				return 'C';
		}
	}
	return 'Q';
}
程序分析

为什么判断玩家或电脑的输赢要用 * 和 # 呢?

因为可以直接 return 不用再判断 只需要少量的代码即可完成


	if (tmp == '*')
		printf("玩家赢\n");
	else if (tmp == '#')
		printf("电脑赢\n");
	else
		printf("平局\n");

game.h的代码

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

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

//显示棋盘
void Displayborad(char borad[ROW][COL], int row, int col);

//玩家下棋
void PlayMove(char borad[ROW][COL], int row, int col);

//电脑下棋
void ComputerMove(char borad[ROW][COL], int row, int col);

//判断输赢
char IsWin(char borad[ROW][COL], int row, int col);

game.c的代码


#include"game.h"

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

//显示棋盘
// 不易落子
//void Displayborad(char borad[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 ", borad[i][j]);
//		}
//		printf("\n");
//	}
//}

//void Displayborad(char borad[ROW][COL], int row, int col)
//{
//	int i = 0;
//	int j = 0;
//	for (i = 0; i < col; i++)
//	{
//		printf(" %c | %c | %c ", borad[i][0], borad[i][1], borad[i][2]);
//		printf("\n");
//		if (i < col - 1)
//		{
//			printf("---|---|---");
//			printf("\n");
//		}
//	}
//}


void Displayborad(char borad[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 ", borad[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 borad[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("玩家下棋\n");
	while (1)
	{
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (borad[x - 1][y - 1] == ' ')//判断该位置是否没落子
			{
				borad[x - 1][y - 1] = '*';//将 * 赋给坐标
				break;
			}
			else
			{
				printf("该坐标已被占用,请重新输入\n");
			}
		}
		else
		{
			printf("该坐标非法,请重新输入\n");
		}
	}
}

void ComputerMove(char borad[ROW][COL], int row, int col)
{
	while (1)
	{
		int x = rand() % row;//rand生成的随机值模row得到的值为0到row左闭右开的区间
		int y = rand() % col;//同理
		if (x >= 0 && x < row && y >= 0 && y < col)//判断坐标的范围是否合法
		{
			if (borad[x][y] == ' ')//判断坐标是否未落子
			{
				borad[x][y] = '#';
				break;
			}
		}
	}
}


//玩家赢   *
//电脑赢   #
//平局     Q
//继续     C
IsFull(char borad[ROW][COL], int row, int col);

char IsWin(char borad[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	//判断任意一行,是否有相等的棋子
	for (i = 0; i < row; i++)
	{
		if (borad[i][0] == borad[i][1] && borad[i][1] == borad[i][2] && borad[i][0] != ' ')
		{
			return borad[i][0];
		}
	}
	//判断任意一列,是否有相等的棋子
	for (j = 0; j < col; j++)
	{
		if (borad[0][j] == borad[1][j] && borad[1][j] == borad[2][j] && borad[0][j] != ' ')
		{
			return borad[0][j];
		}
	}
	//判断对角线是否有相等的棋子
	if (borad[0][0] == borad[1][1] && borad[1][1] == borad[2][2] && borad[1][1] != ' ')
	{
		return borad[0][0];
	}
	if (borad[0][2] == borad[1][1] && borad[1][1] == borad[2][0] && borad[0][2] != ' ')
	{
		return borad[0][2];
	}
	//判断平局,如果平局,就代表棋盘满了
	IsFull(borad, row, col);
}

IsFull(char borad[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			if (borad[i][j] == ' ')//如果有空格,就说明了棋盘没有满所以继续
				return 'C';
		}
	}
	return 'Q';
}

test.c的代码

#include"game.h"
void menu()
{
	printf("************************\n");
	printf("******  1. play   ******\n");
	printf("******  2, exit   ******\n");
	printf("************************\n");
}
void game()
{
	char tmp = 0;
	int borad[ROW][COL] = { 0 };
	InitBorad(borad, ROW, COL);//初始化棋盘
	Displayborad(borad, ROW, COL);//显示棋盘
	//显示完之后死循环下棋,直到分出胜负或者棋盘满了
	while (1)
	{
		PlayMove(borad, ROW, COL);//玩家下棋
		tmp = IsWin(borad, ROW, COL);
		if (tmp != 'C')
			break;
		Displayborad(borad, ROW, COL);//显示棋盘
		ComputerMove(borad, ROW, COL);//电脑下棋
		tmp = IsWin(borad, ROW, COL);
		if (tmp != 'C')
			break;
		Displayborad(borad, ROW, COL);//显示棋盘

	}
	if (tmp == '*')
		printf("玩家赢\n");
	else if (tmp == '#')
		printf("电脑赢\n");
	else
		printf("平局\n");

}
int main()
{
	int input = 0;
	do {
		srand((unsigned)time(NULL));
		menu();//打印菜单
		scanf("%d", &input);
		switch (input)
		{
		case 1:game();
			break;
		case 0:printf("退出游戏\n");
			break;
		default:printf("输入错误\t请输入 1或 2\n");
			break;
		}
	} while (input);
	return 0;
}

到这里除了电脑下棋水平不行,就完成了三子棋小游戏了

后续会更新较强的.................

persistence

  • 12
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 15
    评论
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晨曦的iPhone

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值