三子棋进阶版(可自定义棋盘格大小,可选择玩n子棋)

一、 n字棋游戏规则

        在一个m*m的正方形棋盘格上先由玩家落子,然后电脑落子,当行,或者列,或者斜着连着的数量达到开局设置的n个子,则玩家或者电脑获胜,当棋盘格下满了以后平局。

二、游戏实现

(1)游戏整体流程:

        首先打印菜单,然后让玩家选择是否进入游戏还是退出游戏,如果进入游戏,创建棋盘格,玩家选择棋盘格大小,玩家选择玩几子棋,然后游戏开始,玩家落子,电脑落子判定胜负平,游戏结束,最后让玩家选择继续游戏还是退出游戏。

        本文使用玩家落子为 * ,电脑落子为 #  

(2)如何实现n子棋:

        在游戏开始之后创建整形int = 0,保存玩家想玩的n子棋。创建int row 和int col,保存玩家想玩的棋盘格

(3)如何实现玩家自定义游戏棋盘:

        我们可以定义一个很大的二维数组(本文定义了50*50的二维数组),通过宏定义ROW=50,COL=50,在一轮游戏开始的时候创建二维数组char board[ROW][COL] , 这样我们就有了ROW*COL大小的棋盘格。

        玩家输入棋盘格大小之后,只需要显示出玩家设定的大小范围即可。

#define ROW 50
#define COL 50

        自定义棋盘格大小代码:

void BoardSize(int* row, int* col)
{
	while (1)
	{
		int i = 0;
		printf("\n输入正方形棋盘格的大小,上限为%d\n",ROW);
		printf("至少输入3,请输入->");
		scanf("%d", &i);
		*row = i;
		*col = *row;
		if (*row > 2 && *row <= ROW)
		{
			break;
		}
		else
		{
			printf("\n输入非法请重新输入!\n");
		}
	}
}

(4)初始化玩家设定的棋盘

        显示棋盘时,未落子的地方应当时空白的所以我们将board[ROW][COL]中前row-1行和前col-1列初始化为空格即可。

//初始化棋盘
void InitBoard(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] = ' ';
		}
	}
}

(5) 显示棋盘

        显示board[ROW][COL]中的前row-1行和前col-1列时,因为初始化都是空格,我们是看不到的,所以我们需要打印棋盘格线,将其分 开。并提示这是第几行第几列,如图:

这是如何实现的呢?

        空白部分是就是棋盘格初始化的空格,为了方便观看,我们显示的时候可以在打印board[i][j]的前后都打印一个空格。每打印一个空格后面就好打印一个 | 所以打印到col-1列时,竖线只需要打印到col-2即可,下一行是先打印 --- 后打印 | ,同样也是 --- 打印到col-1, | 打印到col-2。可以察觉到每两行就是一个循环。最后一次循环的时候就不需要打印第二行也就是---|---|---。

提示第几行第几列时如何实现的呢?

        显然提示列的部分是在再开始打印的,从0一直打印到col即可,为了对齐可以加入空格。

        提示行的部分是在每次开始打印board[i][0]的第一个元素之前打印是行数和 | 。

此部分重点是如何对齐,一定要分清楚影响打印的是行数还是列数!!!

//打印棋盘
void DispalyBoard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i <= col; i++)
	{
		if (i < 9)
		{
			printf(" %d  ", i );
		}
		else
		{
			printf(" %d ", i );
		}
	}
	printf("\n");
	for (i = 0; i < row ; i++)
	{
		if (i < 9)
		{
			printf(" %d |", i + 1);
		}
		else
		{
			printf(" %d|", i + 1);
		}
		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++)
			{
				if (j <= col)
				{
					printf("---");
					if (j < col)
					{
						printf("|");
					}
				}
			}
		}
	
		printf("\n");
	}
}

 (6)玩家落子

        只需要判定玩家输入落子的位置是不是可以落子的,如果落子位置是空格就可以落子,不是就需要重新输入,一直到落子成功。

void PlayerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	while (1)
	{
		printf("横纵坐标用空格隔开\n");
		printf("请输入落子的坐标->:");
		scanf("%d %d", &x, &y);
		if (' ' == board[x-1][y-1])
		{
			board[x-1][y-1] = '*';
			break;
		}
		else
		{
			printf("\n输入坐标非法,请重新输入\n");
		}
	}
	
}

(7)电脑落子

        电脑落子需要生成随机数,我们可以通过rand()函数来实现,由于在使用rand()之前要使用srand()对其进行初始化。

