⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xreducetestdlg.cpp

📁 一个有趣的卡诺图划简程序。学生可自己填充卡诺图
💻 CPP
📖 第 1 页 / 共 3 页
字号:
					cur_node->num = mask_itemnum[m_idx];
				}
				//继续下一步化简
				ReduceNext( cur_node , pos,maskbit[m_idx][j],mask_itemnum[m_idx] );
			}
		}
		if( high_ok ) break;
	}

	//根据自动化简生成结果
	//编列整个树
	autonum = 0;
	

	if( root.son != NULL ){
		SearchAutoRedTree( root.son );
		DeleteInvalid();
	}
	
	SetCursor( oldcur );

}

void XReduceTestDlg::DeleteInvalid()
{
	int min_way,ways,items;
	for( int i = 1; i <= autonum; i++ ){
		ways = 0;
		for( int i1 = 0; i1 < tabAutoReducing[i].intCurIndex ; i1++ ){
			items = 0;
			for( int i2 = 0; i2 < 17; i2++ ){
				if( tabAutoReducing[i].ItemsProcessing[i1][i2] == -1 )
					break;
				else
					items++;
			}
			switch(items){
			case 0: ways += 0; break;
			case 1: ways += intValNum; break;
			case 2: ways += intValNum-1; break;
			case 4: ways += intValNum-2; break;
			case 8: ways += intValNum-3; break;
			case 16: ways += intValNum-4; break;
			}
		}
		ways += tabAutoReducing[i].intCurIndex - 1 ;
		if( i == 1 )
			min_way = ways ;
		else if( min_way > ways )
			min_way = ways;
	}

	//删除非最简方法
	for( int i = 1; i <= autonum; i++ ){
		ways = 0;
		for( int i1 = 0; i1 < tabAutoReducing[i].intCurIndex ; i1++ ){
			items = 0;
			for( int i2 = 0; i2 < 17; i2++ ){
				if( tabAutoReducing[i].ItemsProcessing[i1][i2] == -1 )
					break;
				else
					items++;
			}
			switch(items){
			case 0: ways += 0; break;
			case 1: ways += intValNum; break;
			case 2: ways += intValNum-1; break;
			case 4: ways += intValNum-2; break;
			case 8: ways += intValNum-3; break;
			case 16: ways += intValNum-4; break;
			}
		}
		ways += tabAutoReducing[i].intCurIndex - 1 ;
		if( ways > min_way ){
			tabAutoReducing[i] = tabAutoReducing[autonum] ;
			autonum--;
			i--;
		}
	}

	for( int i = 1; i <= autonum; i++ )
		tabAutoReducing[i].Normalize();
	//删除重复的化简方法

	for( int i = 1 ; i < autonum; i++ ){
		for( int j = i+1 ; j <= autonum; j++ ){
			if( tabAutoReducing[i] == tabAutoReducing[j] ){
				tabAutoReducing[j] = tabAutoReducing[autonum];//删除该项
				autonum--;
//				if( j == autonum ) break;
				j--;
			}
		}
	}

}

void XReduceTestDlg::SearchAutoRedTree( treeAutoReduce * node )
{
	int cur_num;

	if( node->son != NULL )//myson
		SearchAutoRedTree( node->son );
	//找到一个叶节点
	else{
		//倒退生成化简树
		//加入本项
		autonum++;//找到叶,就可反向生成一个化简方法
		treeAutoReduce * temp_node = node;
		while( temp_node->par != temp_node ){
			tabAutoReducing[autonum].AddOneLine( 
			temp_node->value ,
			temp_node->maskbit,
			temp_node->num );
			temp_node = temp_node->par;
		};
		if( autonum >= 999 )
			DeleteInvalid();
	}

	if( node->next != NULL )//my brother
		SearchAutoRedTree( node->next );
		
	delete node;

}

//原理:需要很大内存,不可预料
/*
void XReduceTestDlg::SearchAutoRedTree( treeAutoReduce * node )
{
	int cur_num;

	if( node->son != NULL ){//myson
		cur_num = autonum;
		SearchAutoRedTree( node->son );
		//将本项加入所有的现有化简
		for( int i = cur_num+1; i <= autonum ; i++ )
			tabAutoReducing[i].AddOneLine( node->value ,node->maskbit ,node->num );
	}
	//找到一个叶节点
	else{
		//加入本项
		autonum++;//找到叶,就可反向生成一个化简方法
		tabAutoReducing[autonum].AddOneLine( node->value ,node->maskbit,node->num );
	}
	
	if( node->next != NULL )//my brother
		SearchAutoRedTree( node->next );
		
	delete node;

}
*/
void XReduceTestDlg::ReduceNext( treeAutoReduce * par , int val, int mask ,int num )
{
	int pos = 0;
	static int maskbit[4][7] = { {14,13,11,7},{12,10,9,6,5,3},{8,4,2,1},{0} };
	//可化简的项数                 3                2             1        
	static int mask_num[] = { 4,6,4,1 };//3项化简:共有四种屏蔽码
	static int mask_itemnum[] = { 8,4,2,1 };
	int m_num = intValNum == 3 ? 1 : 0;//与变量数有关,8
	int m_idx = m_num;
	int j;
	int high_ok = false;//尽量更多项化简
	treeAutoReduce * par_node = par;
	treeAutoReduce * cur_node = NULL , * bef_node = NULL;

	//删除上一次化简所使用的值
	static int mask_numl[] = { 0,0x1,0x3,0x7 };
	static int mask_numh[] = { 15,12,8,0 };
	bool intArrayValue_old[16];
	int order;
	int t1,t2,t3;
	//贻贝恢复
	for( int i = 0; i < 16 ; i++ )
		intArrayValue_old[i] = intArrayValue[i];

	for( int i = 0; i < num ; i++ ){
		order = i;
		for( int j = 0; j < intValNum ; j++ ){
			if( !( (mask>>j) & 0x1) ){//如果碰到屏蔽位是 0  
				t1 = order & mask_numl[j];//低位
				t2 = val & (0x1<<j) ;//插入位
				t3 = (order<<1) & mask_numh[j];//保留高位
				order = t1 | t2 | t3;
			}
		}
		intArrayValue[order] = false;
	}
	//删除上一次化简所使用的值

	//查找第一个
	while( !intArrayValue[pos] ) pos++;
	if( pos >= 16 ){
		//恢复被删除的值
		for( int i = 0; i < 16 ; i++ )
			intArrayValue[i] = intArrayValue_old[i];		
		return;
	}

	//取intArrayValue第一项值
	for( m_idx = m_num; m_idx <= 3; m_idx++ ){//8项,4项,2项
		for( j = 0; j < mask_num[m_idx]; j++ ){//使用那一个MASK 
			if( CanReduce( pos,maskbit[m_idx][j],mask_itemnum[m_idx] ) ){
				if( high_ok ){//说明同一级存在多种化简方法
					bef_node = cur_node;
					cur_node = new treeAutoReduce;
					bef_node->next = cur_node;
					cur_node->before = bef_node;
					cur_node->par = par_node;
					cur_node->son = NULL;
					cur_node->next = NULL;
					cur_node->value = pos;
					cur_node->maskbit = maskbit[m_idx][j];
					cur_node->num = mask_itemnum[m_idx];
				}
				else{
					high_ok = true;
					cur_node = new treeAutoReduce;
					par_node->son = cur_node;
					cur_node->par = par_node;
					cur_node->before = NULL;
					cur_node->son = NULL;
					cur_node->next = NULL;
					cur_node->value = pos;
					cur_node->maskbit = maskbit[m_idx][j];
					cur_node->num = mask_itemnum[m_idx];
				}
				//继续下一步化简
				ReduceNext( cur_node , pos,maskbit[m_idx][j],mask_itemnum[m_idx] );
			}
		}
		//if( high_ok ) break;//2003_1_7前总是尽量多的项合并,不尽合理
		if( high_ok && (m_idx == 2) ) //如果可以多项合并,则不化简肯定不是最简
			break;//2003_1_7前总是尽量多的项合并,不尽合理
	}

	//恢复被删除的值
	for( int i = 0; i < 16 ; i++ )
		intArrayValue[i] = intArrayValue_old[i];

}

//能否化简
bool XReduceTestDlg::CanReduce( int val, int mask ,int num )
{
	int mask_numl[] = { 0,0x1,0x3,0x7 };
	int mask_numh[] = { 15,12,8,0 };

	//检查相关项是否也是最小项或无关项
	int order;
	int t1,t2,t3;
	for( int i = 0; i < num ; i++ ){
		order = i;
		for( int j = 0; j < intValNum ; j++ ){
			if( !( (mask>>j) & 0x1) ){//如果碰到屏蔽位是 0  
				t1 = order & mask_numl[j];//低位
				t2 = val & (0x1<<j) ;//插入位
				t3 = (order<<1) & mask_numh[j];//保留高位
				order = t1 | t2 | t3;
			}
		}
		//判断是否是最小项
		if( intTabValue[order] == 0 ) return false;
	}

	return true;
}

//未用
void XReduceTestDlg::OnKeyDown( UINT nChar,   UINT nRepCnt,   UINT nFlags )
{
	if( 10 == nChar )
		nChar++;
}
//未用
void XReduceTestDlg::OnKeyUp( UINT nChar,   UINT nRepCnt,   UINT nFlags )
{

//	VK_CONTROL
}

// 正在手工化简
void XReduceTestDlg::DrawSelfReduingTab( CDC * dc)
{
	//若变量还未确定,则不显示具体数值,此时显示没有意义
	if( intProcessState != 2 ) return;

	CRect rect,rectBlock = rectDrawArea;
	CPoint pt;
				
	rectBlock.DeflateRect( 40,40,0,0 );

	int dw = rectBlock.Width() / 4;
	int lnum = (intValNum - 2)*2;
	int dh = rectBlock.Height() / lnum;
	//CString val[3] = { "0","1","X" };
	//int tabVal[][4] = { {0,1,3,2},{4,5,7,6},{12,13,15,14},{8,9,11,10} };
	int Pos[17][2] = { {1,1},{1,2},{1,4},{1,3},//(行,列)
					{2,1},{2,2},{2,4},{2,3},
					{4,1},{4,2},{4,4,},{4,3},
					{3,1},{3,2},{3,4},{3,3} };

	//把已经化简好,用框化出 
	int line_idx,count;
	int data[17];
	COLORREF p_col[] = {
		RGB(255,0,0),  RGB(0,128,0) ,  RGB(0,128,128),  RGB(0,0,255),RGB(128,0,128), 
		RGB(255,128,64),  RGB(255,0,255),RGB(128,128,64),RGB(255,0,128) ,RGB(0,128,255) , RGB(128,0,255),RGB(00,255,0),RGB(128,128,128)  
	};	                 
	CPen * pen;//
	CPen * old_pen;
	

	for( line_idx = 0 ; line_idx < tabSelfReducing.intCurIndex ; line_idx++ ){
		//取出一行
		tabSelfReducing.GetThisLine( line_idx,data, count );
		pen = new CPen(PS_SOLID,3,p_col[line_idx%13] );
		old_pen = dc->SelectObject( pen );
		DrawThisBlock( dc, data, count );
		dc->SelectObject( old_pen );
		delete pen;
		//
	}
	tabSelfReducing.GetThisLine( tabSelfReducing.intCurIndex,data, count );
	//正在化简的一行显示色块
	CBrush brush( RGB(255,0,0) );
	CBrush * old_brush = dc->SelectObject( &brush );
	rectBlock.right = rectBlock.left + dw;
	rectBlock.bottom = rectBlock.top + dh;
	dc->SetROP2(R2_XORPEN);
	for( int i = 0; i < count ; i++ ){
		pt.x = (Pos[ data[i] ][1]-1)*dw;
		pt.y = (Pos[ data[i] ][0]-1)*dh;
		rect = rectBlock + pt;
		dc->Rectangle( &rect );
	}
	dc->SelectObject( old_brush );

}

