【华为OD】社招算法真题:四子棋连,下棋后,棋子会落到最底部,实现一行、一列或者一条对角线 上有四个相同颜色的棋子,获胜

四子棋
(游戏:四子连)四子连是一个两个人玩的棋盘游戏,在游戏 中,玩家轮流将有颜色的棋子放在一个m行n列的垂直悬挂的 网格中,如下所示。 这个游戏的目的是在对手实现一行、一列或者一条对角线 上有四个相同颜色的棋子之前,你能先做到。程序提示两个玩 家交替地下红子 Red 或黄子 Yellow。当放下一子时,程序在控 制台重新显示这个棋盘,然后确定游戏的状态(贏、平局还是 继续)。下面是一个运行示例:
输入1:
5 5
1 1 2 2 3 3 4 4
棋盘大小 5 ∗ 5 ( m ∗ n ) 5*5(m*n) 55mn
第一步,红子在1位置下棋,第二步,白子在1位置下棋,依次类推
输出1:
7,red
在第七步,红子赢了
输入2:
5 5
0 1 1 2 2 3 3 4 4
输出2 :
1,error
因为0是异常输入,不能输入0

输入3:

5 5 
1 2 3 4 2 3 3 4 5 4 4 1 2 3

输出3:
11,red
在这里插入图片描述

输入4:

5 5
1 2 3 4 2 3 3 4 5 4 5 1 2 3

输出4:
15,error

输入5:

5 4 
1 2 1 2 3 3 1 1 2 4 3 4 4

输出5:
13,red

输入5:

4 5
4 5 1 3 3 2 1 2 2 1 1

输出5:
13,red

行不通过输入
5 5
1 2 3 4 5 1 1 2 2 4 4 5 5
输出:
14,error
在这里插入图片描述
行通过输入
5 10
1 2 3 4 5 1 1 2 2 4 4 5 5 1 6 6 7 7
输出:
在这里插入图片描述

列不通过输入
5 5
3 1 3 3 3 2 3 4 5
输出:
10,error
在这里插入图片描述
列通过输入
5 5
3 1 3 2 3 4 3 5
输出:
在这里插入图片描述

左上斜角通过

5 5 
1 2 3 4 2 3 3 4 5 4 4 1 2 3

输出:
11,red
在这里插入图片描述

右上斜角通过
5 5
2 3 5 4 5 3 4 2 3 2 2
输出:
在这里插入图片描述
右上斜角不通过
5 5
2 3 5 4 5 5 4 3 1 2 1 2 2 1 2 5 1
输出:没有连续的
在这里插入图片描述

通过上述测试用例,验证正确性
c++:

#include <iostream>
#include<vector>
#include<assert.h>
using namespace std;


