Perl实战项目:随机生成成语交叉显示在网格(设置不同难度、显示在网页并给出正确答案)

一.设计思路,算法说明

1.基本流程

A.设置三个难度,每个难度的可能出现的成语基数不同,成语出现的方式不同:

难度一:成语基数,随机性低,全部正序出现(从左到右和从上到下);

难度二:成语基数适中,随机性适中,以倒序优先,无可满足的倒序情况则正序出现;

难度三:成语基数最大,随机性高,以倒序优先(同上),部分成语有重合叠加部分

B.生成随机汉字:根据难度划分要读取成语的数量。将成语数组中的汉字全部取出生成汉字数组,在汉字数组中获取随机汉字。

C.生成随机坐标:最后生成的7*7Table是二维数组,每次填成语(或插入单个汉字)之前先获取Table中所有未填充的坐标,然后在未填充的坐标中生成随机坐标。

D.生成可行情况数组:随机汉字插入随机坐标之前,先判定该位置的情况,共设定八种情况:1.右一右二右三为空;2.左一右一右二为空;3.左二左一右一为空;4左三左二左一为空;5.上一上二上三为空;上一上二下一为空;上一下一下二为空下一下二下三为空;将所有满足的情况放入一个“可选情况数组”中。

E.生成汉字在成语不同位置的四个hash表:将所读取的成语生成四个hash表,分别为1.key为成语第一个字;2. key为成语第二个字;3. key为成语第三个字;4. key为成语第四个字,value为其对应成语的hash表。每个hash表在不同的情况使用,例如:hash1可在情况1、情况4、情况5、情况8使用;hash2可在情况2和情况3、情况7和情况8。

F.生成满足情况的随机成语:已知随机汉字,在不同的可行情况选择不同的hash表,从“可选情况数组”中随机选择一个情况,该随机汉字在该情况对应的hash表中随机选取一个成语。

G.插入操作: 由于生成的随机成语已经满足了插入7*7Table的各种限制条件,若取得对应情况的随机成语,故可以直接插入。若在选取的情况没有对应的成语则将之前的随机汉字插入。

2.三个难度的实现

上述操作是难度一(正序)的基本操作。难度一选择读取成语的数量为15

而进行难度二和难度三增加了一些不同的选择条件:

难度二(倒序优先):读取的成语数量选为120;在生成随机成语时,不再从“可选情况数组”中随机选择一个情况,而是优先选择倒装情况,如:设随机字为“X”,在情况1:“X000”右一右二右三为空的情况时优先选取汉字为成语第四个字的成语,如“一二三X”,然后倒装依次插入,完成成语的倒序出现:“X三二一”。如果没有可选的倒装插入的成语就会选取汉字为成语第一个字的成语正序插入。

难度三(倒叙优先+重叠):读取的数量为全部成语;在难度二优先倒装情况的基础上,对随机位置的情况判定分为了两部分:横向位置情况的判定和纵向位置情况的判定。两次情况判定分别随机选出一个(如果存在)可行的情况放入同一个数组中,这个数组中有两个值或一个值或为空。若为空则将之前生成的随机汉字插入,若为一个值则同难度二成语无重合,若数组中为两个值时说明刚刚的随机汉字在横向和纵向同时有可插入的成语,同时在横向和纵向完成不同的成语插入,借此完成了两个成语的重合叠加。

由于不同等级所选的成语基数不同,生成的对应成语不同位置(如key为第一字,value为对应成语)的四个hash表中的成语数量不同,由于插入时有条件限制,成语越多对应的hash表中越容易有满足条件的成语,故在生成满足条件的可插入的成语将会随着等级升高而增多,以此来满足不同难度成语数量不同;而随着随机成语的基数增多,成语的随机性也会随着等级的提高而提高,难度也相应有些提高。

3.主要函数

       getLevel():在此函数中和玩家交互获得难度。

       getIdiomNum():获取根据IO玩家的选择来读取的成语总数;

       genEmptyTable7x7():获取初始表,表中的值全为0;

       situation():参数为要填充的随机汉字的横坐、纵坐标、以及要填充的表。这个函数用来首先会判断要填充的位置是否为空,若为空则判断其周围位置的情况,分为八种情况:分别对应要填充的字为横向成语的第一、二、三、四个字和纵向成语的第一、二、三、四个字。初始化表中值为0,故判断是否为未填充成语的条件为是否为0,函数的返回值是可行情况数组中的随机一个情况(可为横向情况或纵向情况);

       situation_hard():基本流程同函数situation(),但在此函数中横向(情况一二三四)和纵向(情况五六七八)的情况分别各放入一个数组中,然后再从两个数组中分别随机选取一个,最后返回横向纵向的情况各一个(如果存在),在paddingTable_Hard()中调用。

       IdiomArray2Hashs():将读取的每一个成语都按照key为第一或第二或第三或第四个字,value为对应成语的四个hash表,在之前判断了不同情况下可选取不同的hash表来完成填充以确保成语刚好能填充到为空的位置;

       padding():在此函数中通过getLevel()函数中获得的难度等级变量,根据该变量来判断调用paddingTable()、              paddingTable_Normal()、paddingTable_Hard()三个哪个变量;

       genRandomPosition():获取当前填充的7*7Table为空的坐标,横纵坐标一一对应,分别放入两个数组的对应位置。而生成的随机坐标将从这两个数组中得出。若无空白位置则返回-1;返回值为一个未填充位置的随机坐标。

       getRandomHZ():从读取的所有成语中的所有的字中选出随机字;

       choose_situation_PSonly():只选择正序填充成语的情况来完成填充的函数。在paddingTable()中调用。

       choose_situation_Reverse():对于随机字,如果存在对应情况且可倒序插入的成语则倒序填充,若不存在则选择正序填充成语。在函数paddingTable_Normal()和函数paddingTable_Hard()中调用。

       paddingTable():难度一时采用的填充函数,参数为要读取的成语数组和这些成语中出现的字的数组。该函数在一个while循环中,分别用调用函数getRandomHZ()和genRandomPosition()获取随机坐标,然后利用函数choose_situation_PSonly()来正序完成成语的插入,不断生成随机字和随机位置完成插入直到7*7Table被填满为止;

       paddingTable_Normal():难度二时采用的填充函数,参数为要读取的成语数组和这些成语中出现的字的数组。该函数在一个while循环中,分别用调用函数getRandomHZ()和genRandomPosition()获取随机坐标,然后利用函数                           choose_situation_Reserve()来完成成语的插入(若有满足倒序插入的成语则插入,若没有则插入满足正序插入的成语,若两者都没有则插入随机字),不断生成随机字和随机位置完成插入直到7*7Table被填满为止;

      paddingTable_Hard():难度三时采用的填充函数,参数为要读取的成语数组和这些成语中出现的字的数组。在获取随机字和随机位置之后,利用situation_hard()函数返回的一个数组(),数组长度可为0或1或2。在此函数中对该数组进行while(1)遍历,完成对数组中情况的遍历,若为2则同时插入横向和纵向两个成语完成成语的重叠。若数组长度为1或0则同paddingTable_Normal();

      print_html():将生成的table7*7打印网页;

      PrintAnswer():打印答案到txt文件中;

二.代码及注释

       代码与注释见IdiomGame.pl;

       生成的网页见IdiomGame.html;

       成语所在位置见answer.txt;

三. 结果显示

1.难度一结果展示:

难度一:成语基数,随机性低,全部正序出现(从左到右和从上到下);

Cmd:

IdiomGame.html:

Answer.txt:

2.难度二结果展示:

难度二:成语基数适中,随机性适中,以倒序优先,无可满足的倒序情况则正序出现;

Cmd:

IdiomGame.html:

Answer.txt:

3.难度三结果展示:

难度三:成语基数最大,随机性高,以倒序优先(同上),部分成语有重合叠加部分

Cmd:

IdiomGame.html:

Answer.txt:

 

五、代码

playIdiomGame();


sub playIdiomGame{
	globle_init();
	padding();
	output();
}
sub globle_init{
	$level=getLevel();
	$idiom_num=getIdiomNum(\level);
	ReadIdiom("IdiomPy.txt",\@Idiom,\$idiom_num);
	Idiom2HZs(\@Idiom,\%I2HZs,\@HZarray);
	getRandomHZ(\@HZarray);
	genEmptyTable7x7(\@Table);
	genEmptyTable7x7(\@Answer);
}
sub padding{
	if($level==1){paddingTable(\@Idiom,\@HZarray);}
	if($level==2){paddingTable_Normal(\@Idiom,\@HZarray);}
	if($level==3){paddingTable_Hard(\@Idiom,\@HZarray);}
}
sub output{
	displayTable(\@Table);
	print"\n答案可见answer.txt\n";
	PrintAnswer(">answer.txt",\@Answer);
	print"\n网页可见IdiomGame.html\n   :)";
	print_html(\@Table,\@Answer);
}
sub ReadIdiom	#根据难度不同读取不同数目成语
{
	my($dict,$ref1,$ref2)[email protected]_;
	open(In,$dict);
	while(<In>){
		chomp;
		if(/(\S+) ([^_]+)\d.*_([^_]+)\d$/){
			push(@{$ref1},$1);
			$i++;
			if($i==${$ref2}){last;}
		}
	}
	close(In);
}
sub getLevel{
	print"plz choose the difficulty of IdiomGame\n\t\t1:easy\n\t\t2:normal\n\t\t3:hard\ninput(1 or 2 or 3)";
	chomp($inp=<stdin>);
	return $inp;
	}
sub getIdiomNum{
	my($ref1)[email protected]_;
	if(${$ref1}==1){
	$idiom_num=15;}
	if(${$ref1}==2){
	$idiom_num=120;}
	if(${$ref1}==3){
	$idiom_num=5000;}
	return $idiom_num;
}
sub Idiom2HZs{#得到每个成语对应的四个汉字。成语为key,汉字为value;
	my($ref1,$ref2,$ref3)[email protected]_;
	my(@HZs);
	foreach(@{$ref1}){
		@HZs=$_=~/../g;#两点匹配一个汉字
		@{${$ref2}{$_}}[email protected];
		foreach(@HZs){push(@{$ref3},$_);}#得到所有出现过的汉字的array
	}
}
sub genEmptyTable7x7{
	my($t)[email protected]_;
	for($i=0;$i<7;$i++){
		for($j=0;$j<7;$j++){
			${$t}[$i][$j]=0;
		}
	}
}
sub displayTable{
	my($t)[email protected]_;
	for($i=0;$i<7;$i++){
		for($j=0;$j<7;$j++){
			print "${$t}[$i][$j]\t";
		}
		print "\n";
	}
}
sub getRandomHZ{
	my($ref)[email protected]_;
	my($num);
	$num=int(rand()*@{$ref});
	return ${$ref}[$num];
}
#参数为随机位置和要插入的表,获取这个位置中有哪几种可以插入成语的情况,并返回其中一种
sub situation{
	my($h,$l,$t)[email protected]_;
	my(@situationNum);
	@situationNum=();
	if(${$t}[${$h}][${$l}] eq "0"){
		if((${$t}[${$h}][${$l}+3] eq "0") and (${$t}[ ${$h} ][${$l}+2] eq "0") and ( ${$l}+3 <7 ) and (${$t}[${$h}][ ${$l}+1] eq "0") ){
		push(@situationNum,1);
		}	
		if((${$t}[${$h}][${$l}+1] eq "0") and(${$t}[${$h}][${$l}+2] eq "0")  and(int(${$l}+2)<7) and (${$t}[${$h}][${$l}-1] eq "0")  and (${$l}-1)>-1){
		push(@situationNum,2);
		}
		if(${$t}[${$h}][ ${$l}+1] eq "0" and ${$t}[${$h}][${$l}-2] eq "0" and ${$l}+1<7 and ${$t}[${$h}][${$l}-1] eq "0"  and ${$l}-2>-1){
		push(@situationNum,3);
		}
		if(${$t}[${$h}][${$l}-1] eq "0"  and ${$t}[${$h}][${$l}-2] eq "0"  and ${$t}[${$h}][${$l}-3] eq "0"  and ${$l}-3>-1){
		push(@situationNum,4);
		}
		if(${$t}[${$h}+3][$l] eq "0" and ${$t}[${$h}+2][$l] eq "0"  and ${$h}+3<7 and ${$t}[${$h}+1][${$l}] eq "0" ){
		push(@situationNum,5);
		}
		if(${$t}[${$h}+1][${$l}] eq "0" and ${$t}[${$h}+2][${$l}] eq "0"  and ${$h}+2<7 and ${$t}[${$h}-1][${$l}] eq "0"  and ${$h}-1>-1){
		push(@situationNum,6);
		}
		if(${$t}[${$h}+1][$l] eq "0" and ${$t}[${$h}-2][$l] eq "0" and ${$h}+1<7 and ${$t}[${$h}-1][$l] eq "0"  and ${$h}-2>-1){
		push(@situationNum,7);
		}
		if((${$t}[${$h}-1][${$l}] eq "0") and ${$t}[${$h}-2][${$l}] eq "0" and ${$t}[${$h}-3][${$l}]eq "0"  and ${$h}-3>-1){
		push(@situationNum,8);
		}
		$choose=int(rand()*@situationNum);
		if(@situationNum>0){return $situationNum[$choose];}#先看是否有情况进入数组
		else{return -1;}
	}
	elsif(${$t}[${$h}][${$l}] ne '0'){	
		return -1;}
}
#将成语分入四个hash表中:如
#key为A 读取的成语这种第一/二/三/四个字为A的所有成语(如Axxx/xAxx/xxAx/xxxA)为value
#在函数choose_situation_PSonly()和choose_situation_Reverse()中对value中的成语随机获取
sub IdiomArray2Hashs{
	my($Idioms)[email protected]_;
	foreach(@{$Idioms}){
		if(/(..)(..)(..)(..)/){
			push(@{$first2Idiom{$1}},$1);
			push(@{$first2Idiom{$1}},$2);
			push(@{$first2Idiom{$1}},$3);
			push(@{$first2Idiom{$1}},$4);
			push(@{$second2Idiom{$2}},$1);
			push(@{$second2Idiom{$2}},$2);
			push(@{$second2Idiom{$2}},$3);
			push(@{$second2Idiom{$2}},$4);
			push(@{$third2Idiom{$3}},$1);
			push(@{$third2Idiom{$3}},$2);
			push(@{$third2Idiom{$3}},$3);
			push(@{$third2Idiom{$3}},$4);
			push(@{$fourth2Idiom{$4}},$1);
			push(@{$fourth2Idiom{$4}},$2);
			push(@{$fourth2Idiom{$4}},$3);
			push(@{$fourth2Idiom{$4}},$4);
			}
		}
}
#paddingTable和situation一一对应,situ_choose=1则按照situation1的情况放成语,放的成语是"随机生成的汉字"为第一个字的成语,若没有对应的成语则放入该随机字。
sub genRandomPosition{
	my($t)[email protected]_;
	my($hang,$lie);
	my(@a,@b);
	@a=();
	@b=();
	for($i=0;$i<7;$i++){#读取目前没有填充的位置,横纵坐标分别放在两个数组中且一一对应
		for($j=0;$j<7;$j++){
			if(${$t}[$i][$j] eq "0"){
				push(@a,$i);
				push(@b,$j);
			}
		}
	}
	if(@a==0 and @b==0){#数组为空说明全部填充完毕则返回负值随机位置
		$hang=-1;$lie=-1;
		return $hang,$lie;}
	else{
		$rand=int(rand()*@a);
		$hang=$a[$rand];#取随机坐标时,横纵是对应的
		$lie=$b[$rand];
	}
#	print"hanglie$hang $lie\t";
	return $hang,$lie;
}
#难度一调用
sub paddingTable{
	my($Is,$HZs)[email protected]_;#成语列表 7x7表 汉字列表
	IdiomArray2Hashs(\@{$Is});
	my($q);
	while(1){
	$q++;
	my($HZ)=getRandomHZ(\@{$HZs});
	my($h,$l)=genRandomPosition(\@Table);#对现有的表遍历收集未填的点
#	print"随机的坐标:$h,$l\n";
#	print"随机的汉字:$HZ\n";
	if($h == -1 and $l == -1){
		last;}
	else{
	my($situ_choose)=situation(\$h,\$l,\@Table);
	choose_situation_PSonly(\$situ_choose,\$HZ,\$h,\$l);
	}
	#displayTable(\@Table);
	#print"\n";
}	print"\n通过$q\次循环完成padding\n";
	}
#难度一调用
sub choose_situation_PSonly{#只有正序填充
	my($situ_choose,$HZ,$h,$l)[email protected]_;
	if(${$situ_choose}==-1or${$situ_choose}==0){
		$Table[${$h}][${$l}]=${$HZ} ;
		#	print"此时没有满足的情况\n";
	}
	if( ${$situ_choose} ==1){
		$i=0;
		if(@{$first2Idiom{${$HZ}}}==0){$Table[${$h}][${$l}]=${$HZ};}
		else{	
			$x=4*int(rand()*((@{$first2Idiom{${$HZ}}}-4)/4));
			#克服了汉字在对应hash表的value(成语的字数组)中只能取到第一个成语的问题,能随机取到value中成语
			while(1){	
		$Table[${$h}][${$l}+$i]=${$first2Idiom{${$HZ}}}[$x+$i];
		$Answer[${$h}][${$l}+$i]=${$first2Idiom{${$HZ}}}[$x+$i];
				$i++;
				if($i==4){last;}
		}
		}
	}
	if(${$situ_choose}==2){
		$i=0;
		if(@{$second2Idiom{${$HZ}}}==0){$Table[${$h}][${$l}]=${$HZ};}
		else{
		$x=4*int(rand()*((@{$second2Idiom{${$HZ}}}-4)/4));
		while(1){	
		$Table[${$h}][${$l}-1+$i]=${$second2Idiom{${$HZ}}}[$x+$i];
		$Answer[${$h}][${$l}-1+$i]=${$second2Idiom{${$HZ}}}[$x+$i];
		$i++;
		if($i==4){last;}
		}
	}
	}
	if( ${$situ_choose}==3){
		$i=0;
		if(@{$third2Idiom{${$HZ}}}==0){$Table[${$h}][${$l}]=${$HZ};}
		else{
			$x=4*int(rand()*((@{$third2Idiom{${$HZ}}}-4)/4));
		while(1){	
			$Table[${$h}][${$l}-2+$i]=${$third2Idiom{${$HZ}}}[$x+$i];
			$Answer[${$h}][${$l}-2+$i]=${$third2Idiom{${$HZ}}}[$x+$i];
			$i++;
			if($i==4){last;}
		}
	}}
	if(${$situ_choose}==4){
		$i=0;
		if(@{$fourth2Idiom{${$HZ}}}==0){$Table[${$h}][${$l}]=${$HZ};}
		else{
		$x=4*int(rand()*((@{$fourth2Idiom{${$HZ}}}-4)/4));
		while(1){	
			$Table[${$h}][${$l}-3+$i]=${$fourth2Idiom{${$HZ}}}[$x+$i];
			$Answer[${$h}][${$l}-3+$i]=${$fourth2Idiom{${$HZ}}}[$x+$i];
			$i++;
			if($i==4){last;}
		}
	}
	}
	if(${$situ_choose}==5){
		$i=0;
		if(@{$first2Idiom{${$HZ}}}==0){$Table[${$h}][${$l}]=${$HZ};}
		else{
			$x=4*int(rand()*((@{$first2Idiom{${$HZ}}}-4)/4));
		while(1){
		$Table[${$h}+$i][${$l}]=${$first2Idiom{${$HZ}}}[$x+$i];
		$Answer[${$h}+$i][${$l}]=${$first2Idiom{${$HZ}}}[$x+$i];
			$i++;
			
			if($i==4){last;}
		}
	}}
	if( ${$situ_choose}==6){
		$i=0;
		if(@{$second2Idiom{${$HZ}}}==0){$Table[${$h}][${$l}]=${$HZ};}
		else{
			$x=4*int(rand()*((@{$second2Idiom{${$HZ}}}-4)/4));
		while(1){
		$Table[${$h}-1+$i][${$l}]=${$second2Idiom{${$HZ}}}[$x+$i];
		$Answer[${$h}-1+$i][${$l}]=${$second2Idiom{${$HZ}}}[$x+$i];
			$i++;
			if($i==4){last;}
		}
	}}
	if( ${$situ_choose}==7){
			$i=0;
		if(@{$third2Idiom{${$HZ}}}==0){$Table[${$h}][${$l}]=${$HZ};}
		else{
			$x=4*int(rand()*((@{$third2Idiom{${$HZ}}}-4)/4));
		while(1){	
		$Table[${$h}-2+$i][${$l}]=${$third2Idiom{${$HZ}}}[$x+$i];
		$Answer[${$h}-2+$i][${$l}]=${$third2Idiom{${$HZ}}}[$x+$i];
				$i++;
				if($i==4){last;}
		}
	}
	}
	if(${$situ_choose}==8){
		$i=0;
		if(@{$fourth2Idiom{${$HZ}}}==0){$Table[${$h}][${$l}]=${$HZ};}
		else{
			$x=4*int(rand()*((@{$fourth2Idiom{${$HZ}}}-4)/4));
		while(1){
		$Table[${$h}-3+$i][${$l}]=${$fourth2Idiom{${$HZ}}}[$x+$i];
		$Answer[${$h}-3+$i][${$l}]=${$fourth2Idiom{${$HZ}}}[$x+$i];
				$i++;
			if($i==4){last;}
			}
	}	
		}
}
#难度二、难度三调用
sub choose_situation_Reverse{
#提供一个汉字,其坐标和选择的情况,可将这个汉字的按照情况随机成语插入
	my($situ_choose,$HZ,$h,$l)[email protected]_;
	if(${$situ_choose}==-1 or ${$situ_choose}==0){
		$Table[${$h}][${$l}]=${$HZ} ;
	}
	if(${$situ_choose} ==1){
		$i=0;$j=0;
		if(@{$first2Idiom{${$HZ}}}==0 and @{$fourth2Idiom{${$HZ}}}==0){$Table[${$h}][${$l}]=${$HZ};}
		elsif(@{$fourth2Idiom{${$HZ}}}){
			#倒序的完成:坐标+3后然后i--(倒着输入)
			$x=4*int(rand()*((@{$fourth2Idiom{${$HZ}}}-4)/4));
		while(1){	
				$Table[${$h}][${$l}+3+$i]=${$fourth2Idiom{${$HZ}}}[$x+$j];
				$Answer[${$h}][${$l}+3+$i]=${$fourth2Idiom{${$HZ}}}[$x+$j];
				$i--;
				$j++;
				if($i==-4){last;}
		}
		}
		elsif(@{$first2Idiom{${$HZ}}}){
		$x=4*int(rand()*((@{$first2Idiom{${$HZ}}}-4)/4));#克服了汉字在第一个位置的成语数组中只能取到第一个成语的问题
			while(1){					
				$Table[${$h}][${$l}+$i]=${$first2Idiom{${$HZ}}}[$x+$i];;
				$Answer[${$h}][${$l}+$i]=${$first2Idiom{${$HZ}}}[$x+$i];;
				$i++;
				if($i==4){last;}
		
			}
		}
		else{$Table[${$h}][${$l}]=${$HZ};}
		
	}
	if( ${$situ_choose}==2){
		$i=0;$j=0;
		if(@{$second2Idiom{${$HZ}}}==0 and @{$third2Idiom{${$HZ}}}==0){$Table[${$h}][${$l}]=${$HZ};}
		elsif(@{$third2Idiom{${$HZ}}}){
$x=4*int(rand()*((@{$third2Idiom{${$HZ}}}-4)/4));
		while(1){
		$Table[${$h}][${$l}+2+$i]=${$third2Idiom{${$HZ}}}[$x+$j];
		$Answer[${$h}][${$l}+2+$i]=${$third2Idiom{${$HZ}}}[$x+$j];
		$i--;$j++;
		if($i==-4){last;}
		}
		}
		elsif(@{$second2Idiom{${$HZ}}}){
		$x=4*int(rand()*((@{$second2Idiom{${$HZ}}}-4)/4));
		while(1){	
		$Table[${$h}][${$l}-1+$i]=${$second2Idiom{${$HZ}}}[$x+$i];
		$Answer[${$h}][${$l}-1+$i]=${$second2Idiom{${$HZ}}}[$x+$i];
		$i++;
		
		if($i==4){last;}
		}
	}
		else{$Table[${$h}][${$l}]=${$HZ};}
	}
	if( ${$situ_choose} ==3){
		$i=0;$j=0;
		if(@{$third2Idiom{${$HZ}}}==0 and @{$second2Idiom{${$HZ}}}==0){$Table[${$h}][${$l}]=${$HZ};}
		elsif(@{$second2Idiom{${$HZ}}}){
			$x=4*int(rand()*((@{$second2Idiom{${$HZ}}}-4)/4));
		while(1){	
			$Table[${$h}][${$l}+1+$i]=${$second2Idiom{${$HZ}}}[$x+$j];
			$Answer[${$h}][${$l}+1+$i]=${$second2Idiom{${$HZ}}}[$x+$j];
			$i--;
			$j++;
			if($i==-4){last;}
		}
		
		}
		elsif(@{$third2Idiom{${$HZ}}})
		{
			$x=4*int(rand()*((@{$third2Idiom{${$HZ}}}-4)/4));
		while(1){
			$Table[${$h}][${$l}-2+$i]=${$third2Idiom{${$HZ}}}[$x+$i];;
			$Answer[${$h}][${$l}-2+$i]=${$third2Idiom{${$HZ}}}[$x+$i];;
			$i++;
			if($i==4){last;}
		}
	}
	else{$Table[${$h}][${$l}]=${$HZ};}
	}
	if( ${$situ_choose}==4){
		$i=0;$j=0;
		if(@{$fourth2Idiom{${$HZ}}}==0 and @{$first2Idiom{${$HZ}}}==0){$Table[${$h}][${$l}]=${$HZ};}
		elsif(@{$first2Idiom{${$HZ}}}){
	$x=4*int(rand()*((@{$first2Idiom{${$HZ}}}-4)/4));
			while(1){		
		$Table[${$h}][${$l}+$i]=${$first2Idiom{${$HZ}}}[$x+$j];
			$Answer[${$h}][${$l}+$i]=${$first2Idiom{${$HZ}}}[$x+$j];
			$i--;$j++;
			if($i==-4){last;}
		}
		
		}
		elsif(@{$fourth2Idiom{${$HZ}}}){
			$x=4*int(rand()*((@{$fourth2Idiom{${$HZ}}}-4)/4));
			while(1){				
			$Table[${$h}][${$l}-3+$i]=${$fourth2Idiom{${$HZ}}}[$x+$i];
			$Answer[${$h}][${$l}-3+$i]=${$fourth2Idiom{${$HZ}}}[$x+$i];
			$i++;
			if($i==+4){last;}
		}
		}
	else{$Table[${$h}][${$l}]=${$HZ};}
	}
	if( ${$situ_choose} ==5){
		$i=0;$j=0;
		if(@{$first2Idiom{${$HZ}}}==0 and @{$fourth2Idiom{${$HZ}}}==0){$Table[${$h}][${$l}]=${$HZ};}
		elsif(@{$fourth2Idiom{${$HZ}}}){
			$x=4*int(rand()*((@{$fourth2Idiom{${$HZ}}}-4)/4));#克服了汉字在第一个位置的成语数组中只能取到第一个成语的问题
			while(1){				
			
			$Table[${$h}+3+$i][${$l}]=${$fourth2Idiom{${$HZ}}}[$x+$j];
			$Answer[${$h}+3+$i][${$l}]=${$fourth2Idiom{${$HZ}}}[$x+$j];
			$i--;
			$j++;
			
			if($i==-4){last;}
		}
		
		}
		elsif(@{$first2Idiom{${$HZ}}}){
	$x=4*int(rand()*((@{$first2Idiom{${$HZ}}}-4)/4));
			while(1){
			$Table[${$h}+$i][${$l}]=${$first2Idiom{${$HZ}}}[$x+$i];
			$Answer[${$h}+$i][${$l}]=${$first2Idiom{${$HZ}}}[$x+$i];
			$i++;
			
			if($i==4){last;}
		}
	}
	else{$Table[${$h}][${$l}]=${$HZ};}
	}
	if( ${$situ_choose} ==6){
		$i=0;$j=0;
		if(@{$second2Idiom{${$HZ}}}==0 and @{$third2Idiom{${$HZ}}}==0){$Table[${$h}][${$l}]=${$HZ};}
		elsif(@{$third2Idiom{${$HZ}}}){
			$x=4*int(rand()*((@{$third2Idiom{${$HZ}}}-4)/4));
		while(1){
			$Table[${$h}+2+$i][${$l}]=${$third2Idiom{${$HZ}}}[$x+$j];
			$Answer[${$h}+2+$i][${$l}]=${$third2Idiom{${$HZ}}}[$x+$j];
			$i--;$j++;
			if($i==-4){last;}
		}}
		elsif(@{$second2Idiom{${$HZ}}}){
			$x=4*int(rand()*((@{$second2Idiom{${$HZ}}}-4)/4));
		while(1){
			$Table[${$h}-1+$i][${$l}]=${$second2Idiom{${$HZ}}}[$x+$i];
			$Answer[${$h}-1+$i][${$l}]=${$second2Idiom{${$HZ}}}[$x+$i];
			$i++;
			if($i==4){last;}
		}
	}
	else{$Table[${$h}][${$l}]=${$HZ};}
	}
	if( ${$situ_choose} ==7){
			$i=0;$j=0;
		if(@{$third2Idiom{${$HZ}}}==0 and @{$second2Idiom{${$HZ}}}==0){$Table[${$h}][${$l}]=${$HZ};}
		elsif(@{$second2Idiom{${$HZ}}}){
			$x=4*int(rand()*((@{$second2Idiom{${$HZ}}}-4)/4));
		while(1){
			$Table[${$h}+1+$i][${$l}]=${$second2Idiom{${$HZ}}}[$x+$j];
				$Answer[${$h}+1+$i][${$l}]=${$second2Idiom{${$HZ}}}[$x+$j];
				$i--;$j++;
				if($i==-4){last;}
		}
		}
		elsif(@{$third2Idiom{${$HZ}}}){	
		$x=4*int(rand()*((@{$third2Idiom{${$HZ}}}-4)/4));
		while(1){
		$Table[${$h}-2+$i][${$l}]=${$third2Idiom{${$HZ}}}[$x+$i];
				$Answer[${$h}-2+$i][${$l}]=${$third2Idiom{${$HZ}}}[$x+$i];
				$i++;
				if($i==4){last;}
		}
	}
	else{$Table[${$h}][${$l}]=${$HZ};}
	}
	if( ${$situ_choose} ==8){
		$i=0;$j=0;
		if(@{$fourth2Idiom{${$HZ}}}==0 and @{$first2Idiom{${$HZ}}}==0){$Table[${$h}][${$l}]=${$HZ};}
		elsif(@{$first2Idiom{${$HZ}}}){
	$x=4*int(rand()*((@{$first2Idiom{${$HZ}}}-4)/4));
			while(1){
			$Table[${$h}+$i][${$l}]=
		$Table[${$h}+$i][${$l}]=${$first2Idiom{${$HZ}}}[$x+$j];
			$Answer[${$h}+$i][${$l}]=${$first2Idiom{${$HZ}}}[$x+$j];
			$j++;
			$i--;
			if($i==-4){last;}
			}
		}
		elsif(@{$fourth2Idiom{${$HZ}}}){
		$x=4*int(rand()*((@{$fourth2Idiom{${$HZ}}}-4)/4));
			while(1){
		$Table[${$h}-3+$i][${$l}]=${$fourth2Idiom{${$HZ}}}[$x+$i];
			$Answer[${$h}-3+$i][${$l}]=${$fourth2Idiom{${$HZ}}}[$x+$i];
			$i++;
			if($i==4){last;}
			}
	}	
		else{$Table[${$h}][${$l}]=${$HZ};}
		}
}	
sub PrintAnswer{
	my($out,$ans)[email protected]_;
	open(out,$out);
	print out "此时7x7的表格中的成语分布为\n";
	for($i=0;$i<7;$i++){
		for($j=0;$j<7;$j++){
			print out "${$ans}[$i][$j]\t";
		}
		print out "\n";
	}	
}
sub paddingTable_Normal{
	my($Is,$HZs)[email protected]_;#成语列表 7x7表 汉字列表
	#print"随机的汉字: $HZ !!!选择的情况为:$situ_choose \n";
	IdiomArray2Hashs(\@{$Is});
	my($q);
	while(1){
	$q++;
	my($HZ)=getRandomHZ(\@{$HZs});
	my($h,$l)=genRandomPosition(\@Table);#对现有的表遍历收集未填的点
	if($h == -1 and $l == -1){
		last;}
	else{
	my($situ_choose)=situation(\$h,\$l,\@Table);
	choose_situation_Reverse(\$situ_choose,\$HZ,\$h,\$l);
	}
	#displayTable(\@Table);
	#print"\n";
	}
	print"\n通过$q\次循环完成padding\n";
}
#situation()返回一个情况,而situation_hard()返回横纵各一个情况(如果存在)
sub situation_hard{
	my($h,$l,$t)[email protected]_;
	my(@situationNum,@h_sit,@l_sit);
	@situationNum=();
	@h_sit=();
	@l_sit=();
	if(${$t}[${$h}][${$l}] eq "0"){
		#此处的if要完全并列,不然就不能同时push到数组中多种情况了
		if((${$t}[${$h}][${$l}+3] eq "0") and (${$t}[ ${$h} ][${$l}+2] eq "0") and ( ${$l}+3 <7 ) and (${$t}[${$h}][ ${$l}+1] eq "0") ){
			push(@h_sit,1);
		}
		if((${$t}[${$h}][${$l}+1] eq "0") and(${$t}[${$h}][${$l}+2] eq "0")  and(int(${$l}+2)<7) and (${$t}[${$h}][${$l}-1] eq "0")  and (${$l}-1)>-1){
			push(@h_sit,2);
		}
		if(${$t}[${$h}][ ${$l}+1] eq "0" and ${$t}[${$h}][${$l}-2] eq "0" and ${$l}+1<7 and ${$t}[${$h}][${$l}-1] eq "0"  and ${$l}-2>-1){
			push(@h_sit,3);
		}
		if(${$t}[${$h}][${$l}-1] eq "0"  and ${$t}[${$h}][${$l}-2] eq "0"  and ${$t}[${$h}][${$l}-3] eq "0"  and ${$l}-3>-1){
			push(@h_sit,4);
		}
		if(${$t}[${$h}+3][$l] eq "0" and ${$t}[${$h}+2][$l] eq "0"  and ${$h}+3<7 and ${$t}[${$h}+1][${$l}] eq "0" ){
			push(@l_sit,5);
		}
		if(${$t}[${$h}+1][${$l}] eq "0" and ${$t}[${$h}+2][${$l}] eq "0"  and ${$h}+2<7 and ${$t}[${$h}-1][${$l}] eq "0"  and ${$h}-1>-1){
			push(@l_sit,6);
		}
		if(${$t}[${$h}+1][$l] eq "0" and ${$t}[${$h}-2][$l] eq "0" and ${$h}+1<7 and ${$t}[${$h}-1][$l] eq "0"  and ${$h}-2>-1){
			push(@l_sit,7);
		}
		if((${$t}[${$h}-1][${$l}] eq "0") and ${$t}[${$h}-2][${$l}] eq "0" and ${$t}[${$h}-3][${$l}]eq "0"  and ${$h}-3>-1){
			push(@l_sit,8);
		}
		if(@h_sit>0){
			$h_choose=int(rand()*@h_sit);
			push(@situationNum,$h_sit[$h_choose]);}
		if(@l_sit>0){
			$l_choose=int(rand()*@l_sit);
			push(@situationNum,$l_sit[$l_choose]);}
		if(@situationNum>0){
			return @situationNum;}#先看是否有情况进入数组 
		else{ 
			@situationNum=();
			return @situationNum;}
	}
	elsif(${$t}[${$h}][${$l}] ne '0'){	
		@situationNum=();
		return @situationNum;}
}
#调用situation_hard()函数,对其返回的两个情况进行遍历依次填充	
sub paddingTable_Hard{
	my($Is,$HZs)[email protected]_;;#成语列表 7x7表 汉字列表
	IdiomArray2Hashs(\@{$Is});
	my($q);
	while(1){
	$q++;
	my($HZ)=getRandomHZ(\@{$HZs});
	my($h,$l)=genRandomPosition(\@Table);#对现有的表遍历收集未填的点
	if($h == -1 and $l == -1){
		last;}
	else{
	my(@situ_chooses)=situation_hard(\$h,\$l,\@Table);
	if(@situ_chooses==0){
		$Table[$h][$l]=$HZ ;
	}
	
	elsif(@situ_chooses>0){
	foreach(@situ_chooses){
	my($situ_choose)=$_;
	choose_situation_Reverse(\$situ_choose,\$HZ,\$h,\$l);
			}	
		}
	}
	#displayTable(\@Table);
	#print"\n";
	}print"\n通过$q\次循环完成padding\n";
	}