srand((unsigned int)time(NULL));

        这样就可完成对rand()的初始化time()函数是获取时间戳。rand()和srand()需要引用库函数 #include<stdlib.h>,time()需要引用库函数#include<time.h>。

        rand()%row可以得到0~(row-1),rand()%col可以得到0~(col-1)。

后面只要判断随机值的位置是不是空格,判定能否落子即可。

//电脑走
void ComputerMove(char board[ROW][COL], int row, int col)
{

	while (1)
	{
		int x = rand() % row;
		int y = rand() % col;
		if (' ' == board[x][y])
		{
			board[x][y] = '#';
			break;
		}
	}
}

(8)判断玩家是否获胜

        获胜有三种情况:行符合,列符合,斜着符合,其中斜着符合,可分为左对角线方向和右对角线方向。

        判断行:

只需要判断0~(row-1)行,列需要判断0~(col-1-(n-1))即 0~(col-n),对数组这些部分进行遍历。对board[i][j]遍历时,判断这一行从这个元素开始是不是都是 * ,因为 * 有对应的ASCII码值,所以创建一个sum存储这n个位置的ASCII码值之和,如果sum -减去‘*’(ASCII码值)乘以n等于0,就证明这些位置都是 *  

        判断列:

与行判断相似,只需要判断0~(col-1)列,行需要判断0~(row-1-(n-1))即 0~(row-n),对数组这些部分进行遍历。

        左对角线判断:

当我们进行左对角线判断时因为获胜时棋子是左斜着的,所以只需要判断0~(row-n)行,0~(col-n)列,相当于判断棋盘部分比玩家设置的棋盘部分少了后n行,后n列。对数组这些部分进行遍历。以遍历的位置为原点,计算这点向右下方的这些元素的ASCII码值之和是否等于‘*’(ASCII码值)乘以n。

        右对角线判断:

当我们进行右对角线判断时因为获胜时棋子是右斜着的,所以只需要判断0~(row-n)行,(n-1)~(col-1)列。对数组这些部分进行遍历。以遍历的位置为原点,计算这点向左下方的这些元素的ASCII码值之和是否等于‘*’(ASCII码值)乘以n。

        判断电脑赢和判定玩家赢同理只不过判定的ASCII码值从*变成#。

char PlayerWin(char board[ROW][COL], int row, int col, int n)
{
	int i = 0;
	for (i = 0; i < row ; i++)
	{
		int j = 0;
		for (j = 0; j < col ; j++)
		{
			int k = 0;
			//行 
			int sum1 = 0;
			if (j <= col - n)
			{
				for (k = 0; k < n; k++)
				{
					sum1 = sum1 + board[i][j + k];
				}
			}
			//列
			int sum2 = 0;
			if (i <= row - n)
			{
				for (k = 0; k < n; k++)
				{
					sum2 = sum2 + board[i + k][j];
				}
			}
			//左对角线
			int sum3 = 0;
			if (i <= row - n && j <= col - n)
			{
				for (k = 0; k < n; k++)
				{
					sum3 = sum3 + board[i+k][j+k];
				}
			}
			//右对角线
			int sum4 = 0;
			if (i <= row - n && j >= n - 1)
			{
				for (k = 0; k < n; k++)
				{
					sum4 = sum4 + board[i + k][j - k];
				}
			}
			if ( (0 == sum1 - '*' * n)|| (0 == sum2 - '*' * n) || (0 == sum3 - '*' * n) || (0 == sum4 - '*' * n))
			{
				return '*';
			}
		}
	}
	return 'C';
}

(9)平局

        当棋盘内落满子时为平局,所以对board[row][col]的每个元素进行遍历,如果没有空格就就平局。

int IsDraw(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++)
		{
			if (board[i][j] == ' ')
			{
				return 0;
			}
		}
	}
	return 1;
}

(10)游戏主体实现

        游戏开始玩家输入棋盘格大小,选择几子棋,无论玩家落子还是电脑落子都要进行判断输赢,根据输赢平局函数的返回值判断。

//游戏开始
void game()
{
	srand((unsigned int)time(NULL));
	char board[ROW][COL];
	int n = 0;
	//玩家设置的棋盘行列
	int row = 0;
	int col = 0;
	BoardSize( &row, &col);
	//选择下几子棋
	while (1)
	{
		printf("\n可以玩三子棋以上的游戏\n");
		printf("您想玩几子棋?请输入数字->:");
		scanf("%d", &n);
		if ( n > 2 && n <= row ) 
		{
			break;
		}
		else
		{
			printf("\n输入非法,请重新输入!\n");
		}
	}
	
	//初始化棋盘
	InitBoard(board, row, col);
	//打印棋盘
	DispalyBoard(board, row, col);
	//玩家 * 42  电脑  # 35  空格32
	while (1)
	{
		//玩家走
		PlayerMove(board, row, col);
		DispalyBoard(board, row, col);
		//判断玩家获胜
		if (PlayerWin(board, row, col, n) == '*')
		{
			printf("恭喜玩家获胜\n");
			break;
		}
		//奇数棋盘玩家最后落子
		//判断是否平局
		if (IsDraw(board, row, col) == 1)
		{
			printf("棋逢对手,平局!\n");
			break;
		}
		//电脑走
		printf("电脑玩家落子\n");
		ComputerMove(board, row, col);
		DispalyBoard(board, row, col);
		//判断电脑是否获胜
		if (ComputerWin(board, row, col, n) == '#')
		{
			printf("恭喜电脑获胜\n");
			break;
		}
		//偶数棋盘电脑最后落子
		//判断是否平局
		if (IsDraw(board, row, col) == 1)
		{
			printf("棋逢对手,平局!\n");
			break;
		}
	}
}

(11)游戏逻辑实现

input初始设置不能为0,不然直接不进入循环。

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"

int main()
{
	int input = 1;
	while (input)
	{
		menu();
		printf("\n请输入->:");
		scanf("%d", &input);
		switch (input)
		{
		case 0:
		{
			printf("\n已经退出游戏\n");
			break;
		}
		case 1:
		{
			game();
			break;
		}
		default:
		{
			printf("\n输入错误,请重新输入\n");
			break;
		}
		}
	}
	
	return 0;
}

三、完整代码

(1)game.h

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

#define ROW 50
#define COL 50

//打印菜单
void menu();

//游戏主体
void game();

//玩家选择棋盘格大小
void BoardSize(int* row, int* col);

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

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

//玩家走
void PlayerMove(char board[ROW][COL], int row, int col);

//电脑走
void ComputerMove(char board[ROW][COL], int row, int col);

//玩家赢
char PlayerWin(char board[ROW][COL], int row, int col, int n);

//电脑赢
char ComputerWin(char board[ROW][COL], int row, int col, int n);
//平局
int IsDraw(char board[ROW][COL], int row, int col);

(2)test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"

int main()
{
	int input = 1;
	while (input)
	{
		menu();
		printf("\n请输入->:");
		scanf("%d", &input);
		switch (input)
		{
		case 0:
		{
			printf("\n已经退出游戏\n");
			break;
		}
		case 1:
		{
			game();
			break;
		}
		default:
		{
			printf("\n输入错误,请重新输入\n");
			break;
		}
		}
	}
	
	return 0;
}

 (3)game.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"

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

void BoardSize(int* row, int* col)
{
	while (1)
	{
		int i = 0;
		printf("\n输入正方形棋盘格的大小,上限为%d\n",ROW);
		printf("至少输入3,请输入->");
		scanf("%d", &i);
		*row = i;
		*col = *row;
		if (*row > 2 && *row <= ROW)
		{
			break;
		}
		else
		{
			printf("\n输入非法请重新输入!\n");
		}
	}
}

//初始化棋盘
void InitBoard(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 DispalyBoard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i <= col; i++)
	{
		if (i < 9)
		{
			printf(" %d  ", i );
		}
		else
		{
			printf(" %d ", i );
		}
	}
	printf("\n");
	for (i = 0; i < row ; i++)
	{
		if (i < 9)
		{
			printf(" %d |", i + 1);
		}
		else
		{
			printf(" %d|", i + 1);
		}
		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++)
			{
				if (j <= col)
				{
					printf("---");
					if (j < col)
					{
						printf("|");
					}
				}
			}
		}
	
		printf("\n");
	}
}

//玩家走
void PlayerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	while (1)
	{
		printf("横纵坐标用空格隔开\n");
		printf("请输入落子的坐标->:");
		scanf("%d %d", &x, &y);
		if (' ' == board[x-1][y-1])
		{
			board[x-1][y-1] = '*';
			break;
		}
		else
		{
			printf("\n输入坐标非法,请重新输入\n");
		}
	}
	
}

//电脑走
void ComputerMove(char board[ROW][COL], int row, int col)
{

	while (1)
	{
		int x = rand() % row;
		int y = rand() % col;
		if (' ' == board[x][y])
		{
			board[x][y] = '#';
			break;
		}
	}
}

