james3mg Posted October 9, 2008 Share Posted October 9, 2008 (edited) Hey all-Just a little challenge to myself- I wanted to see if I could make a Mahjong game. Turns out, it was pretty easy!Understand, this is based on the version of Mahjong that comes in Vista, which, if the description on wikipedia of Mahjong is accurate, is nothing like the actual game. This version is even further removed- for now, I've only got the numbered tiles (no dragons, seasons or flowers), and I used colors instead of the actual suites (bamboo, etc)I kind of consider this the working framework on which someone could build a good game- it would be easy to add in the missing tiles, replace the labels with picture controls, etc. I do intend to add the ability for tiles to be staggered vertically in the future, rather than a pure grid arrangement.One thing I had a problem with using labels as the tiles is that I had to disable the tiles that were not playable, or the tiles above them were hard to select. But if I disabled them, the text got grayed out. The only way I could prevent that was using the "simple" style, which shrunk the tiles to just the size of the text and lost the frames and other styles I'd applied to make it look better. If I can figure out a better control to use, I'll update the script here. Oh, one last warning; I'm still using AutoIt 3.2.8.2, so this is all pre-3.2.10 syntax.Fixed- this code is now playable in v3.2.12.1, at least. (the only difference were some of the #include files...nice) I have found a bug since posting this that I can't run down- if you choose to play another game after winning or losing, the script seems to mark some pieces as "free" (playable) that shouldn't be. If I can get that fixed, I'll update here.FixedHere's the code:expandcollapse popup#include <SQLite.dll.au3> #include <SQLite.au3> #include <WindowsConstants.au3> #include <GUIConstantsEx.au3> _SQLite_Startup() _SQLite_Open() Global $aResult, $iRows, $iCols Global $xSize=35, $ySize=60 Global $Suites[3]=[0xFF0000,0x00BB00,0x6666FF] $GameGUI=GUICreate("AutoIt Mahjong by james3mg",9*$xSize,9*$ySize+20,-1,-1,$GUI_SS_DEFAULT_GUI + $WS_SIZEBOX + $WS_MAXIMIZEBOX) GUISetBkColor(0x006600) $StatusBar=GUICtrlCreateLabel("",0,9*$ySize,9*$xSize,20) GUICtrlSetBkColor(-1,0xBBBBBB) GUICtrlSetResizing(-1,576) GUISetState() While 1 If Play()=7 Then Exit WEnd Func Play() _SQLite_Exec(-1,"DROP TABLE IF EXISTS `pieces`") _SQLite_Exec(-1,"CREATE TABLE `pieces` (`value`,`suite`,`x`,`y`,`z`,`GID` UNIQUE,`vis`,`free`)") Global $NumCombos=0 ;0=point,1=fortress,2=command,3=flower,4=I [heart] U Global $Boards[5][108][2] = _;[board layount #][piece 1, piece 2, ... piece 108][x,y] [[[4,0],[2,1],[3,1],[4,1],[5,1],[6,1],[1,2],[2,2],[3,2],[4,2],[5,2],[6,2],[7,2],[0,3],[1,3],[2,3],[3,3],[4,3],[5,3],[6,3],[7,3],[8,3],[0,4],[1,4],[2,4],[3,4],[4,4],[5,4],[6,4],[7,4],[8,4],[0,5],[1,5],[2,5],[3,5],[4,5],[5,5],[6,5],[7,5],[8,5],[1,6],[2,6],[3,6],[4,6],[5,6],[6,6],[7,6],[2,7],[3,7],[4,7],[5,7],[6,7],[4,8], _ [2,2],[3,2],[4,2],[5,2],[6,2],[1,3],[2,3],[3,3],[4,3],[5,3],[6,3],[7,3],[1,4],[2,4],[3,4],[4,4],[5,4],[6,4],[7,4],[1,5],[2,5],[3,5],[4,5],[5,5],[6,5],[7,5],[2,6],[3,6],[4,6],[5,6],[6,6], _ [2,3],[3,3],[4,3],[5,3],[6,3],[2,4],[3,4],[4,4],[5,4],[6,4],[2,5],[3,5],[4,5],[5,5],[6,5], _ [3,3],[4,3],[5,3],[3,4],[4,4],[5,4],[3,5],[4,5],[6,5]], _ [[0,0],[1,0],[2,0],[3,0],[4,0],[5,0],[6,0],[7,0],[8,0],[8,1],[8,2],[8,3],[8,4],[8,5],[8,6],[8,7],[8,8],[7,8],[6,8],[5,8],[4,8],[3,8],[2,8],[1,8],[0,8],[0,7],[0,6],[0,5],[0,4],[0,3],[0,2],[0,1],[3,3],[4,3],[5,3],[5,4],[5,5],[4,5],[3,5],[3,4], _ [0,2],[0,1],[0,0],[1,0],[2,0],[6,0],[7,0],[8,0],[8,1],[8,2],[8,6],[8,7],[8,8],[7,8],[6,8],[2,8],[1,8],[0,8],[0,7],[0,6],[3,5],[4,5],[5,5],[5,4],[5,3],[4,3],[3,3],[3,4],[0,4],[4,0],[8,4],[4,8], _ [0,1],[0,0],[1,0],[7,0],[8,0],[8,1],[8,7],[8,8],[7,8],[1,8],[0,8],[0,7],[3,5],[4,5],[5,5],[5,4],[5,3],[4,3],[3,3],[3,4], _ [3,3],[4,3],[5,3],[5,4],[5,5],[4,5],[3,5],[3,4],[0,0],[8,0],[8,8],[0,8], _ [3,3],[5,3],[5,5],[3,5]], _ [[0,0],[1,0],[2,0],[3,0],[4,0],[5,0],[6,0],[7,0],[8,0],[2,1],[3,1],[4,1],[5,1],[6,1],[1,2],[2,2],[3,2],[4,2],[5,2],[6,2],[7,2],[1,3],[2,3],[3,3],[4,3],[5,3],[6,3],[7,3],[1,4],[2,4],[3,4],[4,4],[5,4],[6,4],[7,4],[8,4],[1,5],[2,5],[3,5],[4,5],[5,5],[6,5],[7,5],[1,6],[2,6],[3,6],[4,6],[5,6],[6,6],[7,6],[2,7],[3,7],[4,7],[5,7],[6,7],[0,8],[1,8],[2,8],[3,8],[4,8],[5,8],[6,8],[7,8],[8,8], _ [3,2],[4,2],[5,2],[2,3],[3,3],[4,3],[5,3],[6,3],[2,4],[3,4],[4,4],[5,4],[6,4],[7,4],[8,4],[2,5],[3,5],[4,5],[5,5],[6,5],[3,6],[4,6],[5,6], _ [3,3],[4,3],[5,3],[3,4],[4,4],[5,4],[6,4],[7,4],[8,4],[3,5],[4,5],[5,5], _ [4,3],[5,3],[4,4],[5,4],[6,4],[7,4],[8,4],[4,5],[5,5]], _ [[5,2],[6,1],[7,0],[4,1],[3,0],[4,3],[3,4],[6,3],[7,4],[5,3],[5,4],[6,2],[7,2],[5,1],[5,0],[4,2],[3,2],[5,5],[5,6],[4,6],[4,7],[4,8],[0,8],[1,8],[2,8],[3,8],[5,8],[6,8],[7,8],[8,8],[6,5], _ [5,4],[4,3],[3,2],[4,1],[5,0],[6,1],[7,2],[6,3],[4,2],[5,1],[6,2],[5,2],[5,3],[5,5],[5,6],[6,5],[4,6],[4,7],[0,8],[1,8],[2,8],[3,8],[4,8],[5,8],[6,8],[7,8],[8,8], _ [5,2],[4,1],[5,1],[6,1],[4,2],[6,2],[4,3],[5,3],[6,3], _ [5,2],[3,0],[5,0],[7,0],[4,1],[5,1],[6,1],[3,2],[4,2],[5,2],[6,2],[7,2],[4,3],[5,3],[6,3],[3,4],[5,4],[7,4],[5,5],[6,5],[5,6],[4,6],[4,7],[0,8],[1,8],[2,8],[3,8],[4,8],[5,8],[6,8],[7,8],[8,8], _ [4,1],[5,1],[6,1],[4,2],[5,2],[6,2],[5,3],[4,3],[6,3]], _ [[0,0],[0,1],[0,2],[0,3],[8,5],[8,6],[8,7],[7,8],[6,7],[6,6],[6,5],[4,2],[3,1],[2,2],[2,3],[3,4],[4,5],[5,4],[6,3],[6,2],[5,1], _ [0,0],[0,1],[0,2],[0,3],[3,1],[5,1],[4,2],[2,2],[2,3],[3,4],[4,5],[5,4],[6,3],[6,2],[6,5],[6,6],[6,7],[7,8],[8,7],[8,6],[8,5], _ [0,0],[0,1],[0,2],[0,3],[4,2],[3,1],[2,2],[2,3],[3,4],[4,5],[5,4],[6,3],[6,2],[5,1],[6,5],[6,6],[6,7],[7,8],[8,7],[8,6],[8,5], _ [0,0],[0,1],[0,2],[0,3],[4,2],[3,1],[2,2],[2,3],[3,4],[4,5],[5,4],[6,3],[6,2],[5,1],[6,5],[6,6],[6,7],[7,8],[8,7],[8,6],[8,5], _ [0,0],[0,1],[0,2],[0,3],[4,2],[3,1],[2,2],[2,3],[3,4],[4,5],[5,4],[6,3],[6,2],[5,1],[6,5],[6,6],[6,7],[7,8],[8,7],[8,6],[8,5],[3,1],[5,1],[4,5]]] ;this loop will assign the pieces' positions Local $SelBoard=InputBox("Select board","Please enter the number of the board you wish to play: (0-"&UBound($Boards)-1&")",0) If @error OR $SelBoard >= UBound($Boards) Then Exit For $i=0 To 3 For $s=0 To 2 For $n=1 To 9 Local $pos=Random(0,UBound($Boards,2)-1,1) _SQLite_GetTable2d(-1,"SELECT * FROM `pieces` WHERE `x`='"&$Boards[$SelBoard][$pos][0]*$xSize&"' AND `y`='"&$Boards[$SelBoard][$pos][1]*$ySize&"'",$aResult,$iRows,$iCols) _SQLite_Exec(-1,"INSERT INTO `pieces` (`value`,`suite`,`x`,`y`,`z`) VALUES ('"&$n&"','"&$s&"','"&$Boards[$SelBoard][$pos][0]*$xSize&"','"&$Boards[$SelBoard][$pos][1]*$ySize&"','"&$iRows&"')") For $a=$pos To UBound($Boards,2)-2 $Boards[$SelBoard][$a][0]=$Boards[$SelBoard][$a+1][0] $Boards[$SelBoard][$a][1]=$Boards[$SelBoard][$a+1][1] Next If UBound($Boards,2)=1 Then ExitLoop ReDim $Boards[UBound($Boards,1)][UBound($Boards,2)-1][2] Next Next Next ;this loop will create the pieces in the positions determined above and store them in the database _SQLite_GetTable2d(-1,"SELECT * FROM `pieces` ORDER BY `z`,`y`,`x`",$aResult,$iRows,$iCols) For $i=1 To $iRows Local $GID=GUICtrlCreateLabel($aResult[$i][0],$aResult[$i][2]+$aResult[$i][4]*3,$aResult[$i][3]+$aResult[$i][4]*3,$xSize,$ySize,0x0B) GUICtrlSetFont(-1,30,400,2) GUICtrlSetBkColor($GID,$Suites[$aResult[$i][1]]) GUICtrlSetState($GID,$GUI_DISABLE) _SQLite_Exec(-1,"UPDATE `pieces` SET `GID`='"&$GID&"' WHERE `x`='"&$aResult[$i][2]&"' AND `y`='"&$aResult[$i][3]&"' AND `z`='"&$aResult[$i][4]&"'") ;Sleep(15) Next SetPieceState() ;now we start the actual "running" section While 1 Sleep(30) $msg=GUIGetMsg() If $msg=-3 Then Exit If $msg>0 Then GUICtrlSetBkColor($msg,0xFFFFFF) Local $FirstPiece=$msg,$FirstPieceResult,$SecondPieceResult While 1 $msg=GUIGetMsg() If $msg=-3 Then Exit If $msg>0 Then _SQLite_GetTable2d(-1,"SELECT `GID`,`value`,`suite` FROM `pieces` WHERE `GID`='"&$FirstPiece&"'",$FirstPieceResult,$iRows,$iCols) _SQLite_GetTable2d(-1,"SELECT `GID`,`value`,`suite` FROM `pieces` WHERE `GID`='"&$msg&"'",$SecondPieceResult,$iRows,$iCols) If $SecondPieceResult[1][1] == $FirstPieceResult[1][1] AND $SecondPieceResult[1][2] == $FirstPieceResult[1][2] AND $msg <> $FirstPiece Then GUICtrlDelete($msg) GUICtrlDelete($FirstPiece) _SQLite_Exec(-1,"DELETE FROM `pieces` WHERE `GID`='"&$FirstPiece&"'") _SQLite_Exec(-1,"DELETE FROM `pieces` WHERE `GID`='"&$msg&"'") Local $ReturnVal=SetPieceState() If $ReturnVal <> 0 Then _SQLite_GetTable2d(-1,"SELECT `GID` FROM `pieces`",$aResult,$iRows,$iCols) For $i=1 To $iRows GUICtrlDelete($aResult[$i][0]) Next Local $newSize=WinGetClientSize($GameGUI) $xSize=Floor($newSize[0]/9) $ySize=Floor(($newSize[1]-20)/9) Return $ReturnVal EndIf Else GUICtrlSetBkColor($FirstPiece,$Suites[$FirstPieceResult[1][2]]) EndIf ExitLoop EndIf WEnd EndIf WEnd EndFunc Func SetPieceState() ;first, find all the visible (topmost) pieces, and set `vis` accordingly _SQLite_Exec(-1,"UPDATE `pieces` SET `vis`='False'") _SQLite_Exec(-1,"UPDATE `pieces` SET `free`='False'") Local $PiecesArray,$vis,$free _SQLite_GetTable2d(-1,"SELECT * FROM `pieces`",$PiecesArray,$iRows,$iCols) For $i=1 To $iRows _SQLite_GetTable2d(-1,"SELECT * FROM `pieces` WHERE `x`='"&$PiecesArray[$i][2]&"' AND `y`='"&$PiecesArray[$i][3]&"' AND `z`='"&$PiecesArray[$i][4]+1&"'",$aResult,$vis,$iCols) _SQLite_Exec(-1,"UPDATE `pieces` SET `vis`='"&NOT $vis&"' WHERE `GID`='"&$PiecesArray[$i][5]&"'") Next ;now `vis` is set...time to set `free` on all the pieces which are playable _SQLite_GetTable2d(-1,"SELECT `GID`,`x`,`y`,`z` from `pieces` where `vis`='True'",$PiecesArray,$iRows,$iCols) For $i=1 To $iRows _SQLite_GetTable2d(-1,"SELECT `GID` FROM `pieces` WHERE `x`='"&$PiecesArray[$i][1]-$xSize&"' AND `y`='"&$PiecesArray[$i][2]&"' AND `z`='"&$PiecesArray[$i][3]&"' UNION SELECT `GID` FROM `pieces` WHERE `x`='"&$PiecesArray[$i][1]+$xSize&"' AND `y`='"&$PiecesArray[$i][2]&"' AND `z`='"&$PiecesArray[$i][3]&"'",$aResult,$free,$iCols) If $free < 2 Then _SQLite_Exec(-1,"UPDATE `pieces` SET `free`='True' WHERE `GID`='"&$PiecesArray[$i][0]&"'") If BitAND(GUICtrlGetState($PiecesArray[$i][0]),$GUI_DISABLE) Then;only doing this if it's necessary reduces flicker between moves. GUICtrlSetState($PiecesArray[$i][0],$GUI_ENABLE) GUICtrlSetCursor($PiecesArray[$i][0],0) EndIf EndIf Next ;now `free` is set...time to count possible moves $NumCombos=0 Local $FreePieces,$iFreePieces _SQLite_Exec(-1,"DROP TABLE IF EXISTS `combos`") _SQLite_Exec(-1,"CREATE TABLE `combos` (`GID`)") _SQLite_GetTable2d(-1,"SELECT `GID`,`value`,`suite` FROM `pieces` WHERE `free`='True'",$FreePieces,$iFreePieces,$iCols) For $i=1 To $iFreePieces _SQLite_GetTable2d(-1,"SELECT `GID` FROM `pieces` WHERE `value`='"&$FreePieces[$i][1]&"' AND `suite`='"&$FreePieces[$i][2]&"' AND `GID` != '"&$FreePieces[$i][0]&"' AND `free`='True' EXCEPT SELECT `GID` FROM `combos`",$aResult,$iRows,$iCols) $NumCombos+=$iRows _SQLite_Exec(-1,"INSERT into `combos` values('"&$FreePieces[$i][0]&"')") For $n=1 To $iRows _SQLite_Exec(-1,"INSERT into `combos` values('"&$aResult[$n][0]&"')") Next Next TraySetToolTip($NumCombos & " moves available") GUICtrlSetData($StatusBar,$NumCombos & " moves available") _SQLite_GetTable2d(-1,"SELECT `GID` FROM `pieces`",$aResult,$iRows,$iCols) If $iRows=0 Then Return MsgBox(36,"Winner!","You won!"&@CRLF&@CRLF&"Play again?") If $NumCombos=0 Then Return MsgBox(36,"Game over","You lost...there are no more valid moves!"&@CRLF&@CRLF&"Play again?") Return 0 EndFunc Edited October 10, 2008 by james3mg "There are 10 types of people in this world - those who can read binary, and those who can't.""We've heard that a million monkeys at a million keyboards could produce the complete works of Shakespeare; now, thanks to the Internet, we know that is not true." ~Robert Wilensky0101101 1001010 1100001 1101101 1100101 1110011 0110011 1001101 10001110000101 0000111 0001000 0001110 0001101 0010010 1010110 0100001 1101110 Link to comment Share on other sites More sharing options...
TehWhale Posted October 9, 2008 Share Posted October 9, 2008 Can you create a compiled version, or a .zip with a compiled version? Just makes it all easier Link to comment Share on other sites More sharing options...
james3mg Posted October 10, 2008 Author Share Posted October 10, 2008 Can you create a compiled version, or a .zip with a compiled version? Just makes it all easier No space left to upload "There are 10 types of people in this world - those who can read binary, and those who can't.""We've heard that a million monkeys at a million keyboards could produce the complete works of Shakespeare; now, thanks to the Internet, we know that is not true." ~Robert Wilensky0101101 1001010 1100001 1101101 1100101 1110011 0110011 1001101 10001110000101 0000111 0001000 0001110 0001101 0010010 1010110 0100001 1101110 Link to comment Share on other sites More sharing options...
AlmarM Posted October 10, 2008 Share Posted October 10, 2008 (edited) Wow, this is pretty nice AlmarMEDIT:The"0101101 1001010 1100001 1101101 1100101 1110011 0110011 1001101 10001110000101 0000111 0001000 0001110 0001101 0010010 1010110 0100001 1101110"Whats the name of that 'language'? Its called 'Binary' ? Edited October 10, 2008 by AlmarM Minesweeper A minesweeper game created in autoit, source available. _Mouse_UDF An UDF for registering functions to mouse events, made in pure autoit. 2D Hitbox Editor A 2D hitbox editor for quick creation of 2D sphere and rectangle hitboxes. Link to comment Share on other sites More sharing options...
Zedna Posted October 10, 2008 Share Posted October 10, 2008 Short code for such good game!! Resources UDF  ResourcesEx UDF  AutoIt Forum Search Link to comment Share on other sites More sharing options...
james3mg Posted October 10, 2008 Author Share Posted October 10, 2008 (edited) Thanks It's been updated now too, so it runs the latest syntax. I've discovered one bug I noted in the OP, and I'll see if I can't track that down next. Edited October 10, 2008 by james3mg "There are 10 types of people in this world - those who can read binary, and those who can't.""We've heard that a million monkeys at a million keyboards could produce the complete works of Shakespeare; now, thanks to the Internet, we know that is not true." ~Robert Wilensky0101101 1001010 1100001 1101101 1100101 1110011 0110011 1001101 10001110000101 0000111 0001000 0001110 0001101 0010010 1010110 0100001 1101110 Link to comment Share on other sites More sharing options...
TehWhale Posted October 10, 2008 Share Posted October 10, 2008 Wow, this is pretty nice AlmarMEDIT:The"0101101 1001010 1100001 1101101 1100101 1110011 0110011 1001101 10001110000101 0000111 0001000 0001110 0001101 0010010 1010110 0100001 1101110"Whats the name of that 'language'? Its called 'Binary' ?Yep. Binary is the language that computers run off, and consist of only 1s and 0s.Sweet thanks for the update, for the newest version Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now