C语言 实现简单的三子棋游戏

C语言 实现简单的三子棋游戏



前言

三子棋又叫九宫棋、圈圈叉叉、一条龙、井字棋等。

三子棋游戏规则:三子连成一片即为赢,如果双方都没有连成线,即为平局。


一、如何实现?

1.棋盘大小如何确定?

我们要实现一个3×3的棋盘,就需要定义一个3行3列的数组,但是数组的下标从0开始,玩家选择落子坐标很不方便,所以要定义一个4×4的数组,第0行第0列不使用,如下图红框内的行和列不使用。这样就方便玩家选择落子坐标。

在这里插入图片描述

1.如何判定输赢?

三子棋的规则很简单,只要判断每一行、每一列、对角线中是否有连成线的,即为赢。
代码思路:
1、判断是否有相同的行并且不能为空格(数组初始化为空格)。
2、判断是否有相同的列并且不能为空格。
3、判断主次对角线是否相同并且不能为空格。
4、棋盘下满后是否为平局。
代码如下:

//判断谁赢,'X'表示玩家赢,'0'表示电脑赢,'p'表示平局
char IsWin(char map[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	int ret = IsFull(map, ROWS, COLS);
	//判断行
	for (i = 1; i < row; i++)
	{
		if (map[i][1] == map[i][2] && map[i][2] == map[i][3] && map[i][1] != ' ')
		{
			return map[i][1];
		}
	}
	//判断列
	for (j = 1; j < col; j++)
	{
		if (map[1][j] == map[2][j] && map[2][j] == map[3][j] && map[1][j] != ' ')
		{
			return map[1][j];
		}
	}
	//判断主对角线
	if (map[1][1] == map[2][2] && map[2][2] == map[3][3] && map[1][1] != ' ') 
	{
		return map[1][1];
	}
	//判断次对角线
    if (map[1][3] == map[2][2] && map[2][2] == map[3][1] && map[1][3] != ' ')
	{
		return map[1][3];
	}
	//判断是否为平局
	 if (ret == 0)
	{
		return 'p';
	}
	else
	{
		return ' ';//防止编译器报错
	}
}

注意:
1、三个值比较时不可以使用连等,==是关系操作符,==是从左到右进行运算的,计算表达式 a == b == c 时,首先会进行逻辑运算 a == b得出逻辑值1或0,得到的结果作为返回值,然后进行逻辑运算 “返回值” == c 得出逻辑值1或0,作为整个表达式的返回值。所以不能这样用。

2、判断完是否平局后,要加一个else,返回一个字符,不然编译器会报错:
在这里插入图片描述
因为编译器认为还有一种情况:当所有的if都不满足时,没有返回值,所以要加一个else返回一个对结果没有影响的字符。

二、具体代码实现

1.头文件game.h

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

#define ROW 3
#define COL  3
#define ROWS ROW+1
#define COLS  COL+1

//初始化棋盘
void InitMap(char map[][COLS], int row, int col);

//打印棋盘
void DisplayMap(char map[][COLS], int row, int col);

//玩家落子
void PlayerMove(char map[][COLS], int row, int col);

//电脑落子
void ComputerMove(char map[][COLS], int row, int col);

//判断棋盘是否满,0表示满,1表示未满
int IsFull(char map[][COLS], int row, int col);

//判断谁赢,'X'表示玩家赢,'0'表示电脑赢,'p'表示平局
char IsWin(char map[][COLS], int row, int col);

2.主函数main.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"game.h"

void menu()
{
	printf("***********************************************\n");
	printf("********            三子棋            *********\n");
	printf("***********************************************\n");
	printf("***************      1.play      **************\n");
	printf("***************      0.exit      **************\n");
	printf("***********************************************\n");
}

void game()
{
	char map[ROWS][COLS];
	char ret = ' ';//用来接收IsWin()的返回值
	InitMap(map, ROWS, COLS);//初始化棋盘
	DisplayMap(map, ROWS, COLS);//打印棋盘
	do
	{
		PlayerMove(map, ROWS, COLS);//玩家落子	
		ret = IsWin(map, ROWS, COLS);
		if (ret == 'X')
		{
			printf("玩家赢......\n");
			break;
		}
		else if (ret == 'p')
		{
			printf("平局......\n");
			break;
		}
		ComputerMove(map, ROWS, COLS);//电脑落子
		ret = IsWin(map, ROWS, COLS);
		if (ret == '0')
		{
			printf("电脑赢......\n");
			break;
		}
	}while (IsFull(map,ROWS,COLS));//棋盘已满,结束循环
}

void test()
{
	int input = 0;
	srand((unsigned)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);
}

int main()
{
	test();
	return 0;
}

3.函数game.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"game.h"

void InitMap(char map[][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 1; i < row; i++)
	{
		for (j = 1; j < col; j++)
		{
			map[i][j] = ' ';
		}
	}
}

void DisplayMap(char map[][COLS], int row, int col)
{
	int i = 0; 
	int j = 0;
	for (i = 1; i < row; i++)
	{
		for (j = 1; j <= col; j++)
		{
			printf("%3c",map[i][j]);
			if (j < col - 1)
			{
				printf(" | ");
			}
		}
		printf("\n");
		if (i < row - 1)
		{
			for (j = 1; j < col; j++)
			{
				printf(" --- ");
			}
		}	
		printf("\n");
	}
}

void PlayerMove(char map[][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("玩家走->\n");
	while (1)
	{
		printf("请选择落子坐标->");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= 3 && y >= 1 && y <= 3)
		{
			if (map[x][y] == ' ') 
			{
				map[x][y] = 'X';
				break;//落子成功就跳出循环
			}
			else
			{
				printf("该位置已被占用请重新输入->\n");
			}
		}
		else
		{
			printf("坐标非法,请重新输入......\n");
		}
	}
	DisplayMap(map, ROWS, COLS);
}

void ComputerMove(char map[][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("电脑走->\n");
	while (1)
	{
		x = rand() % 3 + 1;//1-3
		y = rand() % 3 + 1;//1-3
		if (map[x][y] == ' ')
		{
			map[x][y] = '0';
			break;
		}
	}
	DisplayMap(map, ROWS, COLS);
 }

//判断棋盘是否满,0表示满,1表示未满
int IsFull(char map[][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	int count = 0;//计算落子过的格子
	for (i = 1; i < row; i++)
	{
		for (j = 1; j < col; j++)
		{
			if (map[i][j] == 'X' || map[i][j] == '0')
			{
				count++;
			}
		}
	}
	if (count == ROW * COL)
	{
		return 0;//满
	}
	else
	{
		return 1;
	}
}

//判断谁赢,'X'表示玩家赢,'0'表示电脑赢,'p'表示平局
char IsWin(char map[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	int ret = IsFull(map, ROWS, COLS);
	//判断行
	for (i = 1; i < row; i++)
	{
		if (map[i][1] == map[i][2] && map[i][2] == map[i][3] && map[i][1] != ' ')
		{
			return map[i][1];
		}
	}
	//判断列
	for (j = 1; j < col; j++)
	{
		if (map[1][j] == map[2][j] && map[2][j] == map[3][j] && map[1][j] != ' ')
		{
			return map[1][j];
		}
	}
	//判断主对角线
	if (map[1][1] == map[2][2] && map[2][2] == map[3][3] && map[1][1] != ' ') 
	{
		return map[1][1];
	}
	//判断次对角线
    if (map[1][3] == map[2][2] && map[2][2] == map[3][1] && map[1][3] != ' ')
	{
		return map[1][3];
	}
	//判断是否为平局
	 if (ret == 0)
	{
		return 'p';
	}
	else
	{
		return ' ';//防止编译器报错
	}
}

4、运行结果示例

在这里插入图片描述在这里插入图片描述


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值