[r1]: / Mahjongg.project  Maximize  Restore  History

Download this file

566 lines (501 with data), 2.4 MB

VAR_GLOBAL
    hold: DWORD;
    iSav: INT;
    jSav: INT;
    kSav: INT;
    bTileSelected: BOOL;
    iNumofTiles: INT;
    dwstarttime: DWORD;
    strTime: string;
    iXPos: INT;
    iYPos: INT;
END_VAR


VAR_INPUT
    tf: TILEFIELD_TYPE;
    xBestChoiceCouples: BOOL;
END_VAR

VAR
    SelectableTileField: ARRAY [..] OF ;
    tfTest: TILEFIELD_TYPE;
    i: INT;
    j: INT;
    k: INT;
    iSymbol: INT;
    iNumofEntries: INT;
    iTotalNum: INT;
    iIndex: INT;
    bDone: BOOL;
    iBestCouple: INT;
    iMaxSymbol: INT;
    iBestLevel: INT;
    iBestSymbol: INT;
    iLevelIndex: INT;
    iCouples: INT;
    iNumofCouples: INT;
END_VAR
REPEAT
	(* Initialize SelectableTileField *)
	FOR iSymbol:=1 TO 36 DO
		SelectableTileField[iSymbol].iNumOfEntries := 0; 							
		SelectableTileField[iSymbol].iNum := 0; 							
	END_FOR
	iTotalNum:=0;
	bDone:=FALSE;

	(* Collect all selectable tiles into the SelectableTileField *)
	FOR i:=1 TO 12 DO
		FOR j:=1 TO 8 DO			
			FOR k:=1 TO 5 DO				
				IF NOT tf.RegularFields[i,j,k].bInvisible THEN
					(* If the field is visible, save the symbol*)
					iSymbol:= tf.RegularFields[i,j,k].iSymbol;
					(* increment the counter for this symbol *) 
					SelectableTileField[iSymbol].iNum:=SelectableTileField[iSymbol].iNum+1;
					iTotalNum:=iTotalNum+1; (* Total number of tiles*)
					(* If the tile is selectable.*)
					IF SelectableTile(i:=i,j:=j,k:=k,tf:=tf) THEN
						(* Is there a tile on top? *)
						IF k=5 OR tf.RegularFields[i,j,k+1].bInvisible THEN
							(* Increment the selectable entries. Save the field for this entry.*)
							iNumofEntries:= SelectableTileField[iSymbol].iNumOfEntries := SelectableTileField[iSymbol].iNumOfEntries + 1; 							
							SelectableTileField[iSymbol].CoupleFields[iNumofEntries].i:=i;
							SelectableTileField[iSymbol].CoupleFields[iNumofEntries].j:=j;
							SelectableTileField[iSymbol].CoupleFields[iNumofEntries].k:=k;
						END_IF
					END_IF
				END_IF
			END_FOR
		END_FOR		
	END_FOR

	(* If 4 couples are accessible, remove all of them.*)
	FOR iSymbol:=1 TO 36 DO
		IF SelectableTileField[iSymbol].iNumOfEntries = 4 THEN
			FOR iNumofEntries:=1 TO 4 DO
			//	RemoveTile(iSymbol := iSymbol, iNumofEntries := iNumofEntries, tf := tf, SelectableTileField := SelectableTileField);
				i:= SelectableTileField[iSymbol].CoupleFields[iNumofEntries].i;
				j:= SelectableTileField[iSymbol].CoupleFields[iNumofEntries].j;
				k:= SelectableTileField[iSymbol].CoupleFields[iNumofEntries].k;
				tf.RegularFields[i,j,k].bInvisible:=TRUE;
			END_FOR
			(* Decrement the total number of tiles.*)
			iTotalNum:=iTotalNum-4;
			bDone:=TRUE;
		END_IF
	END_FOR
  
	(* If 2 of one symbol are already deleted, and the other 2 are accessible, then remove them.*)
	FOR iSymbol:=1 TO 36 DO
		IF SelectableTileField[iSymbol].iNumOfEntries = 2 AND SelectableTileField[iSymbol].iNum = 2  THEN
			FOR iNumofEntries:=1 TO 2 DO
				//RemoveTile(iSymbol := iSymbol, iNumofEntries := iNumofEntries, tf := tf, SelectableTileField := SelectableTileField);
				i:= SelectableTileField[iSymbol].CoupleFields[iNumofEntries].i;
				j:= SelectableTileField[iSymbol].CoupleFields[iNumofEntries].j;
				k:= SelectableTileField[iSymbol].CoupleFields[iNumofEntries].k;
				tf.RegularFields[i,j,k].bInvisible:=TRUE;
			END_FOR
			(* Decrement the total number of tiles.*)
			iTotalNum:=iTotalNum-2;
			bDone:=TRUE;
		END_IF
	END_FOR

	(* look for best choice *)
	IF NOT bDone THEN
		iBestCouple:=0;		
		iMaxSymbol:=36; (* all symbols *)
		iBestLevel:=0;
		iBestSymbol:=0;
		
		FOR iSymbol:=1 TO iMaxSymbol DO
			IF SelectableTileField[iSymbol].iNumOfEntries = 2 OR SelectableTileField[iSymbol].iNumOfEntries = 3  THEN
				tfTest:= tf;
				iLevelIndex:=0;
				FOR iNumofEntries:=1 TO 2 DO
					(* Remove two tiles in the test field.*)
					i:= SelectableTileField[iSymbol].CoupleFields[iNumofEntries].i;
					j:= SelectableTileField[iSymbol].CoupleFields[iNumofEntries].j;
					k:= SelectableTileField[iSymbol].CoupleFields[iNumofEntries].k;
					iLevelIndex:=iLevelindex+k;
					tfTest.RegularFields[i,j,k].bInvisible:=TRUE;
				END_FOR
				iCouples := GetNumOfCouples(tfTest); 
				
				(* Two possibilities to search for the best choice. *)
				IF xBestChoiceCouples THEN
					IF iCouples > iBestCouple OR (iBestCouple = iCouples AND iBestLevel < iLevelIndex) THEN
						iBestCouple := iCouples;
						iBestLevel:=iLevelIndex;
						iBestSymbol:=iSymbol;
					END_IF
				ELSE
					IF iLevelIndex > iBestLevel OR (iLevelIndex = iBestLevel AND iBestCouple < iCouples) THEN
						iBestCouple := iCouples;
						iBestLevel:=iLevelIndex;
						iBestSymbol:=iSymbol;
					END_IF
				END_IF
				
				
			END_IF
			(* Three selectable tiles *)
			IF SelectableTileField[iSymbol].iNumOfEntries = 3  THEN
				iMaxSymbol := iMaxSymbol+2;
				(* save after the end of original symbols, the two combinations.*)
				SelectableTileField[iMaxSymbol + 1].iNumOfEntries:=2;
				SelectableTileField[iMaxSymbol + 1].CoupleFields[1]:=SelectableTileField[iSymbol].CoupleFields[1];
				SelectableTileField[iMaxSymbol + 1].CoupleFields[2]:=SelectableTileField[iSymbol].CoupleFields[3];
				SelectableTileField[iMaxSymbol + 2].iNumOfEntries:=2;
				SelectableTileField[iMaxSymbol + 2].CoupleFields[1]:=SelectableTileField[iSymbol].CoupleFields[2];
				SelectableTileField[iMaxSymbol + 2].CoupleFields[2]:=SelectableTileField[iSymbol].CoupleFields[3];
			END_IF
		END_FOR
		
		(* remove tile on the original field. *)
		IF NOT (iBestSymbol=0) THEN
			FOR iNumofEntries:=1 TO 2 DO
				//RemoveTile(iSymbol := iBestSymbol, iNumofEntries := iNumofEntries, tf := tf, SelectableTileField := SelectableTileField);
				i:= SelectableTileField[iBestSymbol].CoupleFields[iNumofEntries].i;
				j:= SelectableTileField[iBestSymbol].CoupleFields[iNumofEntries].j;
				k:= SelectableTileField[iBestSymbol].CoupleFields[iNumofEntries].k;
				tf.RegularFields[i,j,k].bInvisible:=TRUE;
			END_FOR
			iTotalNum:=iTotalNum-2;
		end_if	 		
	END_IF

	iNumofCouples:=GetNumOfCouples(tf); (* Get remaining number of couples *)
