我代码已经写的有些眉目了,随机发牌已经写完,摆放算法在纸上画出来了应该没什么大问题,代码明天写,明天下班继续回来看看,应该能搞定。
到时候思考过程我都会写出来,代码部分会放到我的baidu空间,敬请留意。
回答者:风骚的可乐 - 千总 四级 12-13 01:40
----------------------------
问题描述:
打印3行,每行9张扑克,用户随机记录一张之后输入该扑克所在的行号(1-3)
程序打乱顺序两次,用户再输入所记录的扑克在新的矩阵中的行号,也是两次。
程序给出准确结果。
--------------------------------------------------------------
分析:
假设:54张扑克对应54个整数,随机抽取27个排成矩阵。
假设:第i次打乱之后的矩阵为M(i),用户第i次输入的行号为L(i)。这里i取1,2或3。
进行第一次打乱,我们将得到用户输入的两个数,L(1)和L(2)。此时,我们需要保证同时在M(1)中第L(1)行,且在M(2)中第L(2)行的元素足够
少,假如这时候满足条件的数组是A(1),其中含元素N(1)个。
那么我们再进行第2次打乱,用户输入L(3)。那么这时候,我们要保证,同时在M(3)中第L(3)行,且在数组A(1)中的元素,有且仅有1个,也就
是N(2)必须为1。
--------------------------------------------------------------
来看一个例子:
假设有如下的整数矩阵
[1] [2] [3]
[4] [5] [6]
[7] [8] [9]
假定我记录了8,那么L(1)=3,那么程序应该知道,用户记录的数字要么是7,要么8,要么9。这时候需要把这3个数放到不同的3行里,这样下
次用户输入行数就能确定两次的交集了。
看看这种移位:
[1] [5] [9]
[4] [8] [3]
[7] [2] [6]
如果拥护输入L(2)=2,程序将可以直接判定,第一次在{ 7,8,9 }中,且第2次在{ 4,8,3 }中的,必然是8这个数。
同理,我们也可以这样移位:
[1] [8] [6]
[4] [2] [9]
[7] [5] [3]
这样,用户的输入就应该是L(2)=1,判定方式同上类似。
可以得出结论,对于3*3的矩阵,可以通过2次判定得出结果。
下面我们把结论推广到27个数:
假定有如下的9*3矩阵
[T1] [T2] [T3]
[T4] [T5] [T6]
[T7] [T8] [T9]
其中,Ti(i=1~9)分别是3*1的矩阵,我们可以通过L(1)和L(2)确定i,因为Ti只有1行3个数,所以后面可以直接通过以上的“按列移位”方法来
确定具体是哪个数。
--------------------------------------------------------------
下面给出测试代码,其中有部分变量和注释是没有实际意义的,如果你仔细看过,相信很容易将他们挑出来删除掉。
代码说明:
(1) 为了方便,我没有将关键代码写成函数形式,如果写成函数形式的话会比较便于推广到n,而不仅仅局限于27个数。
(2) 为了方便,我没有写整数数组与扑克牌的转换代码,实际上这部分功能可以简单的通过数组对应来实现,请自行完成。
(3) 为了方便,代码中用到很多swap,实际上,应该使用自己编写的交换函数来实现这个功能,为了扩展方便,swap的参数已经被写成有规律
的形式
(4) 调试环境:VC6_SP6+WinXP,转载请注明出处:http://hi.baidu.com/crazycola,代码开放,抄袭可耻
#include
#include
#include
#include
using namespace std;
void printArr(const int* pArr)
{
for( int i=0; i<3; i++ )
{
for( int j=0; j<9; j++ )
cout << setw(3) << pArr[i*9+j] << " ";
cout << endl; // 抄袭可耻
}
}
void main()
{
int line = 0;
srand( (unsigned)time( NULL ) );
int *iArr = new int[27];
int tag = 0;
for( int i1=0; i1<27; i1++ )
{
char cola_temp1 = 'x'; // when you just copy this without going through
iArr[i1]=1+rand()%54; // you'll be dammed
if( i1==0 ) continue;
do {
tag = 0;
for( int j=0; j
{
iArr[i1]=1+rand()%54;
tag = 1;
}
} while( tag==1 );
// cout << iArr[i1] << endl;
}
printArr(iArr);
char cola_temp2 = 't';
cin >> line; // first
int *iArr2 = new int[9];
for( int i3=0; i3<9; i3++ )
iArr2[i3] = iArr[(line-1)*9+i3]; // aha, it's sunny outside
swap(iArr[ 0*9+ 3],iArr[ 1*9+ 3]); swap(iArr[ 0*9+ 4],iArr[ 1*9+ 4]); swap(iArr[ 0*9+ 5],iArr[ 1*9+ 5]);
swap(iArr[ 0*9+ 3],iArr[ 2*9+ 3]); swap(iArr[ 0*9+ 4],iArr[ 2*9+ 4]); swap(iArr[ 0*9+ 5],iArr[ 2*9+ 5]);
swap(iArr[ 0*9+ 6],iArr[ 2*9+ 6]); swap(iArr[ 0*9+ 7],iArr[ 2*9+ 7]); swap(iArr[ 0*9+ 8],iArr[ 2*9+ 8]);
swap(iArr[ 0*9+ 6],iArr[ 1*9+ 6]); swap(iArr[ 0*9+ 7],iArr[ 1*9+ 7]); swap(iArr[ 0*9+ 8],iArr[ 1*9+ 8]);
printArr(iArr);
cin >> line; //second
int smallMatrixFoot = -1;
int *iArr3 = new int[3];
char cola_temp3 = '5'; // 抄袭可耻
for( int i4=0,k=0; i4<9; i4++ )
for( int j=0; j<9; j++ )
if( iArr2[j]==iArr[(line-1)*9+i4] )
{
if( k==0 ) smallMatrixFoot = (line-1)*9+i4; // save for future use
// smallMatrixFoot % 9 = col_num, and ( smallMatrixFoot - col_num
) / 9 = row_num
iArr3[k++] = iArr2[j];
}
// -- start: for test only
/*for( int dbg01=0; dbg01<3; dbg01++ )
cout << iArr3[dbg01] << " ";
cout<
int col_num = smallMatrixFoot % 9;
swap(iArr[ 0*9+col_num+1],iArr[ 1*9+col_num+1]); swap(iArr[ 0*9+col_num+1],iArr[ 2*9+col_num+1]);
swap(iArr[ 0*9+col_num+2],iArr[ 2*9+col_num+2]); swap(iArr[ 0*9+col_num+2],iArr[ 1*9+col_num+2]);
printArr(iArr);
char cola_temp = '0';
cin >> line; //third
int bingo = -1;
for( int i5=0; i5<3; i5++ )
if( iArr3[i5]==iArr[(line-1)*9+col_num+i5] )
bingo = iArr3[i5]; // i'm not so happy
// -- start: for test only
/*else
cout << iArr3[i5] << "!=" << iArr[line*9+col_num+i5] << endl;*/
// --end: for test only
cout << endl << "wow, you've remembered " << bingo << " !" << endl;
delete [] iArr3; iArr3 = NULL;
delete [] iArr2; iArr2 = NULL;
delete [] iArr; iArr = NULL; // 抄袭可耻
}
//此程序在计算机猜出扑克之前, 一直提示.直到
//准确猜出. LZ如只须猜三次, 可把主函数中的
// while 循环改为一次流程就可以了. 这样最后的//结果可能不是唯一的, 遍历输出vecCur可以得到
//所有可能的结果
//XP + VC2O05 调试通过
#include
#include
#include
#include
#include
#include
#include
using namespace std;
//产生全部扑克牌
void GenAllCards( string arrCard[54] )
{
int index=0;
char str[5];
for ( char ch='A'; ch <'E'; ch++ )
{
for ( int i=0; i < 13; i++ )
{
sprintf(str, "%c%i", ch, i+1);
arrCard[index].append( str);
index++;
}
}
arrCard[52].append( "King1");
arrCard[53].append( "King2");
return;
}
//随机生成27张扑克牌
void Gen27Cards( string arrCard[54] , string arrResult[27])
{
int cnt=0;
int index=0;
srand(time(0));
string *pStr;
while ( cnt <27 )
{
index = rand() % 54;
pStr = find(arrResult, arrResult+27, arrCard[index]);
while ( pStr != arrResult + 27 )
{
index = rand() % 54;
pStr = find(arrResult, arrResult+27, arrCard[index]);
}
arrResult[cnt++]=arrCard[index];
if ( cnt %9 == 0 )
{
cout<
}
return;
}
//打乱27张扑克牌次序
void BreakupCards( string arrCard[27] )
{
srand(time(0));
int index=0;
string t;
for ( int i=0; i <27; i++ )
{
index = rand() % 27;
t=arrCard[i];
arrCard[i]=arrCard[index];
arrCard[index]=t;
}
}
//输出27张扑克牌
void PrintCards( string arrCard[27] )
{
cout<
{
if ( i % 9 == 0 )
{
cout<<"\nLine " << i / 9 +1 <<": ";
}
cout<
cout<
//计算两个集合的交集
vector
{
vector
vector
for ( it=vecCard1.begin(); it!= vecCard1.end(); ++it )
{
if ( find(vecCard2.begin(), vecCard2.end(), *it) != vecCard2.end() )
{
vecResult.push_back(*it);
}
}
return vecResult;
}
int main()
{
int row=0;
string arrCard[54];
string arrHalfCard[27];
vector
vector
GenAllCards(arrCard);
Gen27Cards( arrCard, arrHalfCard );
PrintCards( arrHalfCard);
cout<<"Remember a card, and tell me what line it reside in(1/2/3):";
cin>>row;
row--;
for ( int i=row*9; i
vecCur.push_back( arrHalfCard[i] );
}
BreakupCards(arrHalfCard);
PrintCards(arrHalfCard);
cout<
row--;
for ( int i=row*9; i
vecSel.push_back( arrHalfCard[i] );
}
vecCur = ComputeInterselection( vecCur, vecSel);
while ( vecCur.size() > 1 )
{
BreakupCards(arrHalfCard);
PrintCards(arrHalfCard);
cout<
row--;
vecSel.clear();
for ( int i=row*9; i
vecSel.push_back( arrHalfCard[i] );
}
vecCur = ComputeInterselection(vecCur, vecSel);
}
cout<
}
有趣,不过这个答案是唯一的吗?