【C】三子棋游戏代码,含大量文字注释

三子棋游戏

代码:

game.h
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include <windows.h>

// 定义棋盘的大小
#define ROW 3// define定义标识符常量,通常用全大写,无分号
#define COL 3// 类型为--int
#define NUM 3// 几子棋

// 函数1--初始化棋盘--先用空格填满即将要下棋的位置
void InitBoard(char board[ROW][COL], int row, int col);

// 函数2--打印棋盘格
void DisplayBoard(char board[ROW][COL], int row, int col);

// 函数3--玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col);

// 函数4--电脑下棋--找没棋的位置“随机”下
void ComputerMove(char board[ROW][COL], int row, int col);

// 函数5--判断输赢
int Jugdement(char board[ROW][COL], int row, int col);
game.c
#include "game.h"

// 函数1--初始化棋盘--先用空格填满即将要下棋的位置
void InitBoard(char board[ROW][COL], int row, int col)
{
	int i, j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			board[i][j] = ' ';//单个字符用'',字符串用""
		}
	}
}

// 函数2--打印棋盘格
void DisplayBoard(char board[ROW][COL], int row, int col)
{
	int i, j = 0;
	for (i = 0; i < ROW; i++)
	{
		if (i < (ROW - 1))
		{
			for (j = 0; j < COL - 1; j++)//000|*(row-1) + 000  打印数据信息行
			{
				printf(" %c |",board[i][j]);
			}
			printf(" %c \n",board[i][j]);

			for (j = 0; j <COL - 1; j++)//---|*(row-1) + ---  打印分隔行
			{
				printf("---|");
			}
			printf("---\n");
		}
		else
		{
			for (j = 0; j < COL - 1; j++)//000|*(row-1) + 000  打印数据信息行
			{
				printf(" %c |", board[i][j]);
			}
		    printf(" %c \n", board[i][j]);
		}
	}
}

// 函数3--玩家下棋:
// 下棋:给二维数组里对应位置赋值;如果超出了或者对应位置已有棋子则提示重下
// 错误版
// 逻辑没问题,但是把传进来的关于表格数据的变量改变做其他用途,暂时来说结果相同,但是思路不正确,如果ROW\COL改了就不对了
//void PlayerMove(char board[ROW][COL], int row, int col)
//{
//	printf("玩家下棋,请输入坐标:>");
//	scanf("%d%d", &row, &col);//玩家输入1~3的数字 
//	if (row <= 3 && col <= 3)
//	{
//		if (board[row-1][col-1] == ' ')
//		{
//			board[row-1][col-1] = '@';
//			DisplayBoard(board, ROW, COL);//打印棋盘
//		}
//		else
//			printf("该位置已有棋子!\n");
//	}
//	else
//		printf("输入错误请重新输入!\n");
//}

// 正确版
void PlayerMove(char board[ROW][COL], int row, int col)
{

	    int x = 0;
	    int y = 0;
		printf("玩家下棋,请输入坐标:>");
		scanf("%d %d", &x, &y);
		if (x <= row && y <= col)
		{
			if (board[x - 1][y - 1] == ' ')
			{
				board[x - 1][y - 1] = '@';
				system("cls");
				DisplayBoard(board, ROW, COL);
			}
			else
				printf("该坐标已有棋子,请重下!\n");
		}
		else
			printf("坐标非法,重新输入!\n");
}


// 函数4--电脑下棋--找没棋的位置“随机”下
// 关键词-随机-rand 函数,在程序主函数里设置一个 srand 函数-设置随机数生成的起点
void ComputerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	do
	{
		x = rand() % row;//0~2
		y = rand() % col;//0~2
		if (board[x][y] == ' ')
		{
			Sleep(500);
			printf("电脑下棋.\n");
			Sleep(1000);
			board[x][y] = '*';
			system("cls");
			DisplayBoard(board, ROW, COL);
			break;
		}
	} while (1);
	// 怎么让棋盘满的时候程序停下来呢?先放着
}


函数5--判断输赢
第一版--遍历,纯属暴力解法......
//int Jugdement(char board[ROW][COL], int row, int col)
//{
//	int i = 0;
//	int j = 0;
//	int n = 0;
//	//
//	for (i = 0; i < ROW; i++)
//	{
//		//case 1:横着判断,[i][j]为左一
//		for (j = 0; j < COL; j++)
//		{
//			for (n = 1; n < NUM  && j + n <= ROW; n++)
//			{
//				if (board[i][j] == board[i][j + n] && (board[i][j] == '@' || board[i][j] == '*'))
//					continue;
//				else
//					break;
//			}
//			if (n == NUM)
//			{
//				printf("%d颗棋子成一条直线\n",NUM);
//				break;//只跳出了这一层循环
//			}
//		}
//		if (n == NUM)
//			return 1;
//	
//		//case 2:竖着判断,[i][j]为上一
//		for (j = 0; j < COL; j++)
//		{
//			for (n = 1; n < NUM && i + n <= COL; n++)
//			{
//				if (board[i][j] == board[i + n][j] && (board[i][j] == '@' || board[i][j] == '*'))
//					continue;
//				else
//					break;
//			}
//			if (n == NUM)
//			{
//				printf("%d颗棋子成一条直线\n", NUM);
//				break;//只跳出了这一层循环
//			}
//		}
//		if (n == NUM)
//			return 1;
//
//		//case 3:朝右下方向斜着判断--[i][j]为左一
//		for (j = 0; j < COL; j++)
//		{
//			for (n = 1; n < NUM && i + n <= COL && j +  n<= ROW; n++)
//			{
//				if (board[i][j] == board[i + n][j + n] && (board[i][j] == '@' || board[i][j] == '*'))
//					continue;
//				else
//					break;
//			}
//			if (n == NUM)
//			{
//				printf("%d颗棋子成一条直线\n", NUM);
//				break;//只跳出了这一层循环
//			}
//		}
//		if (n == NUM)
//			return 1;
//
//		//case 4:朝左下方斜着判断--[i][j]为上一
//		for (j = 0; j < COL; j++)
//		{
//			for (n = 1; n < NUM && i + n <= COL && j - n >= 0; n++)
//			{
//				if (board[i][j] == board[i + n][j - n] && (board[i][j] == '@' || board[i][j] == '*'))
//					continue;
//				else
//					break;
//			}
//			if (n == NUM)
//			{
//				printf("%d颗棋子成一条直线\n", NUM);
//				break;//只跳出了这一层循环
//			}
//		}
//		if (n == NUM)
//			return 1;
//	}
//}

//函数5--判断输赢
//第二版--遍历,优化循环结构
int Jugdement(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	int n = 0;
	//
	for (i = 0; i < ROW; i++)
	{
		for (j = 0; j < COL; j++)
		{
			//case 1:横着判断,[i][j]为左一
			for (n = 1; n < NUM && j + n <= ROW; n++)
			{
				if (board[i][j] == board[i][j + n] && (board[i][j] == '@' || board[i][j] == '*'))
					continue;
				else
					break;
			}
			if (n == NUM)
			{
				printf("%d颗棋子成一条直线\n", NUM);
				break;//只跳出了这一层循环
			}

			//case 2:竖着判断,[i][j]为上一
			for (n = 1; n < NUM && i + n <= COL; n++)
			{
				if (board[i][j] == board[i + n][j] && (board[i][j] == '@' || board[i][j] == '*'))
					continue;
				else
					break;
			}
			if (n == NUM)
			{
				printf("%d颗棋子成一条直线\n", NUM);
				break;//只跳出了这一层循环
			}

			//case 3:朝右下方向斜着判断--[i][j]为左一
			for (n = 1; n < NUM && i + n <= COL && j + n <= ROW; n++)
			{
				if (board[i][j] == board[i + n][j + n] && (board[i][j] == '@' || board[i][j] == '*'))
					continue;
				else
					break;
			}
			if (n == NUM)
			{
				printf("%d颗棋子成一条直线\n", NUM);
				break;//只跳出了这一层循环
			}

			//case 4:朝左下方斜着判断--[i][j]为上一
			for (n = 1; n < NUM && i + n <= COL && j - n >= 0; n++)
			{
				if (board[i][j] == board[i + n][j - n] && (board[i][j] == '@' || board[i][j] == '*'))
					continue;
				else
					break;
			}
			if (n == NUM)
			{
				printf("%d颗棋子成一条直线\n", NUM);
				break;//只跳出了这一层循环
			}
			
		}
		if (n == NUM)
			return 1;
	}
}


test.c
#include "game.h"

// 游戏菜单
void menu()
{
	printf("************************\n");
	printf("*******  1.play  *******\n");
	printf("*******  0.exit  *******\n");
	printf("************************\n");
}

// 游戏逻辑
void game()
{
	// 定义一个二维数组,填入数组即“下棋”
	char board[ROW][COL] = { 0 };

	// 函数1--初始化棋盘--先用空格填满即将要下棋的位置
	InitBoard(board, ROW, COL);
	
	// 函数2--打印棋盘格
	DisplayBoard(board, ROW, COL);

	// 下棋(玩家先手)
	while(1)
	{
	// 函数3--玩家下棋
	PlayerMove(board, ROW, COL);// 不需要这里定义下棋的位置变量,在函数里定义就好了,这样才是满足这个函数使用逻辑的
	
	// 函数5--判断输赢
	int win = Jugdement(board, ROW, COL);
	if (win == 1)
	{
		Sleep(1000);
		printf("恭喜玩家胜利!\n\n\n再来一局~\n");
		break;
	}
	// 函数4--电脑下棋--找没棋的位置“随机”下
	ComputerMove(board, ROW, COL);
	
	//函数5--判断输赢
	Jugdement(board, ROW, COL);
	if (win == 1)
	{
		Sleep(1000);
		printf("电脑胜利~\n\n\n再来一局~\n");
		break;
	}
	}
}

// 主程序
int main()
{
	// 至少循环一次,用do...while结构
	int input = 0;
	srand((unsigned)time(NULL));// 设置时间生成的起点
	do
	{
		menu();
		printf("请选择并输入数字(1/0):>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			system("cls");
			game();// 封装在一个函数里,逻辑很清晰哦
			break;
		case 0:
			printf("退出游戏!\n");
			break;
		default:
			printf("输入错误,请重新输入!\n");
			break;
		}
	} while (input);

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值