sub genHtml(){
    open(OutHtml,'>IdiomGame.html');
    return OutHtml;
}	
sub print_html(){
	my($t,$ans)[email protected]_;
	my($OutHtml)=genHtml();
	print $OutHtml "<html><center>";
	print $OutHtml "<h2>IdiomGame</h2>";
	print $OutHtml '<table width="20%" height="20%" align="center" border>';#设置表的长宽
    for($i=0;$i<7;$i++){
		print $OutHtml  "<tr>";#table换行用<tr>
	    for($j=0;$j<7;$j++){
			if(${$ans}[$i][$j] eq "0"){
				print $OutHtml  "<td style=\"font-family:\'楷体';font-size:30px;\">${$t}[$i][$j]</td>";}#设置字体和字的大小以及背景颜色
			else{
				print $OutHtml  "<td style=\"font-family:\'楷体';font-size:30px;\" bgcolor=\"red\">${$t}[$i][$j]</td>"
			}
		}
		print $OutHtml "</tr>";
	}
	print $OutHtml "</table>";
	print $OutHtml "<h5>red part is the answer!</h5></center>";
	print $OutHtml "</html>";
}
	#难度1:少量词。正序
	#难度2:中等词。倒序优先,无倒序则正序。
	#难度3:大量词。主要优先。有重叠部分的成语。