void XReduceTestDlg::DrawThisBlock(CDC * dc, int * data, int count)
{
	//int tabVal[][4] = { {0,1,3,2},{4,5,7,6},{12,13,15,14},{8,9,11,10} };
	int Pos[17][2] = { {1,1},{1,2},{1,4},{1,3},//(行,列)
						{2,1},{2,2},{2,4},{2,3},
						{4,1},{4,2},{4,4,},{4,3},
						{3,1},{3,2},{3,4},{3,3} };
	int lno_count = 0;//分布于几行中
	bool lno[5];
	bool ano[5];
	int ano_count = 0;//分布于几列中
	int j,line,array;

	for( j = 1 ; j <= 4; j++ ){
		ano[j] = false;
		lno[j] = false;
	}

	//统计分布情况
	for( int i = 0 ; i < count; i++ ){
		if( !lno[ Pos[data[i]][0] ] ){
			lno[ Pos[data[i]][0] ] = true;
			lno_count++;
		}
		if( !ano[ Pos[data[i]][1] ] ){
			ano[ Pos[data[i]][1] ] = true;
			ano_count++;
		}
	}

	//根据统计进行分类
	CRect rectBlock = rectDrawArea;
	rectBlock.DeflateRect( 40,40,0,0 );
	int dw = rectBlock.Width() / 4;
	int lnum = (intValNum - 2)*2;
	int dh = rectBlock.Height() / lnum;

	rectBlock.right = rectBlock.left + dw;
	rectBlock.bottom = rectBlock.top + dh;
	CPoint pt,center;
	CRect rect;
	
		
	if( 1 == count ){
		for( line = 1 ; line <= 4; line++ )
			if(	lno[line] ) break;
		for( array = 1 ; array <= 4; array++ )
			if(	ano[array] ) break;
		rect = rectBlock;	 pt.x = dw*(array-1);	pt.y = dh*(line-1);			rect += pt;
		center = rect.CenterPoint();		pt = center;
		pt.y = center.y + 10; center.y -= 10;
		dc->Arc( &rect,center,center );
	}
	//全部同行
	else if( 1 == lno_count ){
		for( line = 1 ; line <= 4; line++ )
			if(	lno[line] ) break;

		//不相临列,只有可能:2个选择项,同时分布在1,4列
		if( (2 == count) && (ano[1]&&ano[4]) ){
			//化两个半圆
			rect = rectBlock;	 pt.x = 0;		pt.y = dh*(line-1);			rect += pt;
			center = rect.CenterPoint();		pt = center;
			pt.y = center.y + 10; center.y -= 10;
			dc->Arc( &rect,pt,center );
			rect = rectBlock;  pt.x = dw*3; pt.y = dh*(line-1);			rect += pt;
			center = rect.CenterPoint(); 		pt = center;
			pt.y = center.y + 10; center.y -= 10;
			dc->Arc( &rect,center,pt );
		}
		//相临列
		else{
			for( j = 1 ; j <= 4; j++ )
				if(	ano[j] ) break;
			rect = rectBlock;
			pt.x = dw*(j-1); pt.y = dh*(line-1);
			rect += pt;
			center = rect.CenterPoint(); 		pt = center;
			pt.y = center.y + 10; center.y -= 10;
			dc->Arc( &rect,center,pt );

			rect = rectBlock;
			pt.x = dw*(j + count -2); pt.y = dh*(line-1);
			rect += pt;
			center = rect.CenterPoint(); 		pt = center;
			pt.y = center.y + 10; center.y -= 10;
			dc->Arc( &rect,pt,center );
			//画直线
			dc->MoveTo( rectBlock.left + dw*(j-1) +dw/2,rectBlock.top + dh*(line-1) );
			dc->LineTo( rectBlock.left + dw*(j+count-2) +dw/2,rectBlock.top + dh*(line-1) );
			dc->MoveTo( rectBlock.left + dw*(j-1) +dw/2,rectBlock.top + dh*line );
			dc->LineTo( rectBlock.left + dw*(j+count-2) +dw/2,rectBlock.top + dh*line );
		}
	}
	//全部同列
	else if( 1 == ano_count ){
		for( line = 1 ; line <= 4; line++ )
			if(	ano[line] ) break;

		//不相临行,只有可能:2个选择项,同时分布在1,4行
		if( (2 == count) && (lno[1]&&lno[4]) ){
			//化两个半圆
			rect = rectBlock;	 pt.y = 0;		pt.x = dw*(line-1);			rect += pt;
			center = rect.CenterPoint();		pt = center;
			pt.x = center.x + 10; center.x -= 10;
			dc->Arc( &rect,center,pt );
			rect = rectBlock;  pt.y = dh*3; pt.x = dw*(line-1);			rect += pt;
			center = rect.CenterPoint(); 		pt = center;
			pt.x = center.x + 10; center.x -= 10;
			dc->Arc( &rect,pt,center );
		}
		//相临行

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -