C语言实现简单的五子棋

#define _CRT_SECURE_NO_WARNINGS 1
#define __STDC_WANT_LIB_EXT1_ 1
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<windows.h>
//┌ ┬ ┐├ ┼ ┤└ ┴ ┘│─●○
//属性设置:0—白棋  1—黑棋  2—无棋
int board[20][20];//注意这个二维数组为全局更方便
int Board(int row, int column, int player, int cover, int remind);//row横向,column竖向,player为玩家代号
void operation();      //操作棋子的函数(主要)                   //cover为检测棋子重叠的参数,remind是输赢提示
int judge(char, int, int, int, int);//判断操作是移动还是回车,检测棋子重叠
int rule(int, int, int);            //判断输赢,棋子算法
void menu();                        //菜单
int main()
{                                 //em。。我这个main函数似乎过于简洁?
	menu();                         //这也看出本程序的各个函数独立性不是很高
	operation();
	return 0;
}
void menu()
{
	char ch;
loop1:
	system("cls");
	printf("\n\n\n\n\n\n\n");
	for (int i = 0; i < 2; i++)
	printf("                                         *************************                   \n");
	printf("                                         *   ★和轩来玩五子棋★  *                   \n");
	printf("                                         *       1.开始游戏      *                   \n");
	printf("                                         *       2.退出游戏      *                   \n");
	printf("                                         *       3.游戏帮助      *                   \n");
	printf("                                         * ★  ★   ★   ★   ★ *                   \n");
	printf("                                         *************************                   \n");
	ch = getch();
	if(ch=='1')
	{ }
	else if(ch == '2')
	{
		system("cls");
		printf("\n\n\n\n\n\n\n");
		printf("                                         *************************                   \n");
		printf("                                         *   ★和轩来玩五子棋★  *                   \n");
		printf("                                         *         再见!        *                   \n");
		printf("                                         * ★  ★   ★   ★   ★ *                   \n");
		printf("                                         *************************                   \n");
		exit(1);
	}
	else if (ch == '3')
	{
		system("cls");
		printf("\n\n\n\n\n\n\n\n\n\n\n\n");
		printf("                                *****************************************************\n");
		printf("                                *  操作方法:←↑↓→移动棋子,回车放棋.            *\n");
		printf("                                *  游戏声明:本游戏仅支持玩家对战,人机模式敬请期待 *\n");
		printf("                                *          (快打赏轩哥催更吧(づ ̄3 ̄)づ╭~)     *\n");
		printf("                                *                                                   *\n");
		printf("                                *                  按空格返回菜单                   *\n");
		printf("                                *****************************************************\n");
		if (getch() == 32)
			goto loop1;
		else
	{
		system("cls");
		printf("\n\n\n\n\n\n\n\n\n\n\n\n");
		printf("                                             输入错误,请重新输入!");
		Sleep(3000);
		goto loop1;
	}
	}
	
}
int Board(int row, int column, int player, int If_cover, int remind)
{
	printf("\n\n\n\n");
	//注意!本棋盘是每一次操作后重新打印的棋盘,是动态的,而不是三子棋那样的死棋盘
	//边界和角落特殊处理!而且打印必须按顺序!从上往下!否则打印出来会乱七八糟!注意!每个图标后面都有空格,否则重叠
		//下面为左上角
	switch (board[0][0])
	{
	case 0:printf("○");
		break;
	case 1:printf("●");
		break;
	case 2:printf("┌ ");
		break;
	}
	//下面为上边界
	for (int i = 1; i < 19; i++)
	{
		switch (board[0][i])
		{
		case 0:printf("○");
			break;
		case 1:printf("●");
			break;
		case 2:printf("┬ ");
			break;
		}
	}
	//下面为右上角
	switch (board[0][19])
	{
	case 0:printf("○");
		break;
	case 1:printf("●");
		break;
	case 2:printf("┐");
		break;
	}
	printf("\n");
	//下面为第1排到第18排(前面是第0排)
	for (row = 1; row < 19; row++)
	{
		//下面是特殊处理左边界
		switch (board[row][0])
		{
		case 0:printf("○");
			break;
		case 1:printf("●");
			break;
		case 2:printf("├ ");
			break;
		}

		//下面是打印十字
		for (column = 1; column < 19; column++)
		{
			switch (board[row][column])
			{
			case 0:printf("○");
				break;
			case 1:printf("●");
				break;
			case 2:printf("┼ ");
				break;
			}
		}
		//下面是打印右边界
		switch (board[row][19])
		{
		case 0:printf("○");
			break;
		case 1:printf("●");
			break;
		case 2:printf("┤ ");
			break;
		}
		if (row == 8)
			printf("          ************************************** ");
		if (row == 9)
			printf("          *                                    * ");
		if (row == 10)
			printf("          *操作方法:←↑↓→移动棋子,回车放棋*");
		if (row == 11 || row == 12)
			printf("          *                                    *");
		if (row == 13)
		{
			if (If_cover == 1)
			printf("          *提示:此处已有棋子,请选择其他位置: *");
			else if (remind == 1)
			{
			printf("\a          *提示: 玩家1获胜!                  *");
			}
			else if (remind == 2)
			{
				printf("\a          *提示: 玩家2获胜!                  *");
			}
			else
				printf("          *提示: 玩家%d请下棋                  *", player == 1 ? 1 : 2);
		}
		if (row == 14)
		{
			if ((remind == 1) || (remind == 2))
				printf("          *按空格键重新开局,否则结束游戏!    *");
			else
				printf("          *                                    *");
		}
		if (row == 15)
		{
			    printf("          **************************************");
		}
		printf("\n");
	}
	//下面是打印19排左下角
	switch (board[19][0])
	{
	case 0:printf("○");
		break;
	case 1:printf("●");
		break;
	case 2:printf("└ ");
		break;
	}
	//下面为下边界
	for (int i = 1; i < 19; i++)
	{
		switch (board[19][i])
		{
		case 0:printf("○");
			break;
		case 1:printf("●");
			break;
		case 2:printf("┴ ");
			break;
		}
	}
	//下面为右下角
	switch (board[19][19])
	{
	case 0:printf("○");
		break;
	case 1:printf("●");
		break;
	case 2:printf("┘ ");
		break;
	}
	printf("\n");
	if ((remind == 1) || (remind == 2))
	{
		if (getch() == 32)
			return 2;
	}
		
}
void operation()
{

	loop:
	//初始化棋盘
	for (int count = 0; count < 400; count++)
		*(*board + count) = 2;
	int player;
	int Judge = 0;
	int remind = 0;
	int row = 0, column = 0;
	for (int count = 1; count <= 400; count++)
	{
		player = count % 2;
		if (count == 1)
		{
			board[0][0] = 0;
			system("cls");
			Board(row, column, count, Judge, remind);
			board[0][0] = 2;                                 //使初始化的棋盘左上角有一个棋子,从此处开始移动棋子
		}
		//下面是移动棋子的操作      上下左右键对应ASCII码值: 72-up 80-down 75-left 77-right
		int k = 1;                           //用作下面退出while
		int copy = 0;
		char move;
		int If_cover = 0;
		while (k)
		{

			move = getch();
			switch (move)
			{
			case 75:
				system("cls");
				column = column - 1;
				if (column < 0)
					column = 19;
				copy = board[row][column];
				board[row][column] = (player == 1 ? 0 : 1);
				If_cover = 0;
				Board(row, column, player, If_cover, remind);
				judge(move, row, column, player, copy);
				break;
			case 77:
				system("cls");
				column = column + 1;
				if (column > 19)
					column = 0;
				copy = board[row][column];
				board[row][column] = (player == 1 ? 0 : 1);
				If_cover = 0;
				Board(row, column, player, If_cover, remind);
				judge(move, row, column, player, copy);
				break;
			case 80:
				system("cls");
				row = row + 1;
				if (row > 19)
					row = 0;
				copy = board[row][column];
				board[row][column] = (player == 1 ? 0 : 1);
				If_cover = 0;
				Board(row, column, player, If_cover, remind);
				judge(move, row, column, player, copy);
				break;
			case 72:
				system("cls");
				row = row - 1;
				if (row < 0)
					row = 19;
				copy = board[row][column];
				board[row][column] = (player == 1 ? 0 : 1);
				If_cover = 0;
				Board(row, column, player, If_cover, remind);
				judge(move, row, column, player, copy);
				break;
			case 13:
				Judge = judge(move, row, column, player, copy);
				if (Judge == 1)
				{
					If_cover = 1;
					system("cls");
					Board(row, column, player, If_cover, remind);
					continue;
				}
				remind = rule(row, column, player);
				if ((remind == 2) || (remind == 1))
				{
					int k = 0;
					system("cls");
					k = Board(row, column, player, If_cover, remind);
					if (k == 2)
					{
						goto loop;
					}
					else
					{
						system("cls");
						printf("\n\n\n\n\n\n\n");
						printf("                                         *************************                   \n");
						printf("                                         *   ★和轩来玩五子棋★  *                   \n");
						printf("                                         *         再见!        *                   \n");
						printf("                                         * ★  ★   ★   ★   ★ *                   \n");
						printf("                                         *************************                   \n");
						exit(1);
					}
				}
				int copy_player = player;
				if (copy_player == 1)                 //下面6行代码是为了使按回车放棋后能够马上同步提示,而不是继续移动后才更新!
					copy_player = 0;
				else
					copy_player = 1;
				system("cls");
				Board(row, column, copy_player, If_cover, remind);
				k = 0;  //k=0终止while循环!注意下面的break是终止switch的!
				break;
			}
		}
	}
}
int judge(char move, int row, int column, int player, int copy)    //此函数是用来判断是移步还是定步,是否重叠
{

	if (move == 72 || move == 75 || move == 77 || move == 80)
	{
		if ((board[row][column] == 1) || (board[row][column] == 0))    //这是为了使移动棋子时如果压到已下的棋子,可以防止被覆盖属性
		{
			board[row][column] = copy;                           //只要不回车,就保持原属性不变!
		}
		else
			board[row][column] = 2;

	}
	if (move == 13)                                             //检测到回车
	{
		if (board[row][column] == 2)                           //如果此处是空,则放棋
			board[row][column] = (player == 1 ? 0 : 1);
		else
		{
			return 1;                                         //不空,返回1,提示有棋子了,重新选择
		}
	}
}
int rule(int row, int column, int player)
{
	if (player == 1)
	{
		//横向检查player1
		int copy_row = row;
		int copy_column = column;
		int tem_association1 = 0;
		for (copy_column = 0; copy_column < 20; copy_column++)
		{
			if (board[row][copy_column] == 0)
			{
				tem_association1++;
			}
			if (board[row][copy_column] != 0)
			{
				tem_association1 = 0;
			}
			if (tem_association1 == 5)
			{
				return 1;
			}
		}
		//竖向检测player1
		copy_row = row;
		copy_column = column;
		tem_association1 = 0;
		for (copy_row = 0; copy_row < 20; copy_row++)
		{
			if (board[copy_row][column] == 0)
				tem_association1++;
			if (board[copy_row][column] != 0)
				tem_association1 = 0;
			if (tem_association1 == 5)
			{
				return 1;
			}
		}
		//斜向1处理player1                                          //这个斜向检测算法只需最多检测8个位置
		int count1 = 0, count2 = 0, counts = 0;                     //      *
		for (count1 = 1; count1 <= 5;)                              //       *
		{															//        *
			if ((row == 0) || (column == 0)) //起始在边界则中断     //         *
				break;                                              //          #   从#向两边检测,遇到非本方棋子则中断,满4则赢
			if (((row - count1) == 0) || ((column - count1) == 0))  //           *  每次斜向检测分为两部分,一是向左上(右上),二是向右下(左下)
			{                                                       //            *
				if (board[row - count1][column - count1] == 0)      //             *
				{                                                   //              *
					count1++;
					break;
				}
				else
					break;
			}
			else
			{
				if (board[row - count1][column - count1] == 0)
				{
					count1++;
					continue;
				}
				else
					break;
			}
		}
		//斜向2处理player1
		for (count2 = 1; count2 <= 5;)
		{
			if ((row == 19) || (column == 19))
				break;
			if (((row + count2) == 19) || ((column + count2) == 19))
			{
				if (board[row + count2][column + count2] == 0)
				{
					count2++;
					break;
				}
				else
					break;
			}
			else
			{
				if (board[row + count2][column + count2] == 0)
				{
					count2++;
					continue;
				}
				else
					break;
			}
		}
		counts = count1 + count2 - 2;
		if (counts >= 4)
		{
			return 1;
		}
		//斜向2处理玩家1
		count1 = 0, count2 = 0, counts = 0;
		for (count1 = 1; count1 <= 5;)
		{
			if ((row == 0) || (column == 19))
				break;
			if (((row - count1) == 0) || ((column + count1) == 0))
			{
				if (board[row - count1][column + count1] == 0)
				{
					count1++;
					break;
				}
				else
					break;
			}
			else
			{
				if (board[row - count1][column + count1] == 0)
				{
					count1++;
					continue;
				}
				else
					break;
			}
		}
		for (count2 = 1; count2 <= 5;)
		{
			if ((row == 19) || (column == 0))
				break;
			if (((row + count2) == 19) || ((column - count2) == 0))
			{
				if (board[row + count2][column - count2] == 0)
				{
					count2++;
					break;
				}
				else
					break;
			}
			else
			{
				if (board[row + count2][column - count2] == 0)
				{
					count2++;
					continue;
				}
				else
					break;
			}
		}
		counts = count1 + count2 - 2;
		if (counts >= 4)
		{
			return 1;
		}
	}
	if (player == 0)
	{
		//横向检查player2
		int copy_row = row;
		int copy_column = column;
		int tem_association2 = 0;
		for (copy_column = 0; copy_column < 20; copy_column++)
		{
			if (board[row][copy_column] == 1)
			{
				tem_association2++;
			}
			if (board[row][copy_column] != 1)
			{
				tem_association2 = 0;
			}
			if (tem_association2 == 5)
			{
				return 2;
			}
		}
		//竖向检测player2
		copy_row = row;
		copy_column = column;
		tem_association2 = 0;
		for (copy_row = 0; copy_row < 20; copy_row++)
		{
			if (board[copy_row][column] == 1)
				tem_association2++;
			if (board[copy_row][column] != 1)
				tem_association2 = 0;
			if (tem_association2 == 5)
			{
				return 2;
			}
		}
		//斜向1处理player2
		int count1 = 0, count2 = 0, counts = 0;
		for (count1 = 1; count1 <= 5;)
		{
			if ((row == 0) || (column == 0))
				break;
			if (((row - count1) == 0) || ((column - count1) == 0))
			{
				if (board[row - count1][column - count1] == 1)
				{
					count1++;
					break;
				}
				else
					break;
			}
			else
			{
				if (board[row - count1][column - count1] == 1)
				{
					count1++;
					continue;
				}
				else
					break;
			}
		}
		for (count2 = 1; count2 <= 5;)
		{
			if ((row == 19) || (column == 19))
				break;
			if (((row + count2) == 19) || ((column + count2) == 19))
			{
				if (board[row + count2][column + count2] == 1)
				{
					count2++;
					break;
				}
				else
					break;
			}
			else
			{
				if (board[row + count2][column + count2] == 1)
				{
					count2++;
					continue;
				}
				else
					break;
			}
		}
		counts = count1 + count2 - 2;
		if (counts >= 4)
		{
			return 2;
		}
		//斜向2处理玩家2
		count1 = 0, count2 = 0, counts = 0;
		for (count1 = 1; count1 <= 5;)
		{
			if ((row == 0) || (column == 19))
				break;
			if (((row - count1) == 0) || ((column + count1) == 0))
			{
				if (board[row - count1][column + count1] == 1)
				{
					count1++;
					break;
				}
				else
					break;
			}
			else
			{
				if (board[row - count1][column + count1] == 1)
				{
					count1++;
					continue;
				}
				else
					break;
			}
		}
		for (count2 = 1; count2 <= 5;)
		{
			if ((row == 19) || (column == 0))
				break;
			if (((row + count2) == 19) || ((column - count2) == 0))
			{
				if (board[row + count2][column - count2] == 1)
				{
					count2++;
					break;
				}
				else
					break;
			}
			else
			{
				if (board[row + count2][column - count2] == 1)
				{
					count2++;
					continue;
				}
				else
					break;
			}
		}
		counts = count1 + count2 - 2;
		if (counts >= 4)
		{
			return 2;
		}
	}
	return 3;           //必须要return 非1或2的数,否则会默认return 1
}



容错性相对较高,仅支持玩家对战

posted @ 2022-07-31 09:28  QuanHa  阅读(47)  评论(0)    收藏  举报