//竖直四子棋
vector<int>  GetWinner(int rows, int cols, vector<int> data) {
	if (rows <= 3 || cols <= 3)
	{
		assert(1); //棋盘要4个才能赢,少于3行列的棋盘,不会有赢家,所以禁止输入
	}
	vector<int> result;
	int* arr = new int[rows * cols];
	int* arrHeight = new int[cols];

	for (int i = 0; i < rows; i++)
	{
		for (int j = 0; j < cols; j++) {
			arr[i * cols + j] = 0;
		}
	}

	for (int i = 0; i < cols; i++)
	{
		arrHeight[i] = 0;
	}

	int nowColor = 1; //1,红子,2,蓝子
	for (int p = 0; p < (int)data.size(); p++)
	{
		// 开始下棋
		int col = data[p]; //当前下棋的列
		if (col < 0 || col >= cols)
		{
			result.push_back(p);
			result.push_back(0);
			return result;
		}
		int row = (rows - 1 - arrHeight[data[p]]); //当前下棋的行

		if (row >= rows || row < 0)
		{
			result.push_back(p);
			result.push_back(0); //如果超出棋盘范围,直接返回下棋步骤异常
			return result;
		}

		arr[row * cols + col] = nowColor; //下棋

		for (int i = 0; i < rows; i++)
		{
			for (int j = 0; j < cols; j++) 
			{
				cout << arr[i * cols + j] << " ";
			}
			cout << endl;  //打印棋盘
		}
		cout << endl;


		arrHeight[data[p]] += 1;//高度加1
		if (nowColor == 1)
		{
			nowColor = 2; // 红子下完蓝字下
		}
		else {
			nowColor = 1;
		}

		//检查是否出现赢家
		int rflag = 0;//检查红red行
		int bflag = 0;//检查blue行
		int rlflag = 0;//检查red列
		int blflag = 0;
		int rxflag = 0;//检查右向斜 
		int bxflag = 0;
		int rx1flag = 0;//检查左向斜 
		int bx1flag = 0;
		for (int i = 0; i < rows; i++)
		{
			//检查列
			if (arr[cols * i + col] == 1)
			{
				rlflag += 1;//检查列
				blflag = 0;
			}
			else if (arr[cols * i + col] == 2)
			{
				blflag += 1;
				rlflag = 0;
			}
		}
		
		int maxSeq = 0; // 最大连续字串
		int nowSeq = 0; //当前连续串数量
		for (int i = 0; i < cols; i++)
		{
			//检查行
			if (i>=1 && arr[row * cols + i]!=0  && arr[row * cols + i - 1] == arr[row * cols + i])
			{
				nowSeq++;
			}
			else if (arr[row * cols + i] ==0)
			{
				maxSeq = maxSeq < nowSeq ? nowSeq : maxSeq;
				nowSeq = 0;
			}
			else {
				maxSeq = maxSeq < nowSeq ? nowSeq : maxSeq;
				nowSeq = 1;
			}
		}
		if (maxSeq>=4)
		{
			if ((p+1) % 2 == 0) {
				bflag = 4;
			}
			else {
				rflag = 4;
			}
		}
		

		/* 检查右向斜 */
		maxSeq = 0; // 最大连续字串
		nowSeq = 0; //当前连续串数量
		for (int i = row,  j = col; i < rows && j < cols; i++, j++)
		{
			if (i >= 1 && j >=1 && arr[i * cols + j] != 0 && arr[(i-1) * cols + j - 1] == arr[i * cols + j])
			{
				nowSeq++;
			}
			else if (arr[i * cols + j] == 0)
			{
				maxSeq = maxSeq < nowSeq ? nowSeq : maxSeq;
				nowSeq = 0;
			}
			else {
				maxSeq = maxSeq < nowSeq ? nowSeq : maxSeq;
				nowSeq = 1;
			}
		}

		for (int i = row - 1,  j = col - 1; i >= 0 && j >= 0; i--, j--)
		{
			if ( arr[i * cols + j] != 0 && arr[(i + 1) * cols + j + 1] == arr[i * cols + j])
			{
				nowSeq++;
			}
			else if (arr[i * cols + j] == 0)
			{
				maxSeq = maxSeq < nowSeq ? nowSeq : maxSeq;
				nowSeq = 0;
			}
			else {
				maxSeq = maxSeq < nowSeq ? nowSeq : maxSeq;
				nowSeq = 1;
			}
		}

		if (maxSeq >= 4)
		{
			if ((p + 1) % 2 == 0) {
				bxflag = 4;
			}
			else {
				 rxflag = 4;
			}
		}
		/* 检查左向斜 */
		maxSeq = 0; // 最大连续字串
		nowSeq = 0; //当前连续串数量
		for (int i = row,  j = col; i < rows && i >= 0 && j >= 0 && j < cols; i++, j--)
		{
			if (i>=1 && j< cols-1 &&arr[i * cols + j] != 0 && arr[(i - 1) * cols + j + 1] == arr[i * cols + j])
			{
				nowSeq++;
			}
			else if (arr[i * cols + j] == 0)
			{
				maxSeq = maxSeq < nowSeq ? nowSeq : maxSeq;
				nowSeq = 0;
			}
			else {
				maxSeq = maxSeq < nowSeq ? nowSeq : maxSeq;
				nowSeq = 1;
			}
		}
		for (int i = row - 1,  j = col - 1; i < rows && i >= 0 && j >= 0 && j < cols; i--, j++)
		{
			if (arr[i * cols + j] != 0 && arr[(i + 1) * cols + j - 1] == arr[i * cols + j])
			{
				nowSeq++;
			}
			else if (arr[i * cols + j] == 0)
			{
				maxSeq = maxSeq < nowSeq ? nowSeq : maxSeq;
				nowSeq = 0;
			}
			else {
				maxSeq = maxSeq < nowSeq ? nowSeq : maxSeq;
				nowSeq = 1;
			}
		}


		if (maxSeq >= 4)
		{
			if ((p + 1) % 2 == 0) {
				bx1flag = 4;
			}
			else {
				rx1flag = 4;
			}
		}
		if (rflag == 4 || rlflag == 4 || rxflag == 4 || rx1flag == 4)
		{
			result.push_back(p);
			result.push_back(1);
			return result;
		}
		if (bflag == 4 || blflag == 4 || bxflag == 4 || bx1flag == 4)
		{
			result.push_back(p);
			result.push_back(2);
			return result;
		}

	}
	
	result.push_back(data.size());
	result.push_back(0);
	delete[] arr;
	delete[] arrHeight;
	return result;
}

int main()
{
	int m, n;
	cin >> m >> n;
	vector<int> arr;
	int num = 0;
	while (cin >> num)
	{
		arr.push_back(num - 1);
		if (cin.get() == '\n')
		{
			break;
		}
	}
	vector<int> result = GetWinner(m, n, arr);
	cout << result[0] + 1 << ",";
	if (result[1] == 1)
	{
		cout << "red";
	}
	else if (result[1] == 2)
	{
		cout << "blue";
	}
	else {
		cout << "error";
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值