C++/Qt 计算24点

C++/Qt 计算24点


​ 游戏的算法可描述如下:4个1-10的数字,用加、减、乘、除和括号把数子算成24,每个数字都必须使用到,且只能用一次。
​ 用C++写会更加的方便:
在这里插入图片描述

​ 在这本书中要求了表达式中数字的顺序不能改变,所以在7.7节 中提供的算法不具有普遍适应性,但是算法的思路还是很简单并且清晰。不需要多动脑袋。在他的基础上,可以轻易的扩展成一般的算法。

一些比较难的24点计算

  • 1 3 9 10

  • 1 4 5 6

  • 1 5 5 5

  • 2 7 10 10

  • 3 3 7 7

  • 3 3 8 8

1、用递归分治算法思路及设计

在这里插入图片描述
【1】最开始是4个数,A、B、C、D。
【2】从4个数中选择两个数,例如 A 和 B 。
【3】将两个数进行运算,R1 = A OP B
【4】运算结果 R1 和 剩余的数字进行运算,R1、C、D
【5】从三个数中选择任意两个数进行运算
【6】继续运算,只至一个数字
【7】用递归方法,计算结果是否为24 ,很容易,但是要输出一条完整的表达式,很复杂,因为其简单的计算思路,值得笔记下来。表达式应该还有需要深思的地方…

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<vector>
#include <string>
#include <map>
using namespace std;
string ops[] = { "#","+","-","*","/","-","/" };
map <string, vector<string> > maps;
static int counts = 3;
string num_string( double n )
{
	char buf[10];
	sprintf( buf, "%g", n );
	return string( buf );
}
double cal( double x, double y, int op )
{
	switch( op )
	{
		case 1:return x + y;
		case 2:return x - y;
		case 3:return x * y;
		case 4:
		{
			if( y == 0 )
				return -1000;
			return x / y;
		}
		default:
			return -1000;
	}
}
void findKeys( map <string, vector<string> > &m, string &v )
{
	map <string, vector<string> >::iterator it;
	it = m.find( v );
	if( it != m.end() && counts > 0 )
	{
		counts--;
		cout << "(";
		for( int i = 0; i < 3; i++ )
		{
			findKeys( m, it->second[i] );
		}
		cout << ")";
	}
	else
	{
		cout << v;
	}
}
bool is24( vector<double> a )
{
	bool find = false;
	if( a.size() == 1 )
		return fabs( a[0] - 24 ) < 10E-5;
	for( int i = 0; i < a.size(); i++ )
	{
		vector<double> b( a );
		b.erase( b.begin() + i );
		for( int j = 0; j < b.size(); j++ )
		{
			vector<double> c( b );
			c.erase( c.begin() + j );
			for( int op = 1; op <= 4; op++ )
			{
				vector<double> d( c );
				double r = cal( a[i], b[j], op );
				if( r < 0 )
					continue;
				else
					d.push_back( r );
				if( is24( d ) )
				{
					find = true;
					vector<string> res;
					res.push_back( num_string( a[i] ) );
					res.push_back( ops[op] );
					res.push_back( num_string( b[j] ) );
					maps[num_string( r )] = res;
					return true;
				}
			}
		}
	}
	return false;
}
int main()
{
	vector<double> a( 4, 0 );
	while( cin >> a[0] >> a[1] >> a[2] >> a[3] )
	{
		maps.clear();
		counts = 3;
		if( is24( a ) )
		{
			cout << "true" << endl;
			string s( "24" );
			findKeys( maps, s);
			cout << " = 24" << endl;
		}
		else cout << "false" << endl;
	}
}

2、暴力穷举法

在这里插入图片描述
【1】四个数, 穷举 A、B、C、D
【2】三个符号,穷举 +、-、×、÷
【3】两种模式
【3.1】组成表达式,((A OP1 B) OP2 C ) OP3 D
【3.2】组成表达式,(A OP1 B) OP3 (C OP2 D)
【4】注意:减法和除法两个数字交换顺序后,会有不同结果,所以四则运算要分成6种。
对于减法,要检查是否为负数;对于除法,还要检查除数是否为0。

此时每一个数字和符号都已确定,可直接组合成完整的表达式。

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<vector>
#include <string>
#include <map>
using namespace std;
string ops[] = { "#","+","-","*","/","-","/" };
string num_string( double n )
{
	char buf[10];
	sprintf( buf, "%g", n );
	return string( buf );
}
double cal( double x, double y, int op )
{
	switch( op )
	{
		case 1:return x + y;
		case 2:return x - y;
		case 3:return x * y;
		case 4:
		{
			if( y == 0 )
				return -1000;
			return x / y;
		}
		case 5:
			return y - x;
		case 6:
		{
			if( x == 0 )
				return -1000;
			return y / x;
		}
		default:
			return -1000;
	}
}
bool findString( vector<string> &vec, const string &str )
{
	for( const string var : vec )
	{
		if( var == str )
			return true;
	}
	return false;
}
bool is24( vector<double> a )
{
	vector < string > results;
	bool find = false;
	string res;  //可以考虑使用逆波兰表达式,脱去括号,求得最终的表达式,加入表达式集,去除相同的部分
	for( int A = 0; A < 4; A++ )
	{
		for( int B = 0; B < 4; B++ )
		{
			if( B == A ) continue;
			for( int C = 0; C < 4; C++ )
			{
				if( C == A || C == B ) continue;
				for( int D = 0; D < 4; D++ )
				{
					if( D == A || D == B || D == C ) continue;
					for( int op1 = 1; op1 <= 4; op1++ )
						for( int op2 = 1; op2 <= 6; op2++ )
							for( int op3 = 1; op3 <= 6; op3++ )
							{
								double r1 = cal( a[A], a[B], op1 );    //  (A op1 B)	||	(B op1 A)
								if( r1 < 0 )
									continue;
								double r21 = cal( r1, a[C], op2 );       //  (r1 op2 C)	||  (C op2 r1)
								double r31 = cal( r21, a[D], op3 );      //  (r21 op2 D)	||  (D op2 r21)
								if( fabs( r31 - 24 ) < 10E-5 && ( r21 >= 0 ) )
								{
									//cout << "r31\n";
									find = true;
									if( op1 < 5 )
										res = "(" + num_string( a[A] ) + ops[op1] + num_string( a[B] ) + ")";
									else
										res = "(" + num_string( a[B] ) + ops[op1] + num_string( a[A] ) + ")";
									if( op2 < 5 )
										res = "(" + res + ops[op2] + num_string( a[C] ) + ")";
									else
										res = "(" + num_string( a[C] ) + ops[op2] + res + ")";
									if( op3 < 5 )
										res = res + ops[op3] + num_string( a[D] );
									else
										res = num_string ( a[D] ) + ops[op3] + res;
									//检查是否有同样的表达式
									if( !findString( results, res ) )
										results.push_back( res );
									else
										continue;
                                    cout << res << "= 24" << endl;
								}
								double r22 = cal( a[C], a[D], op2 );   //  (C op2 D)	||  (D op2 C)
								double r32 = cal( r1, r22, op3 );      //  (r1 op2 r22)	||  (r22 op2 r1)
								if( fabs( r32 - 24 ) < 10E-5 && ( r22 >= 0 ) )
								{
									find = true;
									string temp;
									if( op1 < 5 )
										res = "(" + num_string( a[A] ) + ops[op1] + num_string( a[B] ) + ")";
									else
										res = "(" + num_string( a[B] ) + ops[op1] + num_string( a[A] ) + ")";
									if( op2 < 5 )
										temp = "(" + num_string( a[C] ) + ops[op2] + num_string( a[D] ) + ")";
									else
										temp = "(" + num_string( a[D] ) + ops[op2] + num_string( a[C] ) + ")";
									if( op3 < 5 )
										res = res + ops[op3] + temp;
									else
										res = temp + ops[op3] + res;
									//检查是否有同样的表达式
									if( !findString( results, res ) )
										results.push_back( res );
									else
										continue;
									cout << res << "= 24" << endl;
								}
							}
				}
			}
		}
	}
	if( !find )
	{
		cout << "Sorry ,无法计算\n";
		return false;
	}
	else
		return true;
}
int main()
{
	vector<double> a( 4, 0 );
	while( cin >> a[0] >> a[1] >> a[2] >> a[3] )
	{
		is24( a );
	}
}

3、Qt 图片

#include "Widget.h"
#include <QtWidgets>
QString ops[] = { "#","+","-","*","/","-","/" };
int num[] = { 0,1,7,5,10 };
int idx = 0;
Widget::Widget(QWidget *parent) : QWidget(parent)
{
    QPalette palette;
    palette.setColor(QPalette::Window,Qt::red);
    QHBoxLayout *labsLayout = new QHBoxLayout;
    for (int i = 0; i < 4; ++i) {
        labs[i] = new QLabel;
        labs[i]->setAutoFillBackground(true);
        labs[i]->setPalette(palette);
        labs[i]->setFrameStyle(QFrame::Panel );
        labs[i]->setAlignment(Qt::AlignCenter);
        labs[i]->setMinimumHeight(50);
        labs[i]->setMargin(10);
        labsLayout->addWidget(labs[i]);
    }

    QGridLayout *btnsLayout = new QGridLayout;
    for (int i = 0; i < 10; ++i) {
        QPushButton *btn = new QPushButton(QString::number(i+1));
        connect(btn,&QPushButton::clicked,[=](){
            labs[idx]->setText(btn->text());
            idx +=1;
            if(idx==1){
                for (int i = 1; i < 4; ++i) {
                    labs[i]->setText("");
                }
                edit->clear();
            }
            if(idx==4){
                idx %= 4;
                get24();
            }
        });
        btnsLayout->addWidget(btn,i/5,i%5);
    }

    edit = new QTextEdit;
    edit->setReadOnly(true);

    QVBoxLayout *mainLayout = new QVBoxLayout(this);
    mainLayout->addLayout(labsLayout);
    mainLayout->addWidget(edit);
    mainLayout->addLayout(btnsLayout);
}

double Widget::cal(double x, double y, int op)
{
    switch( op )
    {
    case 1:return x + y;
    case 2:return x - y;
    case 3:return x * y;
    case 4:
    {
        if( y == 0 )
            return -1000;
        return x / y;
    }

    case 5:
        return y - x;
    case 6:
    {
        if( x == 0 )
            return -1000;
        return y / x;
    }
    default:
        return -1000;
    }
}

bool Widget::findString(QVector<QString> &vec, const QString &str)
{
    for( const QString var : vec )
    {
        if( var == str )
            return true;
    }
    return false;
}

void Widget::get24()
{
    num[1] = labs[0]->text().toInt();
    num[2] = labs[1]->text().toInt();
    num[3] = labs[2]->text().toInt();
    num[4] = labs[3]->text().toInt();

    QVector < QString > results;

    bool find = false;
    QString res;  //可以考虑使用逆波兰表达式,脱去括号,求得最终的表达式,加入表达式集,去除相同的部分
    for( int A = 1; A <= 4; A++ )
    {
        for( int B = 1; B <= 4; B++ )
        {
            if( B == A ) continue;
            for( int C = 1; C <= 4; C++ )
            {
                if( C == A || C == B ) continue;
                for( int D = 1; D <= 4; D++ )
                {
                    if( D == A || D == B || D == C ) continue;
                    for( int op1 = 1; op1 <= 4; op1++ )
                        for( int op2 = 1; op2 <= 6; op2++ )
                            for( int op3 = 1; op3 <= 6; op3++ )
                            {
                                double r1 = cal( num[A], num[B], op1 );    //  (A op1 B)	||	(B op1 A)
                                if( r1 < 0 )
                                    continue;
                                double r21 = cal( r1, num[C], op2 );       //  (r1 op2 C)	||  (C op2 r1)
                                double r31 = cal( r21, num[D], op3 );      //  (r21 op2 D)	||  (D op2 r21)

                                //                                if( r31 == 24 && ( r21 >= 0 ) )
                                if( qAbs(r31 - 24)<10E-5 && ( r21 >= 0 ) )
                                {
                                    //cout << "r31\n";
                                    find = true;
                                    if( op1 < 5 )
                                        res = "(" + QString::number( num[A] ) + ops[op1] + QString::number( num[B] ) + ")";
                                    else
                                        res = "(" + QString::number( num[B] ) + ops[op1] + QString::number( num[A] ) + ")";

                                    if( op2 < 5 )
                                        res = "(" + res + ops[op2] + QString::number( num[C] ) + ")";
                                    else
                                        res = "(" + QString::number( num[C] ) + ops[op2] + res + ")";

                                    if( op3 < 5 )
                                        res = res + ops[op3] + QString::number( num[D] );
                                    else
                                        res = QString::number( num[D] ) + ops[op3] + res;
                                    //检查是否有同样的表达式
                                    if( !findString( results, res ) )
                                        results.push_back( res );
                                    else
                                        continue;
                                    //                                    qDebug() << res << "= 24" ;
                                    edit->append(res+" = 24");
                                }

                                double r22 = cal( num[C], num[D], op2 );   //  (C op2 D)	||  (D op2 C)
                                double r32 = cal( r1, r22, op3 );          //  (r1 op2 r22)	||  (r22 op2 r1)
                                if( qAbs(r32 - 24)<10E-5 && ( r22 >= 0 ) )
                                {
                                    find = true;
                                    QString temp;
                                    if( op1 < 5 )
                                        res = "(" + QString::number( num[A] ) + ops[op1] + QString::number( num[B] ) + ")";
                                    else
                                        res = "(" + QString::number( num[B] ) + ops[op1] + QString::number( num[A] ) + ")";

                                    if( op2 < 5 )
                                        temp = "(" + QString::number( num[C] ) + ops[op2] + QString::number( num[D] ) + ")";
                                    else
                                        temp = "(" + QString::number( num[D] ) + ops[op2] + QString::number( num[C] ) + ")";

                                    if( op3 < 5 )
                                        res = res + ops[op3] + temp;
                                    else
                                        res = temp + ops[op3] + res;
                                    //检查是否有同样的表达式
                                    if( !findString( results, res ) )
                                        results.push_back( res );
                                    else
                                        continue;
                                    //                                    qDebug() << res << "= 24";
                                    edit->append(res+" = 24");
                                }
                            }
                }
            }
        }
    }
    if( !find )
        edit->append("Sorry ,无法计算") ;
    else
        edit->moveCursor(QTextCursor::Start);
}

有感兴趣的 可以直接下载 0 积分
https://download.csdn.net/download/hitzsf/85750810, 0积分下载

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 在Ubuntu操作系统中使用Qt库开发图像应用程序时,可以通过鼠标控制像素点的显示和操作。 Qt是一个跨平台的应用程序开发框架,支持C++编程语言。它提供了丰富的图形组件和工具,适用于不同的应用领域,包括图像处理。 在Qt中,可以使用QImage类来表示和操作图像。QImage类提供了获取和设置像素点颜色的方法。我们可以通过鼠标点击获取鼠标指针所在位置的像素点的坐标和颜色值,然后在图像上显示或修改该像素点的颜色。 具体的实现方法是,首先需要在Qt中创建一个窗口,并在窗口上显示图像。可以使用QLabel组件来显示图像。接下来,需要在窗口上监听鼠标事件,可以通过重写窗口的mousePressEvent()方法来实现。在鼠标点击事件中,可以获取鼠标指针位置的坐标,并通过调用QImage的pixel()方法获取该位置的像素点的颜色值。 通过获取到的像素点颜色值,我们可以进行各种操作,例如修改像素点的颜色、获取像素点的亮度等。可以通过调用QImage的setPixel()方法来设置像素点的颜色值,然后通过调用update()方法使窗口进行更新,从而实现像素点的显示和修改。 总之,通过Ubuntu和Qt,我们可以方便地使用鼠标控制图像中的像素点,实现图像的显示和操作。 ### 回答2: 在Ubuntu系统下使用Qt库进行图像处理时,我们可以通过获取鼠标位置来获取像素点的信息。 在Qt中,可以通过QMouseEvent类来获得鼠标事件的信息。当鼠标在窗口中进行移动时,我们可以通过重写QWidget的mouseMoveEvent()函数来捕捉鼠标移动事件。在此函数中,我们可以获取鼠标的坐标位置。 一旦我们获取到鼠标的坐标位置,我们可以通过QImage类来获取该位置对应的像素点信息。QImage类提供了pixel()函数用于获取指定位置的像素点值。像素点值可以通过QRgb类型来获取,它包含了红、绿、蓝和透明度等信息。 我们可以通过一个简单的例子来展示这一过程。首先,我们需要创建一个继承自QWidget的自定义窗口类,然后重写mouseMoveEvent()函数来获取鼠标位置。然后,在该函数中,我们可以通过调用QImage的pixel()函数,传入鼠标坐标来获取该像素点的值。 接下来,我们可以通过Qt的信号和槽机制来实时显示鼠标所在位置的像素点信息。当获取到像素点的信息后,我们可以将该信息显示在窗口上,或者进行其他的处理。 通过上述的步骤,我们就可以在Ubuntu系统下使用Qt库进行图像处理,并获取鼠标所在位置的像素点信息。这样的功能可以在图像编辑软件、计算机视觉和图像处理等领域中发挥重要作用。 ### 回答3: 对于Ubuntu操作系统下使用Qt编程实现鼠标响应像素点的功能,我们可以采取以下步骤: 首先,我们需要在Ubuntu系统上安装Qt开发工具包,在终端中输入命令sudo apt-get install qtcreator即可进行安装。 接下来,我们打开Qt Creator,在新建项目时选择Qt Widgets Application,并给项目取一个合适的名字。然后,我们在项目中添加一个QLabel控件,用于显示图像。 在代码编辑器中,我们首先需要引入相关的头文件: ```cpp #include <QLabel> #include <QMouseEvent> ``` 然后,在成员变量部分声明一个QLabel指针和一个用于存储像素点坐标的变量: ```cpp private: QLabel *imageLabel; QPoint pixelCoord; ``` 在构造函数中,我们创建imageLabel控件实例,并设置鼠标追踪以便正确响应鼠标事件: ```cpp MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { imageLabel = new QLabel(this); imageLabel->setMouseTracking(true); // ... } ``` 接下来,我们需要重写QWidget的mouseMoveEvent函数,以获取鼠标移动时的像素点坐标: ```cpp void MainWindow::mouseMoveEvent(QMouseEvent *event) { pixelCoord = event->pos(); // 更新显示当前坐标的方法 updatePixel(); } ``` 在updatePixel方法中,我们根据当前像素点坐标获取图像的像素值,并将其显示在imageLabel上: ```cpp void MainWindow::updatePixel() { QImage image = imageLabel->pixmap()->toImage(); QColor pixelColor = image.pixel(pixelCoord); // 将像素值转为字符串并显示 imageLabel->setText(pixelColor.name()); } ``` 最后,在需要显示图像的位置,我们加载一个图片文件并将其设置为imageLabel的背景图像: ```cpp QPixmap pixmap("image.jpg"); imageLabel->setPixmap(pixmap); ``` 这样,当我们启动程序后,在Qt窗口上显示的图像中,我们可以通过移动鼠标获取对应位置的像素点坐标和颜色值,并在imageLabel上显示出来。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值