//玩家赢
char PlayerWin(char board[ROW][COL], int row, int col, int n)
{
	int i = 0;
	for (i = 0; i < row ; i++)
	{
		int j = 0;
		for (j = 0; j < col ; j++)
		{
			int k = 0;
			//行 
			int sum1 = 0;
			if (j <= col - n)
			{
				for (k = 0; k < n; k++)
				{
					sum1 = sum1 + board[i][j + k];
				}
			}
			//列
			int sum2 = 0;
			if (i <= row - n)
			{
				for (k = 0; k < n; k++)
				{
					sum2 = sum2 + board[i + k][j];
				}
			}
			//左对角线
			int sum3 = 0;
			if (i <= row - n && j <= col - n)
			{
				for (k = 0; k < n; k++)
				{
					sum3 = sum3 + board[i+k][j+k];
				}
			}
			//右对角线
			int sum4 = 0;
			if (i <= row - n && j >= n - 1)
			{
				for (k = 0; k < n; k++)
				{
					sum4 = sum4 + board[i * k][j - k];
				}
			}
			if ( (0 == sum1 - '*' * n)|| (0 == sum2 - '*' * n) || (0 == sum3 - '*' * n) || (0 == sum4 - '*' * n))
			{
				return '*';
			}
		}
	}
	return 'C';
}

//电脑赢
char ComputerWin(char board[ROW][COL], int row, int col, int n)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < col; j++)
		{
			int k = 0;
			//行 
			int sum1 = 0;
			if (j <= col - n)
			{
				for (k = 0; k < n; k++)
				{
					sum1 = sum1 + board[i][j + k];
				}
			}
			//列
			int sum2 = 0;
			if (i <= row - n)
			{
				for (k = 0; k < n; k++)
				{
					sum2 = sum2 + board[i + k][j];
				}
			}
			//左对角线
			int sum3 = 0;
			if (i <= row - n && j <= col - n)
			{
				for (k = 0; k < n; k++)
				{
					sum3 = sum3 + board[i + k][j + k];
				}
			}
			//右对角线
			int sum4 = 0;
			if (i <= row - n && j >= n - 1)
			{
				for (k = 0; k < n; k++)
				{
					sum4 = sum4 + board[i + k][j - k];
				}
			}
			if ((0 == sum1 - '#' * n) || (0 == sum2 - '#' * n) || (0 == sum3 - '#' * n) || (0 == sum4 - '#' * n))
			{
				return '#';
			}
		}
	}
	return 'C';
}
//平局
int IsDraw(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++)
		{
			if (board[i][j] == ' ')
			{
				return 0;
			}
		}
	}
	return 1;
}

//游戏开始
void game()
{
	srand((unsigned int)time(NULL));
	char board[ROW][COL];
	int n = 0;
	//玩家设置的棋盘行列
	int row = 0;
	int col = 0;
	BoardSize( &row, &col);
	//选择下几子棋
	while (1)
	{
		printf("\n可以玩三子棋以上的游戏\n");
		printf("您想玩几子棋?请输入数字->:");
		scanf("%d", &n);
		if ( n > 2 && n <= row ) 
		{
			break;
		}
		else
		{
			printf("\n输入非法,请重新输入!\n");
		}
	}
	
	//初始化棋盘
	InitBoard(board, row, col);
	//打印棋盘
	DispalyBoard(board, row, col);
	//玩家 * 42  电脑  # 35  空格32
	while (1)
	{
		//玩家走
		PlayerMove(board, row, col);
		DispalyBoard(board, row, col);
		//判断玩家获胜
		if (PlayerWin(board, row, col, n) == '*')
		{
			printf("恭喜玩家获胜\n");
			break;
		}
		//奇数棋盘玩家最后落子
		//判断是否平局
		if (IsDraw(board, row, col) == 1)
		{
			printf("棋逢对手,平局!\n");
			break;
		}
		//电脑走
		printf("电脑玩家落子\n");
		ComputerMove(board, row, col);
		DispalyBoard(board, row, col);
		//判断电脑是否获胜
		if (ComputerWin(board, row, col, n) == '#')
		{
			printf("恭喜电脑获胜\n");
			break;
		}
		//偶数棋盘电脑最后落子
		//判断是否平局
		if (IsDraw(board, row, col) == 1)
		{
			printf("棋逢对手,平局!\n");
			break;
		}
	}
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值