三子棋游戏

三子棋

  • 实现的逻辑
    • test.c
      • 主函数mian()
      • 菜单meum()
      • 游戏逻辑game()
        • 初始化棋盘Init_board()
        • 打印棋盘Display_board()
        • 玩家下棋Player()
        • 电脑下棋Computer()
        • 判断输赢 is_winner()
    • test.c的全部代码
  • 功能的实现
    • game.c
      • Init_board()的实现
      • Display_board()的实现
      • Player()的实现
      • Computer()的实现
      • is_winner()的实现
        • 行的判断
        • 列的判断
        • 对角线的判断
        • 平局的判断
        • 游戏继续
    • game.c全部代码
  • 头文件game.h

实现的逻辑

test.c

主函数mian()


int main()
{
	srand((unsigned int)time(NULL));//产生一个随机数,以供电脑下棋
	int input = 0;
	//菜单
	meun();
	do
	{
		printf("请选择数字>\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("游戏开始\n");
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误,请重新选择\n");
			break;
		}

	} while (input);

	return 0;
}

此处需要注意的是要用到rand()这个函数,关于这个函数的使用可以参考rand()

而使用这个函数必须首先用srand()

至于为什么在函数一开始就写srand(),是因为要产生一个随机数给电脑,以便电脑下棋。值得注意的是不能把srand()放在包含rand()函数的的前面,不然这个随机数就不再随机。

菜单meum()

void meun()
{
	printf("*************************\n");
	printf("**** 1.Play  0.Exit *****\n");
	printf("*************************\n");

}

调用meum(),让玩家知道如何开始

游戏逻辑game()

game()这个函数主要包括

初始化棋盘Init_board()

//棋盘是一个二维数组,首先申请一个二维数组
char board[ROW][COL] = { 0 };
//初始化棋盘
Init_board(board, ROW, COL);

打印棋盘Display_board()

Display_board(board, ROW, COL);

玩家下棋Player()

Player(board, ROW, COL);

电脑下棋Computer()

Computer(board, ROW, COL);

判断输赢 is_winner()

//这里的ret是为了接受返回字符
//返回‘#’玩家赢
//返回‘*’玩家赢
//返回‘E’平局
//返回‘K'游戏继续
ret = is_winner(board, ROW, COL);
	if (ret != 'K')
		{
		//不是继续游戏,就表示有人赢或平局,那就退出循环
			break;
		}

test.c的全部代码

#define _CRT_SECURE_NO_WARNINGS 1

#include"game.h"

void meun()
{
	printf("*************************\n");
	printf("**** 1.Play  0.Exit *****\n");
	printf("*************************\n");

}

void game()
{
	char ret = 0;
	char board[ROW][COL] = { 0 };
	//初始化棋盘
	Init_board(board, ROW, COL);
	//打印棋盘
	Display_board(board, ROW, COL);
	//下棋
	while (1)
	{
		//玩家下棋
		Player(board, ROW, COL);
		//判断输赢
		ret = is_winner(board, ROW, COL);
		if (ret != 'K')
		{
			break;
		}
		Display_board(board, ROW, COL);
	

		//电脑下棋
		Computer(board, ROW, COL);
		//判断输赢
		ret = is_winner(board, ROW, COL);
		if (ret != 'K')
		{
			break;
		}
		Display_board(board, ROW, COL);
		
	}


	if (ret == '#')
	{
		printf("玩家赢\n");
	}
	else if (ret == '*')
		printf("电脑赢\n");
	else
	{
		printf("平局\n");
	}
	Display_board(board, ROW, COL);


}


int main()
{
	srand((unsigned int)time(NULL));
	int input = 0;
	//菜单
	meun();
	do
	{
		printf("请选择数字>\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("游戏开始\n");
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误,请重新选择\n");
			break;
		}

	} while (input);

	return 0;
}

功能的实现

game.c

Init_board()的实现

//传一个二维数组,行,列
//使棋盘都为空格
void Init_board(char board[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < col; j++)
		{
			board[i][j] = ' ';
		}
	}
}

Display_board()的实现

三子棋游戏_第1张图片
我们把圈起来的看成一行
值得注意的是,这一行包含两个部分
第一部分:
三子棋游戏_第2张图片
一个空格一个字符再加一个空格 # 在加一条 |
第二部分
在这里插入图片描述
三个 在加一个 |

首先我们打印第一部分,然后换行,在打第二部分

void Display_board(char board[ROW][COL], int row, int col)
{
	int i = 0;//行
	for (i = 0; i < row; i++)
	{
		int j = 0;//列
		//打印字符
		for (j = 0; j < col; j++)
		{
			printf(" %c ", board[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");
		}
		
	}

}

这里来解释为什么有 if(j 我们注意最后一列我们是不需要 | 所以增加一个判断
在这里插入图片描述

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

		}

而这里的**if(i 三子棋游戏_第3张图片

//打印分割线
if (i < row - 1)
		{
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)
				{
					printf("|");
				}			

			}
			printf("\n");
		}

Player()的实现

//玩家下棋
void Player(char board[ROW][COL], int row, int col)
{
//玩家输入坐标
	int x = 0; 
	int y = 0;
	while (1)
	{
		printf("玩家请下棋>");
		scanf("%d %d", &x, &y);
		//判断坐标是否合法
		if ((x > 0 && x <= row) && (y > 0 && y <= col))
		{
			//该坐标是否被占用
			//因为玩家不知道数组是从0开始的,所以x-1,y-1,就相当于下在**数组的第一行第一列**的位置
			if (board[x - 1][y - 1] == ' ')
			{
				//玩家下棋,输入‘ # ’,并跳出while()
				board[x - 1][y - 1] = '#';
				break;
			}
			else
			{
				printf("坐标被占用,请重新输入\n");
			}
		
		}
		else
		{
			printf("坐标非法,请重新输入\n");
		}
	}

}

Computer()的实现

void Computer(char board[ROW][COL], int row, int col)
{
	printf("电脑下棋>\n");
	while (1)
	{
		int x = rand() % row;
		int y = rand() % col;
		if (board[x][y] == ' ')
		{
		//电脑下棋输入' * '
			board[x][y] = '*';
			break;
		}
	}

}

使用rand()产生随机数,这里不懂,可以看看上文,至于为什么处于row和col,是因为是为了得到符合棋盘的范围,可以试着除一下,产生0~2的随机数,

is_winner()的实现

这里实现了动态的判断输赢
//返回‘#’玩家赢
//返回‘*’玩家赢
//返回‘E’平局
//返回‘K’游戏继续

行的判断

//行
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col-1; j++)
		{
			if ((board[i][j] == board[i][j + 1]) && (board[i][j + 1] != ' '))
			{
				if (j == col - 2)
				{
					return board[i][j];
				}
			}
			else
			{
				break;
			}
		}
		
		
	}

for循环中的j是因为,board[i][j] == board[i][j + 1]这个代码可以保证这一行都可以检测到,假如是三子棋
当j=0的时候,检测第一列和第二列,当j=1的时候,检测了第一列和第二列。
注意 if (j == col - 2)
{
return board[i][j];
}

还是假如是一个三子棋当j=1的时候,这一行都检测完了,就可以返回这个字符了。

列的判断

列和行的思想差不多,这里不再叙述

for (j = 0; j < col; j++)
	{
		for (i = 0; i < row - 1; i++)
		{
			if((board[i][j] == board[i + 1][j]) && (board[i + 1][j] != ' '))
			{
				if (i == row - 2)
				{
					return board[i][j];
				}
			}
			else
			{
				break;
			}		
		}
	}

对角线的判断

return的思想和行列都是一样的,
左对角线,坐标11 22 33;
右对角线对角线13 22 31

//左对角线
	for (i = 0; i < row-1; i++)
	{
		j = i;
		if ((board[i][j] == board[i + 1][j + 1]) && (board[i + 1][j + 1] != ' '))
		{
			if (i == row - 2)
			{
				return board[i][j];
			}
		}
		else
		{
			break;
		}
	}

//右对角线
	for(i = 0; i < row; i++)
	{
	//举例当第一行的时候坐标是1 3
	//在数组的位置就是0 2
		j = col - 1 - i;
		if ((board[i][j] == board[i + 1][j - 1]) && (board[i + 1][j - 1] != ' '))
		{
			if (i == row - 2)
			{
				return board[i][j];
			}
		}
		else
		{
			break;
		}

	}

平局的判断

	if (IsFull(board, row, col))
	{
	//‘E’代表平局
		return 'E';
	}

这里创建了一个IsFull()的函数,如果棋盘满了返回1,否则返回0

//判断棋盘是否满
//满了返回1
//没满返回0
int IsFull(char board[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 (board[i][j] == ' ')
				return 0;
		}
	}
	return 1;
}

游戏继续

	//游戏继续
	return 'K';

game.c全部代码

#define _CRT_SECURE_NO_WARNINGS 1

#include"game.h"


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

//打印棋盘
void Display_board(char board[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		//打印字符
		for (j = 0; j < col; j++)
		{
			printf(" %c ", board[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 Player(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	while (1)
	{
		printf("玩家请下棋>");
		scanf("%d %d", &x, &y);
		if ((x > 0 && x <= row) && (y > 0 && y <= col))
		{
			if (board[x - 1][y - 1] == ' ')
			{
				board[x - 1][y - 1] = '#';
				break;
			}
			else
			{
				printf("坐标被占用,请重新输入\n");
			}
		
		}
		else
		{
			printf("坐标非法,请重新输入\n");
		}
	}
	

}

//电脑下棋
void Computer(char board[ROW][COL], int row, int col)
{
	printf("电脑下棋>\n");
	while (1)
	{
		int x = rand() % row;
		int y = rand() % col;
		if (board[x][y] == ' ')
		{
			board[x][y] = '*';
			break;
		}
	}

}


//判断棋盘是否满
//满了返回1
//没满返回0
int IsFull(char board[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 (board[i][j] == ' ')
				return 0;
		}
	}
	return 1;
}

//判断输赢
char is_winner(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	//行
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col-1; j++)
		{
			if ((board[i][j] == board[i][j + 1]) && (board[i][j + 1] != ' '))
			{
				if (j == col - 2)
				{
					return board[i][j];
				}
			}
			else
			{
				break;
			}
		}
		
		
	}
	//列
	for (j = 0; j < col; j++)
	{
		for (i = 0; i < row - 1; i++)
		{
			if((board[i][j] == board[i + 1][j]) && (board[i + 1][j] != ' '))
			{
				if (i == row - 2)
				{
					return board[i][j];
				}
			}
			else
			{
				break;
			}		
		}
	}

	//左对角线
	for (i = 0; i < row-1; i++)
	{
		j = i;
		if ((board[i][j] == board[i + 1][j + 1]) && (board[i + 1][j + 1] != ' '))
		{
			if (i == row - 2)
			{
				return board[i][j];
			}
		}
		else
		{
			break;
		}
	}
	//右对角线
	for(i = 0; i < row; i++)
	{
		j = col - 1 - i;
		if ((board[i][j] == board[i + 1][j - 1]) && (board[i + 1][j - 1] != ' '))
		{
			if (i == row - 2)
			{
				return board[i][j];
			}
		}
		else
		{
			break;
		}


	}


	//棋盘满了,平局
	if (IsFull(board, row, col))
	{
		return 'E';
	}

	//游戏继续
	return 'K';


}

头文件game.h

#pragma once

#include
#include
#include
#define ROW 3
#define COL 3

//声明棋盘
void Init_board(char board[ROW][COL], int row, int col);

//打印棋盘
void Display_board(char board[ROW][COL], int row, int col);

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

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

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

#define ROW 3
#define COL 3
是为了动态设计棋盘,根据玩家,自己的想法修改棋盘大小;

自此三子棋小游戏写完了,希望能够有所帮助大家,点个赞呗!友友们!

三子棋游戏_第4张图片

你可能感兴趣的:(C语言从入门到精通,游戏,c语言,c++)