UNTIL iNumofCouples = 0 END_REPEAT; 
CoDeSysPlays:=iTotalNum;

-------------------------------------------------------------------------------
PlayMahJongg
-------------------------------------------------------------------------------


PROGRAM PlayMahJongg

VAR
    i: INT;
    j: INT;
    k: INT;
END_VAR

VAR_INOUT
    tf: TILEFIELD_TYPE;

END_VAR
(* Play the game and remove selected couples of the field. *)
FOR i:=1 TO 12 DO
	FOR j:=1 TO 8 DO
		FOR k:=1 TO 5 DO
			IF tf.RegularFields[i,j,k].bIsSelected THEN
				(* If selected tile is invisible, then unselect it.*)
				IF tf.RegularFields[i,j,k].bInvisible THEN
					tf.RegularFields[i,j,k].bIsSelected:=FALSE;
					CONTINUE;
				END_IF
				(* If the selected tile is the one, which was selected before.*)
				IF i=iSav AND j=jSav AND k=kSav THEN
					CONTINUE;
				END_IF
				(* If the selected tile is allowed to be selected.*)
				IF SelectableTile(i:=i,j:=j,k:=k,tf:=tf) THEN
					(* If 2 same symbols are selected. *)
					IF bTileSelected AND tf.RegularFields[iSav,jSav,kSav].iSymbol=tf.RegularFields[i,j,k].iSymbol THEN
						(* Set both as invisible.*)
						tf.RegularFields[i,j,k].bInvisible:=TRUE;
						tf.RegularFields[iSav,jSav,kSav].bInvisible:=TRUE;
						(* Decrement the number of available tiles. *)
						iNumofTiles:=iNumofTiles-2;
						bTileSelected:=FALSE; (* currently nothing is selected *)
					ELSE
						(* New Selection *)
						bTileSelected := TRUE;
						iSav:=i; (* Save the selection *)
						jSav:=j;
						kSav:=k;
					END_IF
				END_IF
			END_IF (* IF tile is selected*)
		END_FOR
	END_FOR
END_FOR
-------------------------------------------------------------------------------
PLC_PRG
-------------------------------------------------------------------------------


PROGRAM PLC_PRG

VAR
    tf: TILEFIELD_TYPE;
    bInit: BOOL;
    bFirstStart: BOOL;
    bPlay: BOOL;
    bCheckForSolution: BOOL;
    dwTime: DWORD;
    bFinish: BOOL;
    strFinish: string;
    iNumofCouples: INT;
    iCoDeSysPlays: INT;
    iCoDeSysPlays1: INT;
    iCoDeSysPlays2: INT;
    iCoDeSysBest: INT;
    sCoDeSysBest: string;
END_VAR
IF bFirstStart THEN
	bInit:=TRUE;
	bFirstStart:=FALSE;
END_IF

IF bInit THEN
	iCoDeSysBest:=0;
	sCoDeSysBest:='';
	bCheckForSolution:=FALSE;
	InitTileField(tf);
	bInit:=FALSE;	
	bPlay:=TRUE;
	iSav:=1;
	jSav:=1;
	kSav:=2;
	bTileSelected:=FALSE;
	iNumofTiles:=144;
	dwTime:=0;
	bFinish:=FALSE;
END_IF

IF bPlay THEN
	IF dwTime=0 THEN
		dwstarttime:=SysTimeGetMs();
		dwTime:=dwstarttime;
	ELSE
		dwTime:=SysTimeGetMs()-dwstarttime;
		SetTimeString(dwTime:=dwTime); (* For showing in the visualization.*)
	END_IF
	(* Check the selected tiles and let seleted couples disappear.*)
	PlayMahJongg(tf:=tf);
	(* Set the yellow border for the current selection. *)
	SetCursor(tf:=tf);
	(* Count the current number of possible couples.*)
	iNumofCouples:=GetNumOfCouples(tf:=tf);	
	(* If no more tiles are remaining, the user has won the game.*)
	IF iNumofTiles = 0 THEN
		bFinish:=TRUE;
		bPlay:=FALSE;
		strFinish:='Congratulation';	
	(* If some tiles are remaining, but no more couples available the game is over. *)	
	ELSIF iNumofCouples = 0 THEN
		bFinish:=TRUE;
		bPlay:=FALSE;
		strFinish:='Sorry, you lost. Try again!';
	END_IF
END_IF

(* Let CoDeSys play*)
IF bPlay AND bCheckForSolution THEN
	iCoDeSysPlays := CoDeSysPlays(tf, TRUE);
	iCoDeSysPlays1 := CoDeSysPlays_1(tf);
	iCoDeSysPlays2 := CoDeSysPlays(tf, FALSE);
	iCoDeSysBest:=MIN(iCoDeSysPlays,MIN(iCoDeSysPlays1,iCoDeSysPlays2));
	sCoDeSysBest:=Concat(Concat('I can finish with ' , INT_TO_STRING(iCoDeSysBest)), ' tiles left.');
	bCheckForSolution := FALSE;
END_IF

VAR_INOUT
    tf: TILEFIELD_TYPE;

END_VAR

VAR
    SymbolField: ARRAY [..] OF ;
    iIndex: INT;
    i: INT;
    j: INT;
    k: INT;
    iSymbol: INT;
    udiNumofDifferentSymbols: UDINT;
    l: INT;
    m: INT;
END_VAR
(* Init for Random Function in GetSymbol Function *)
hold := SysTimeGetMs();

(* tiles are linked to a symbol at random *)
FOR i:=1 TO 12 DO
	FOR j:=1 TO 8 DO
		FOR k:=1 TO 5 DO
			tf.RegularFields[i,j,k].bInvisible:=TRUE;
			tf.RegularFields[i,j,k].bIsSelected:=FALSE;
			(* Check for a valid tile field, because not all rows are complete.*)
			IF IsValidtileField(i:=i,j:=j,k:=k) THEN
				(* Get a symbol for each tile. *)
				tf.RegularFields[i,j,k].iSymbol:=GetSymbol(SymbolField,udiNumofDifferentSymbols);
				tf.RegularFields[i,j,k].bInvisible:=FALSE;
			END_IF
		END_FOR
	END_FOR		
END_FOR

VAR_INPUT
    i: INT;
    j: INT;
    k: INT;
END_VAR

VAR_INOUT
    tf: TILEFIELD_TYPE;

END_VAR
                                                                                                                                                                                                                                                                                
(* Calculate a random value *)
Random := SHR ((hold := hold * 214013 + 2531011), 16) AND 16#7fff;

VAR_INPUT
    tf: TILEFIELD_TYPE;
END_VAR

VAR
    SelectableTileField: ARRAY [..] OF ;
    tfTest: TILEFIELD_TYPE;
    i: INT;
    j: INT;
    k: INT;
    iSymbol: INT;
    iNumofEntries: INT;
    iTotalNum: INT;
    iIndex: INT;
    bDone: BOOL;
    iBestCouple: INT;
    iMaxSymbol: INT;
    iBestLevel: INT;
    iBestSymbol: INT;
    iLevelIndex: INT;
    iCouples: INT;
    iNumofCouples: INT;
END_VAR
REPEAT
	(* Initialize SelectableTileField *)
	FOR iSymbol:=1 TO 36 DO
		SelectableTileField[iSymbol].iNumOfEntries := 0; 							
		SelectableTileField[iSymbol].iNum := 0; 							
	END_FOR
	iTotalNum:=0;
	bDone:=FALSE;

	(* Collect all selectable tiles into the SelectableTileField *)
	FOR i:=1 TO 12 DO
		FOR j:=1 TO 8 DO			
			FOR k:=1 TO 5 DO				
				IF NOT tf.RegularFields[i,j,k].bInvisible THEN
					(* If the field is visible, save the symbol*)
					iSymbol:= tf.RegularFields[i,j,k].iSymbol;
					(* increment the counter for this symbol *) 
					SelectableTileField[iSymbol].iNum:=SelectableTileField[iSymbol].iNum+1;
					iTotalNum:=iTotalNum+1;(* Total number of tiles*)
					IF SelectableTile(i:=i,j:=j,k:=k,tf:=tf) THEN
						(* Is there a tile on top? *)
						IF k=5 OR tf.RegularFields[i,j,k+1].bInvisible THEN
							(* Increment the selectable entries. Save the field for this entry.*)
							iNumofEntries:= SelectableTileField[iSymbol].iNumOfEntries := SelectableTileField[iSymbol].iNumOfEntries + 1; 							
							SelectableTileField[iSymbol].CoupleFields[iNumofEntries].i:=i;
							SelectableTileField[iSymbol].CoupleFields[iNumofEntries].j:=j;
							SelectableTileField[iSymbol].CoupleFields[iNumofEntries].k:=k;
						END_IF
					END_IF
				END_IF
			END_FOR
		END_FOR		
	END_FOR

	(* If at least 2 accessible symbols are available, remove two *)
	FOR iSymbol:=1 TO 36 DO
		IF SelectableTileField[iSymbol].iNumOfEntries >= 2 THEN
			FOR iNumofEntries:=1 TO 2 DO
				i:= SelectableTileField[iSymbol].CoupleFields[iNumofEntries].i;
				j:= SelectableTileField[iSymbol].CoupleFields[iNumofEntries].j;
				k:= SelectableTileField[iSymbol].CoupleFields[iNumofEntries].k;
				tf.RegularFields[i,j,k].bInvisible:=TRUE;
			END_FOR
			iTotalNum:=iTotalNum-2;
			bDone:=TRUE;			
		END_IF
	END_FOR

	iNumofCouples:=GetNumOfCouples(tf);
UNTIL iNumofCouples = 0 END_REPEAT; 
CoDeSysPlays_1:=iTotalNum;

-------------------------------------------------------------------------------
SetTimeString
-------------------------------------------------------------------------------

                   Get the hours, minutes and seconds from the systime and save it as string for the visualization. 


PROGRAM SetTimeString

VAR_INPUT
    dwTime: DWORD;
END_VAR

VAR
    dwSec: DWORD;
    dwMin: DWORD;
    dwStd: DWORD;
END_VAR
                                                                                                                                                                                            

VAR_INOUT
    tf: TILEFIELD_TYPE;

END_VAR

VAR
    SymbolField: ARRAY [..] OF ;
    i: INT;
    j: INT;
    k: INT;
END_VAR
(* Count the number of currently available couples.*)

(* Collect all selectable tiles in a symbol table *)
FOR i:=1 TO 12 DO (* columns *)
	FOR j:=1 TO 8 DO (* rows *)			
		FOR k:=1 TO 5 DO (* level *)				
			IF NOT tf.RegularFields[i,j,k].bInvisible THEN (* If tile is visible*)
				IF SelectableTile(i:=i,j:=j,k:=k,tf:=tf) THEN (* Is the tile selectable? *)
					(* Is the tile hidden by another one on top? *)
					IF k=5 OR tf.RegularFields[i,j,k+1].bInvisible THEN
						(* Count up the selectable symbols.*)
						SymbolField[tf.RegularFields[i,j,k].iSymbol]:=SymbolField[tf.RegularFields[i,j,k].iSymbol]+1;
					END_IF
				END_IF
			END_IF
		END_FOR
	END_FOR		
END_FOR

(* count number of symbols > 1*)
FOR i:=1 TO 36 DO (* There are 36 symbols. *)
	IF SymbolField[i] > 1 THEN (* If one symbols is more than once selectable, then count up the number of couples.*)
		GetNumOfCouples := GetNumOfCouples+1;
	END_IF
END_FOR
 
	

VAR
    iSymbol: INT;
    l: INT;
    m: INT;
END_VAR

VAR_INOUT
    SymbolField: ARRAY [..] OF ;
    udiNumofDifferentSymbols: UDINT;

END_VAR
(* Generate a random symbol value. *)
iSymbol:= UDINT_TO_INT((Random() MOD udiNumofDifferentSymbols))+1;
(**)
l:=1;
m:=1;

(* Check the remaining symbols. *)
WHILE  l<iSymbol OR SymbolField[m]=0 DO 
	(* If the field is 0, then all four symbols are already used.*)
	IF SymbolField[m]=0 THEN
		m:=m+1;
	ELSE
		l:=l+1;
		m:=m+1;
	END_IF
END_WHILE

GetSymbol:=m;
SymbolField[m]:=SymbolField[m]-1;
(* If one symbol is four times selected, reduce the number of the remeining symbols.*)
IF SymbolField[m]=0 THEN
	udiNumofDifferentSymbols:=udiNumofDifferentSymbols-1;
END_IF
-------------------------------------------------------------------------------
SetCursor
-------------------------------------------------------------------------------


PROGRAM SetCursor

VAR_INOUT
    tf: TILEFIELD_TYPE;

END_VAR

VAR
    iOffset: INT;
END_VAR
(* Move the selected border to the currently selected tile.*)
IF bTileSelected THEN
	IF kSav=5 THEN
		CASE jSav OF
			1: 	iXPos:= 10;
				iYPos:=215;
			2: 	iXPos:=299;
				iYPos:=200;
			3:	iXPos:=622;
				iYPos:=214;
			4:	iXPos:=669;
				iYPos:=214;
		END_CASE
	ELSE
		iOffset:=(kSav-1)*5;
		iXPos:=57 + (iSav-1)*47-iOffset;
		iYPos:=19 + (jSav-1)*56-iOffset;
	END_IF
END_IF

VAR_INPUT
    i: INT;
    j: INT;
    k: INT;
END_VAR