📄 kmahjongg.cpp
字号:
case 4: hilightTile( TimerPos1, false, false ); hilightTile( TimerPos2, false ); break; // remove matching tiles from game board case 5: setRemovedTilePair(TimerPos1, TimerPos2); removeTile( TimerPos1, false ); removeTile( TimerPos2 ); drawTileNumber(); break; } // restart timer if demo mode is still active if( TimerState == Demo ) QTimer::singleShot( ANIMSPEED, this, SLOT( demoMoveTimeout() ) );}// ---------------------------------------------------------void BoardWidget::setShowMatch( bool show ){ if( showMatch ) stopMatchAnimation(); showMatch = show;}// ---------------------------------------------------------void BoardWidget::matchAnimationTimeout(){ if (matchCount == 0) return; if( iTimerStep++ & 1 ) { for(short Pos = 0; Pos < matchCount; Pos++) { hilightTile(PosTable[Pos], true); } } else { for(short Pos = 0; Pos < matchCount; Pos++) { hilightTile(PosTable[Pos], false); } } if( TimerState == Match ) QTimer::singleShot( ANIMSPEED, this, SLOT( matchAnimationTimeout() ) );}// ---------------------------------------------------------void BoardWidget::stopMatchAnimation(){ for(short Pos = 0; Pos < matchCount; Pos++) { hilightTile(PosTable[Pos], false); } TimerState = Stop; matchCount = 0;}void BoardWidget::redoMove(void){ setRemovedTilePair(Game.MoveList[Game.TileNum-1],Game.MoveList[Game.TileNum-2]); removeTile(Game.MoveList[Game.TileNum-1], false); removeTile(Game.MoveList[Game.TileNum-1]); drawTileNumber();}// ---------------------------------------------------------void BoardWidget::animateMoveList(){ setStatusText( i18n("Congratulations. You have won!") ); while( Game.TileNum < Game.MaxTileNum ) { // put back all tiles putTile(Game.MoveList[Game.TileNum]); Game.TileNum++; putTile(Game.MoveList[Game.TileNum], false); Game.TileNum++; drawTileNumber(); } while( Game.TileNum > 0 ) { // remove all tiles removeTile(Game.MoveList[Game.TileNum-1], false); removeTile(Game.MoveList[Game.TileNum-1]); drawTileNumber(); } calculateNewGame();}// ---------------------------------------------------------void BoardWidget::calculateNewGame( int gNumber){ cancelUserSelectedTiles(); initialiseRemovedTiles(); setStatusText( i18n("Calculating new game...") ); if( !loadBoard()) { setStatusText( i18n("Error converting board information!") ); return; } if (gNumber == -1) { gameGenerationNum = 0; } else { gameGenerationNum = gNumber; } random.setSeed(gameGenerationNum); // try max. 64 times for( short nr=0; nr<64; nr++ ) { if( generateStartPosition2() ) { drawBoard(); setStatusText( i18n("Ready. Now it's your turn.") ); cheatsUsed=0; return; } } drawBoard(); setStatusText( i18n("Error generating new game!") );}bool BoardWidget::generateStartPosition2() { int totalTiles=0; POSITION tilesLeft[BoardLayout::maxTiles]; memset(tilesLeft, 0, sizeof(tilesLeft)); // zero out all face values for (int z=0; z< BoardLayout::depth; z++) { for (int y=0; y<BoardLayout::height; y++) { for (int x=0; x<BoardLayout::width; x++) { Game.Board[z][y][x]=0; if (Game.Mask[z][y][x] == '1') { tilesLeft[totalTiles].x = x; tilesLeft[totalTiles].y = y; tilesLeft[totalTiles].e = z; tilesLeft[totalTiles].f = 254; totalTiles++; } } } } // Initialise the faces to allocate. For the classic // dragon board there are 144 tiles. So we allocate and // randomise the assignment of 144 tiles. If there are > 144 // tiles we will reallocate and re-randomise as we run out. // One advantage of this method is that the pairs to assign are // non-linear. In kmahjongg 0.4, If there were > 144 the same // allocation series was followed. So 154 = 144 + 10 rods. // 184 = 144 + 40 rods (20 pairs) which overwhemed the board // with rods and made deadlock games more likely. int remaining = totalTiles; randomiseFaces(); for (int tile=0; tile <totalTiles; tile+=2) { int p1; int p2; if (remaining > 2) { p2 = p1 = random.getLong(remaining-2); int bail = 0; while (p1 == p2) { p2 = random.getLong(remaining-2); if (bail >= 100) { printf("Bail!\n"); break; } if ((tilesLeft[p1].y == tilesLeft[p2].y) && (tilesLeft[p1].e == tilesLeft[p2].e)) { // skip if on same y line bail++; p2=p1; continue; } } } else { p1 = 0; p2 = 1; } POSITION a, b; a = tilesLeft[p1]; b = tilesLeft[p2]; tilesLeft[p1] = tilesLeft[remaining - 1]; tilesLeft[p2] = tilesLeft[remaining - 2]; remaining -= 2; getFaces(a, b); Game.putTile(a); Game.putTile(b); } Game.TileNum = Game.MaxTileNum; return 1; }void BoardWidget::getFaces(POSITION &a, POSITION &b) { a.f = tilePair[tilesUsed]; b.f = tilePair[tilesUsed+1]; tilesUsed += 2; if (tilesUsed >= 144) { randomiseFaces(); } }void BoardWidget::randomiseFaces(void) { int nr; int numAlloced=0; // stick in 144 tiles in pairsa. for( nr=0; nr<9*4; nr++) tilePair[numAlloced++] = TILE_CHARACTER+(nr/4); // 4*9 Tiles for( nr=0; nr<9*4; nr++) tilePair[numAlloced++] = TILE_BAMBOO+(nr/4); // 4*9 Tiles for( nr=0; nr<9*4; nr++) tilePair[numAlloced++] = TILE_ROD+(nr/4); // 4*9 Tiles for( nr=0; nr<4; nr++) tilePair[numAlloced++] = TILE_FLOWER+nr; // 4 Tiles for( nr=0; nr<4; nr++) tilePair[numAlloced++] = TILE_SEASON+nr; // 4 Tiles for( nr=0; nr<4*4; nr++) tilePair[numAlloced++] = TILE_WIND+(nr/4); // 4*4 Tiles for( nr=0; nr<3*4; nr++) tilePair[numAlloced++] = TILE_DRAGON+(nr/4); // 3*4 Tiles //randomise. Keep pairs together. Ie take two random //odd numbers (n,x) and swap n, n+1 with x, x+1 int at=0; int to=0; for (int r=0; r<200; r++) { to=at; while (to==at) { to = random.getLong(144); if ((to & 1) != 0) to--; } UCHAR tmp = tilePair[at]; tilePair[at] = tilePair[to]; tilePair[to] = tmp; tmp = tilePair[at+1]; tilePair[at+1] = tilePair[to+1]; tilePair[to+1] = tmp; at+=2; if (at >= 144) at =0; } tilesAllocated = numAlloced; tilesUsed = 0;/* printf("Allocated %d tiles\n",numAlloced); for (int t=0; t<numAlloced; t++) { printf("%2.2X ", tilePair[t]); if ((t % 20) == 19) printf("\n"); } printf("\n");*/}// ---------------------------------------------------------bool isFlower( UCHAR Tile ){ return( Tile >= TILE_FLOWER && Tile <=TILE_FLOWER+3 );}bool isSeason( UCHAR Tile ){ return( Tile >= TILE_SEASON && Tile <=TILE_SEASON+3 );}bool isBamboo(UCHAR t) { return( t >= TILE_BAMBOO && t <TILE_BAMBOO+9);}bool isCharacter(UCHAR t) { return( t >= TILE_CHARACTER && t <TILE_CHARACTER + 9);}bool isRod(UCHAR t) { return( t >= TILE_ROD && t <TILE_ROD + 9);}bool isDragon(UCHAR t) { return( t >= TILE_DRAGON && t < TILE_DRAGON +3);}bool isWind(UCHAR t) { return( t >= TILE_WIND && t < TILE_WIND +4);}bool BoardWidget::isMatchingTile( POSITION& Pos1, POSITION& Pos2 ){ // don't compare 'equal' positions if( memcmp( &Pos1, &Pos2, sizeof(POSITION) ) ) { UCHAR FA = Pos1.f; UCHAR FB = Pos2.f; if( (FA == FB) || ( isFlower( FA ) && isFlower( FB ) ) || ( isSeason( FA ) && isSeason( FB ) ) ) return( true ); } return( false );}// ---------------------------------------------------------bool BoardWidget::findMove( POSITION& posA, POSITION& posB ){ short Pos_Ende = Game.MaxTileNum; // Ende der PosTable for( short E=0; E<BoardLayout::depth; E++ ) { for( short Y=0; Y<BoardLayout::height-1; Y++ ) { for( short X=0; X<BoardLayout::width-1; X++ ) { if( Game.Mask[E][Y][X] != (UCHAR) '1' ) continue; if( ! Game.Board[E][Y][X] ) continue; if( E < 4 ) { if( Game.Board[E+1][Y][X] || Game.Board[E+1][Y+1][X] || Game.Board[E+1][Y][X+1] || Game.Board[E+1][Y+1][X+1] ) continue; } if( (Game.Board[E][Y][X-1] || Game.Board[E][Y+1][X-1]) && (Game.Board[E][Y][X+2] || Game.Board[E][Y+1][X+2]) ) continue; Pos_Ende--; PosTable[Pos_Ende].e = E; PosTable[Pos_Ende].y = Y; PosTable[Pos_Ende].x = X; PosTable[Pos_Ende].f = Game.Board[E][Y][X]; } } } // PosTable[0].e = BoardLayout::depth; // 1. Paar noch nicht gefunden iPosCount = 0; // Hier Anzahl der gefunden Paare merken // The new tile layout with non-contiguos horizantle spans // can lead to huge numbers of matching pairs being exposed. // we alter the loop to bail out when BoardLayout::maxTiles/2 pairs are found // (or less); while( Pos_Ende < Game.MaxTileNum-1 && iPosCount <BoardLayout::maxTiles-2) { for( short Pos = Pos_Ende+1; Pos < Game.MaxTileNum; Pos++) { if( isMatchingTile(PosTable[Pos], PosTable[Pos_Ende]) ) { if (iPosCount <BoardLayout::maxTiles-2) { PosTable[iPosCount++] = PosTable[Pos_Ende]; PosTable[iPosCount++] = PosTable[Pos]; } } } Pos_Ende++; } if( iPosCount>=2 ) { random.setSeed(0); // WABA: Why is the seed reset? short Pos = random.getLong(iPosCount) & -2; // Gerader Wert posA = PosTable[Pos]; posB = PosTable[Pos+1]; return( true ); } else return( false );}// ---------------------------------------------------------short BoardWidget::findAllMatchingTiles( POSITION& posA ){ short Pos = 0; for( short E=0; E<BoardLayout::depth; E++ ) { for( short Y=1; Y<BoardLayout::height-1; Y++ ) { for( short X=1; X<BoardLayout::width-1; X++ ) { if( Game.Mask[E][Y][X] != (UCHAR) '1' ) continue; if( ! Game.Board[E][Y][X] ) continue; if( E < 4 ) { if( Game.Board[E+1][Y][X] || Game.Board[E+1][Y+1][X] || Game.Board[E+1][Y][X+1] || Game.Board[E+1][Y+1][X+1] ) continue; } if( (Game.Board[E][Y][X-1] || Game.Board[E][Y+1][X-1]) && (Game.Board[E][Y][X+2] || Game.Board[E][Y+1][X+2]) ) continue; PosTable[Pos].e = E; PosTable[Pos].y = Y; PosTable[Pos].x = X; PosTable[Pos].f = Game.Board[E][Y][X]; if( isMatchingTile(posA, PosTable[Pos]) ) Pos++; } } } return Pos;}// ---------------------------------------------------------// This function replaces the old method of hilighting by// modifying color 21 to color 20. This was single tileset// specific. We now have two tile faces, one selected one not.void BoardWidget::hilightTile( POSITION& Pos, bool on, bool doRepaint ){ if (on) { Game.hilighted[Pos.e][Pos.y][Pos.x]=1; } else { Game.hilighted[Pos.e][Pos.y][Pos.x]=0; } if (doRepaint) { updateBackBuffer=true; repaint(0,0,-1,-1, false); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -