📄 wordgame.cpp
字号:
int lose=0; for ( int j=0; j<c; j++ ) lose += r->tileRef(j)->value(); totalleft += lose; scoreinfo->addScore(i,-lose); } else { out = i; } } int highest=0; int winner=0; for (i=0; i<nplayers; i++) { int s = scoreinfo->playerScore(i); if ( s > highest ) { highest = s; winner = i; } } if ( out >= 0 ) scoreinfo->addScore(out,totalleft); scoreinfo->setBoldOne(winner); gameover = TRUE; done->setEnabled(TRUE); reset->setEnabled(FALSE);}void WordGame::endTurn(){ if ( gameover ) { openGameSelector(namelist); } else { if ( board->checkTurn() ) { if ( board->turnScore() >= 0 ) { scoreinfo->addScore(player,board->turnScore()); board->finalizeTurn(); } else { QApplication::beep(); } nextPlayer(); } }}void WordGame::resetTurn(){ board->resetRack();}void WordGame::passTurn(){ // ######## trade? nextPlayer();}bool WordGame::refillRack(int i){ Rack* r = rack(i); while ( !bag->isEmpty() && !r->isFull() ) { r->addTile(bag->takeRandom()); } return r->count() != 0;}void WordGame::readyRack(int i){ Rack* r = rack(i); racks->raiseWidget(i); board->setCurrentRack(r); done->setEnabled( !r->computerized() ); reset->setEnabled( !r->computerized() ); if ( r->computerized() ) { cpu = new ComputerPlayer(board, r); aiheart->start(0); }}Rack* WordGame::rack(int i) const{ return racks ? (Rack*)racks->widget(i) : NULL;}void WordGame::think(){ if ( !cpu->step() ) { delete cpu; cpu = 0; aiheart->stop(); if ( board->turnScore() < 0 ) passTurn(); else endTurn(); }}ComputerPlayer::ComputerPlayer(Board* b, Rack* r) : board(b), rack(r), best(new const Tile*[rack_tiles]), best_blankvalues(new Tile[rack_tiles]){ best_score = -1; across=FALSE; dict=0;}ComputerPlayer::~ComputerPlayer(){ delete [] best; delete [] best_blankvalues;}bool ComputerPlayer::step(){ const QDawg::Node* root = dict ? Global::dawg("WordGame").root() : Global::fixedDawg().root(); QPoint d = across ? QPoint(1,0) : QPoint(0,1); const Tile* tiles[99]; // ### max board size uchar nletter[4095]; // QDawg only handles 0..4095 memset(nletter,0,4096); for (int i=0; i<rack->count(); i++) { const Tile* r = rack->tileRef(i); if ( r->isBlank() ) nletter[0]++; else nletter[r->text()[0].unicode()]++; } Tile blankvalues[99]; // ### max blanks findBest(current, d, root, 0, nletter, tiles, 0, blankvalues, 0); if ( ++current.rx() == board->xTiles() ) { current.rx() = 0; if ( ++current.ry() == board->yTiles() ) { if ( across ) { if ( dict == 1 ) { if ( best_score >= 0 ) { rack->arrangeTiles(best,best_n); rack->setBlanks(best_blankvalues); board->scoreTurn(best_start, best_n, best_dir); board->showTurn(); } return FALSE; } dict++; across = FALSE; current = QPoint(0,0); } else { across = TRUE; current = QPoint(0,0); } } } return TRUE;}void ComputerPlayer::findBest(QPoint at, const QPoint& d, const QDawg::Node* node, ulong used, uchar* nletter, const Tile** tiles, int n, Tile* blankvalues, int blused){ if ( !node ) return; QChar l = node->letter(); const Tile* cur = board->tile(at); if ( cur ) { if ( cur->text()[0] == l ) { bool nextok = board->contains(at+d); if ( node->isWord() && n && (!nextok || !board->tile(at+d)) ) noteChoice(tiles,n,d,blankvalues,blused); if ( nextok ) findBest(at+d, d, node->jump(), used, nletter, tiles, n, blankvalues, blused); // #### text()[1]... } } else { if ( nletter[l.unicode()] || nletter[0] ) { int rc = rack->count(); ulong msk = 1; for ( int x=0; x<rc; x++ ) { if ( !(used&msk) ) { const Tile* t = rack->tileRef(x); if ( t->isBlank() || t->text() == l ) { // #### multi-char value()s bool nextok = board->contains(at+d); tiles[n++] = t; if ( t->isBlank() ) blankvalues[blused++] = Tile(l,0); if ( node->isWord() && (!nextok || !board->tile(at+d)) ) noteChoice(tiles,n,d,blankvalues,blused); used |= msk; // mark nletter[t->text()[0].unicode()]--; if ( nextok ) findBest(at+d, d, node->jump(), used, nletter, tiles, n, blankvalues, blused); n--; nletter[t->text()[0].unicode()]++; if ( t->isBlank() ) { // keep looking blused--; used &= ~msk; // unmark } else { break; } } } msk <<= 1; } } // #### text()[1]... } findBest(at, d, node->next(), used, nletter, tiles, n, blankvalues, blused);}void ComputerPlayer::noteChoice(const Tile** tiles, int n, const QPoint& d, const Tile* blankvalues, int blused){ int s = board->score(current, tiles, n, blankvalues, d, TRUE, 0);/*if (s>0 || current==QPoint(5,1)){QString st;for ( int i=0; i<n; i++ ) st += tiles[i]->text();qDebug("%d,%d: %s (%d) for %d",current.x(),current.y(),st.latin1(),n,s);}*/ if ( s > best_score ) { int i; for ( i=0; i<n; i++ ) best[i] = tiles[i]; for ( i=0; i<blused; i++ ) best_blankvalues[i] = blankvalues[i]; best_n = n; best_blused = blused; best_score = s; best_dir = d; best_start = current; }}int TileItem::smallWidth(){ return tile_smallw;}int TileItem::smallHeight(){ return tile_smallh;}int TileItem::bigWidth(){ return tile_bigw;}int TileItem::bigHeight(){ return tile_bigh;}void TileItem::setState( State state ){ hide(); s = state; show(); // ### use update() in Qt 3.0}void TileItem::setTile(const Tile& tile){ hide(); t = tile; show(); // ### use update() in Qt 3.0}void TileItem::setBig(bool b){ big = b;}void TileItem::drawShape(QPainter& p){ static QFont *value_font=0; static QFont *big_font=0; static QFont *small_font=0; if ( !value_font ) { value_font = new QFont("helvetica",8); if ( TileItem::bigWidth() < 20 ) { big_font = new QFont("helvetica",12); small_font = new QFont("helvetica",8); } else { big_font = new QFont("smoothtimes",17); small_font = new QFont("smoothtimes",TileItem::smallWidth()*10/16); } } QRect area((int)(x()),int(y()),width(),height()); p.setBrush(s == Floating ? yellow/*lightGray*/ : white); p.drawRect(area); if ( big ) { p.setFont(*value_font); QString n = QString::number(t.value()); int w = p.fontMetrics().width('1'); int h = p.fontMetrics().height(); w *= n.length(); QRect valuearea((int)(x())+width()-w-1,int(y())+height()-h,w,h); p.drawText(valuearea,AlignCenter,n); p.setFont(*big_font); area = QRect(int(x()),int(y())+tile_btweak,width()-4,height()-1); } else { p.setFont(*small_font); area = QRect(int(x())+1+tile_stweak,int(y())+1,width(),height()-3); } if ( t.value() == 0 ) p.setPen(darkGray); p.drawText(area,AlignCenter,t.text().upper());}Board::Board(QPixmap bgshapes, int w, int h, QWidget* parent) : QCanvasView(new QCanvas(bgshapes,w,h, TileItem::smallWidth(), TileItem::smallHeight()), parent){ setFixedSize(w*TileItem::smallWidth(),h*TileItem::smallHeight()); grid = new TileItem*[w*h]; memset(grid,0,w*h*sizeof(TileItem*)); setFrameStyle(0); setHScrollBarMode(AlwaysOff); setVScrollBarMode(AlwaysOff); current_rack = 0; shown_n = 0;}Board::~Board(){ delete canvas();}QSize Board::sizeHint() const{ return QSize(canvas()->width(),canvas()->height());}void Board::writeConfig(Config& cfg){ unshowTurn(); // not simple to save this info QStringList t; int n=canvas()->tilesHorizontally()*canvas()->tilesVertically(); for (int i=0; i<n; i++) t.append( grid[i] ? grid[i]->tile().key() : QString(".") ); cfg.writeEntry("Board",t,';');}void Board::readConfig(Config& cfg){ clear(); QStringList t = cfg.readListEntry("Board",';'); int i=0; int h=canvas()->tilesHorizontally(); for (QStringList::ConstIterator it=t.begin(); it!=t.end(); ++it) { if ( *it != "." ) { QPoint p(i%h,i/h); setTile(p,Tile(*it)); } i++; } canvas()->update();}void Board::clear(){ int n=canvas()->tilesHorizontally()*canvas()->tilesVertically(); for (int i=0; i<n; i++) { delete grid[i]; grid[i]=0; }}void Board::setCurrentRack(Rack* r){ turn_score = -1; current_rack = r;}void Board::resetRack(){ unshowTurn(); canvas()->update();}void Board::contentsMousePressEvent(QMouseEvent* e){ dragstart = e->pos();}void Board::contentsMouseMoveEvent(QMouseEvent* e){ if ( current_rack && !current_rack->computerized() ) { QPoint d = e->pos() - dragstart; if ( d.x() <= 0 && d.y() <= 0 ) { // None resetRack(); } else { int n; QPoint start=boardPos(dragstart); QPoint end=boardPos(e->pos()); QPoint diff=end-start; QPoint dir; if ( d.x() > d.y() ) { n = diff.x()+1; dir = QPoint(1,0); } else { n = diff.y()+1; dir = QPoint(0,1); } unshowTurn(); // Subtract existing tiles from n QPoint t = start; for ( int i=n; i--; ) { if ( contains(t) && tile(t) ) n--; t += dir; } // Move start back to real start while (contains(start-dir) && tile(start-dir)) start -= dir; scoreTurn(start, n, dir); showTurn(); } }}void Board::finalizeTurn(){ int i=0; QPoint at = shown_at; while ( i<shown_n && contains(at) ) { if ( item(at) && item(at)->state() == TileItem::Floating ) { current_rack->remove(item(at)->tile()); setTileState(at,TileItem::Firm); i++; } at += shown_step; } canvas()->update();}void Board::unshowTurn(){ int i=0; QPoint at = shown_at; while ( i<shown_n && i<current_rack->count() && contains(at) ) { if ( item(at) && item(at)->state() == TileItem::Floating ) { unsetTile(at); i++; } at += shown_step; }}void Board::showTurn(){ unshowTurn(); QPoint at = shown_at; int i=0; while ( i<shown_n && i<current_rack->count() && contains(at) ) { if ( !tile(at) ) { Tile t = current_rack->tile(i); setTile(at,t); setTileState(at,TileItem::Floating); i++; } at += shown_step; } canvas()->update();}int Board::bonussedValue(const QPoint& at, int base, int& all_mult) const{ int rule = rule_shape[idx(at)]-'0'; int effect = rule_effect[rule]; int mult = effect&Multiplier; if ( effect & MultiplyAll ) { all_mult *= mult; return base; } else { return base * mult; }}bool Board::isStart(const QPoint& at) const{ int rule = rule_shape[idx(at)]-'0'; int effect = rule_effect[rule]; return effect&Start;}bool Board::checkTurn(){ if ( current_rack->computerized() ) return TRUE; // computer doesn't cheat, and has already set blanks. QPoint at = shown_at; int n = shown_n; QPoint d = shown_step; const Tile* tiles[99]; Tile blankvalues[99]; if ( n > current_rack->count() ) n = current_rack->count(); QDialog check(this,0,TRUE); (new QVBoxLayout(&check))->setAutoAdd(TRUE); QHBox mw(&check); new QLabel(tr("Blanks: "),&mw); int bl=0; QLineEdit* le[99]; for (int i=0; i<n; i++) { tiles[i] = current_rack->tileRef(i); if ( tiles[i]->isBlank() ) { QLineEdit *l = new QLineEdit(&mw); le[bl++] = l; l->setMaxLength(1); l->setFixedSize(l->minimumSizeHint()); } } QHBox btns(&check); connect(new QPushButton(tr("OK"),&btns), SIGNAL(clicked()), &check, SLOT(accept())); connect(new QPushButton(tr("Cancel"),&btns), SIGNAL(clicked()), &check, SLOT(reject())); if ( bl ) {retry: if ( !check.exec() ) { unshowTurn(); canvas()->update();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -