📄 checkers.cxx
字号:
if (!fl_not_clipped(x,y,ISIZE,ISIZE)) return; switch (which) { case CBLACK: which = 0; break; case CWHITE: which = 1; break; case BLACKKING: which = 2; break; case WHITEKING: which = 3; break; default: return; } fl_color(FL_BLACK); bm[which][0]->draw(x, y); fl_color(FL_INACTIVE_COLOR); bm[which][1]->draw(x, y); fl_color(FL_SELECTION_COLOR); bm[which][2]->draw(x, y); fl_color(FL_WHITE); bm[which][3]->draw(x, y);}//----------------------------------------------------------------class Board : public Fl_Double_Window { void draw(); int handle(int);public: void drag_piece(int, int, int); void drop_piece(int); void animate(node* move, int backwards); void computer_move(int); Board(int w, int h) : Fl_Double_Window(w,h) {color(15);}};#define BOXSIZE 52#define BORDER 4#define BOARDSIZE (8*BOXSIZE+BORDER)#define BMOFFSET 5static int erase_this; // real location of dragging piece, don't draw itstatic int dragging; // piece being draggedstatic int dragx; // where it isstatic int dragy;static int showlegal; // show legal movesint squarex(int i) {return (usermoves(i,1)-'A')*BOXSIZE+BMOFFSET;}int squarey(int i) {return (usermoves(i,2)-'1')*BOXSIZE+BMOFFSET;}void Board::draw() { make_bitmaps(); fl_draw_box(box(),0,0,w(),h(),color()); fl_color((Fl_Color)10 /*107*/); int x; for (x=0; x<8; x++) for (int y=0; y<8; y++) { if (!((x^y)&1)) fl_rectf(BORDER+x*BOXSIZE, BORDER+y*BOXSIZE, BOXSIZE-BORDER, BOXSIZE-BORDER); } fl_color(FL_DARK3 /*FL_GRAY_RAMP+4*/); for (x=0; x<9; x++) { fl_rectf(x*BOXSIZE,0,BORDER,h()); fl_rectf(0,x*BOXSIZE,w(),BORDER); } for (int i = 5; i < 40; i++) if (i != erase_this) { draw_piece(b[i], squarex(i), squarey(i)); } if (showlegal) { fl_color(FL_WHITE); node* n; for (n = root->son; n; n = showlegal==2 ? n->son : n->brother) { int x1 = squarex(n->from)+BOXSIZE/2-5; int y1 = squarey(n->from)+BOXSIZE/2-5; int x2 = squarex(n->to)+BOXSIZE/2-5; int y2 = squarey(n->to)+BOXSIZE/2-5; fl_line(x1,y1,x2,y2); fl_push_matrix(); fl_mult_matrix(x2-x1,y2-y1,y1-y2,x2-x1,x2,y2); fl_begin_polygon(); fl_vertex(0,0); fl_vertex(-.3, .1); fl_vertex(-.3, -.1); fl_end_polygon(); fl_pop_matrix(); } int num = 1; fl_color(FL_BLACK); fl_font(FL_BOLD,10); for (n = root->son; n; n = showlegal==2 ? n->son : n->brother) { int x1 = squarex(n->from)+BOXSIZE/2-5; int y1 = squarey(n->from)+BOXSIZE/2-5; int x2 = squarex(n->to)+BOXSIZE/2-5; int y2 = squarey(n->to)+BOXSIZE/2-5; char buf[20]; sprintf(buf,"%d",num); fl_draw(buf, x1+int((x2-x1)*.85)-3, y1+int((y2-y1)*.85)+5); num++; } } if (dragging) draw_piece(dragging, dragx, dragy);}// drag the piece on square i to dx dy, or undo drag if i is zero:void Board::drag_piece(int i, int dx, int dy) { dy = (dy&-2) | dx&1; // make halftone shadows line up if (i != erase_this) drop_piece(erase_this); // should not happen if (!erase_this) { // pick up old piece dragx = squarex(i); dragy = squarey(i); erase_this = i; dragging = b[i]; } if (dx != dragx || dy != dragy) { damage(FL_DAMAGE_ALL, dragx, dragy, ISIZE, ISIZE); damage(FL_DAMAGE_ALL, dx, dy, ISIZE, ISIZE); } dragx = dx; dragy = dy;}// drop currently dragged piece on square ivoid Board::drop_piece(int i) { if (!erase_this) return; // should not happen! erase_this = 0; dragging = 0; int x = squarex(i); int y = squarey(i); if (x != dragx || y != dragy) { damage(4, dragx, dragy, ISIZE, ISIZE); damage(4, x, y, ISIZE, ISIZE); }}// show move (call this *before* the move, *after* undo):void Board::animate(node* move, int backwards) { if (showlegal) {showlegal = 0; redraw();} if (!move) return; int f = move->from; int t = move->to; if (backwards) {int x = f; f = t; t = x;} int x1 = squarex(f); int y1 = squarey(f); int x2 = squarex(t); int y2 = squarey(t); const int STEPS=35; for (int i=0; i<STEPS; i++) { int x = x1+(x2-x1)*i/STEPS; int y = y1+(y2-y1)*i/STEPS; drag_piece(move->from,x,y); Fl::flush(); } drop_piece(t); if (move->jump) redraw();}int busy; // causes pop-up abort menuvoid message(const char* m, ...) { char buffer[2048]; va_list a; va_start(a,m); vsprintf(buffer, m, a); va_end(a); fl_message(buffer);}void Board::computer_move(int help) { if (!playing) return; cursor(FL_CURSOR_WAIT); Fl::flush(); busy = 1; abortflag = 0; node* move = calcmove(root); busy = 0; if (move) { if (!help && move->value <= -30000) { message("%s resigns", move->who ? "White" : "Black"); playing = autoplay = 0; cursor(FL_CURSOR_DEFAULT); return; } animate(move,0); domove(move); } expandnode(root); if (!root->son) { message("%s has no move", root->who ? "Black" : "White"); playing = autoplay = 0; } if (!autoplay) cursor(FL_CURSOR_DEFAULT);}extern Fl_Menu_Item menu[];extern Fl_Menu_Item busymenu[];int Board::handle(int e) { if (busy) { const Fl_Menu_Item* m; switch(e) { case FL_PUSH: m = busymenu->popup(Fl::event_x(), Fl::event_y(), 0, 0, 0); if (m) m->do_callback(this, (void*)m); return 1; case FL_SHORTCUT: m = busymenu->test_shortcut(); if (m) {m->do_callback(this, (void*)m); return 1;} return 0; default: return 0; } } node *t, *n; static int deltax, deltay; int dist; const Fl_Menu_Item* m; switch (e) { case FL_PUSH: if (Fl::event_button() > 1) { m = menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, 0); if (m) m->do_callback(this, (void*)m); return 1; } if (playing) { expandnode(root); for (t = root->son; t; t = t->brother) { int x = squarex(t->from); int y = squarey(t->from); if (Fl::event_inside(x,y,BOXSIZE,BOXSIZE)) { deltax = Fl::event_x()-x; deltay = Fl::event_y()-y; drag_piece(t->from,x,y); return 1; } } } return 0; case FL_SHORTCUT: m = menu->test_shortcut(); if (m) {m->do_callback(this, (void*)m); return 1;} return 0; case FL_DRAG: drag_piece(erase_this, Fl::event_x()-deltax, Fl::event_y()-deltay); return 1; case FL_RELEASE: // find the closest legal move he dropped it on: dist = 50*50; n = 0; for (t = root->son; t; t = t->brother) if (t->from==erase_this) { int d1 = Fl::event_x()-deltax-squarex(t->to); int d = d1*d1; d1 = Fl::event_y()-deltay-squarey(t->to); d += d1*d1; if (d < dist) {dist = d; n = t;} } if (!n) {drop_piece(erase_this); return 1;} // none found drop_piece(n->to); domove(n); if (showlegal) {showlegal = 0; redraw();} if (n->jump) redraw(); computer_move(0); return 1; default: return 0; }}void quit_cb(Fl_Widget*, void*) {exit(0);}int FLTKmain(int argc, char** argv) { Fl::visual(FL_DOUBLE|FL_INDEX); Board b(BOARDSIZE,BOARDSIZE); b.callback(quit_cb); b.show(argc,argv); return Fl::run();} void autoplay_cb(Fl_Widget*bp, void*) { if (autoplay) {autoplay = 0; return;} if (!playing) return; Board* b = (Board*)bp; autoplay = 1; while (autoplay) {b->computer_move(0); b->computer_move(0);}}#include <FL/Fl_Box.H>Fl_Window *copyright_window;void copyright_cb(Fl_Widget*, void*) { if (!copyright_window) { copyright_window = new Fl_Window(400,270,"Copyright"); copyright_window->color(FL_WHITE); Fl_Box *b = new Fl_Box(20,0,380,270,copyright); b->labelsize(10); b->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_WRAP); copyright_window->end(); } copyright_window->hotspot(copyright_window); copyright_window->set_non_modal(); copyright_window->show();}void debug_cb(Fl_Widget*, void*v) { debug = !debug; ((Fl_Menu_Item*)v)->flags = debug ? FL_MENU_TOGGLE|FL_MENU_VALUE : FL_MENU_TOGGLE;}void forced_cb(Fl_Widget*b, void*v) { forcejumps = !forcejumps; ((Fl_Menu_Item*)v)->flags = forcejumps ? FL_MENU_TOGGLE|FL_MENU_VALUE : FL_MENU_TOGGLE; killnode(root->son); root->son = 0; if (showlegal) {expandnode(root); b->redraw();}}void move_cb(Fl_Widget*pb, void*) { Board* b = (Board*)pb; if (playing) b->computer_move(1); if (playing) b->computer_move(0);}void newgame_cb(Fl_Widget*b, void*) { showlegal = 0; newgame(); b->redraw();}void legal_cb(Fl_Widget*pb, void*) { if (showlegal == 1) {showlegal = 0; ((Board*)pb)->redraw(); return;} if (!playing) return; expandnode(root); showlegal = 1; ((Board*)pb)->redraw();}void predict_cb(Fl_Widget*pb, void*) { if (showlegal == 2) {showlegal = 0; ((Board*)pb)->redraw(); return;} if (playing) expandnode(root); showlegal = 2; ((Board*)pb)->redraw();}void switch_cb(Fl_Widget*pb, void*) { user = !user; ((Board*)pb)->computer_move(0);}void undo_cb(Fl_Widget*pb, void*) { Board* b = (Board*)pb; b->animate(undomove(),1); b->animate(undomove(),1);}//--------------------------#include <FL/Fl_Slider.H>#include <FL/Fl_Value_Output.H>Fl_Window *intel_window;Fl_Value_Output *intel_output;void intel_slider_cb(Fl_Widget*w, void*) { double v = ((Fl_Slider*)w)->value(); int n = int(v*v); intel_output->value(n); maxevaluate = maxnodes = n;}void intel_cb(Fl_Widget*, void*) { if (!intel_window) { intel_window = new Fl_Window(200,25,"Checkers Intelligence"); Fl_Slider* s = new Fl_Slider(60,0,140,25); s->type(FL_HOR_NICE_SLIDER); s->minimum(1); s->maximum(500); s->value(50); s->callback(intel_slider_cb); intel_output = new Fl_Value_Output(0,0,60,25); intel_output->value(maxevaluate); intel_window->resizable(s); } intel_window->hotspot(intel_window); intel_window->set_non_modal(); intel_window->show();}//---------------------------void stop_cb(Fl_Widget*, void*) {abortflag = 1;}void continue_cb(Fl_Widget*, void*) {}Fl_Menu_Item menu[] = { {"Autoplay", 'a', autoplay_cb}, {"Legal moves", 'l', legal_cb}, {"Move for me", 'm', move_cb}, {"New game", 'n', newgame_cb}, {"Predict", 'p', predict_cb}, {"Switch sides", 's', switch_cb}, {"Undo", 'u', undo_cb, 0, FL_MENU_DIVIDER}, {"Forced jumps rule", 'f', forced_cb, 0, FL_MENU_TOGGLE|FL_MENU_VALUE}, {"Debug", 'd', debug_cb, (void *)"d", FL_MENU_TOGGLE}, {"Intelligence...", 'i', intel_cb, 0, FL_MENU_DIVIDER}, {"Copyright", 'c', copyright_cb}, {"Quit", 'q', quit_cb}, {0}};Fl_Menu_Item busymenu[] = { {"Stop", '.', stop_cb}, {"Autoplay", 'a', autoplay_cb}, {"Continue", 0, continue_cb}, {"Debug", 'd', debug_cb, (void *)"d", FL_MENU_TOGGLE}, {"Intelligence...", 'i', intel_cb}, {"Copyright", 'c', copyright_cb}, {"Quit", 'q', quit_cb}, {0}};#endif////////////////////////////////////////////////////////////////// parts shared by both interface:#ifdef FLTK#ifdef VT100#define BOTH#endif#endif#ifdef BOTHint terminal;int arg(int, char **argv, int &i) { if (argv[i][1] == 't') {terminal = 1; i++; return 1;} return 0;}#endifint didabort(void) {#ifdef FLTK#ifdef BOTH if (!terminal)#endif Fl::check();#endif if (abortflag) { autoplay = 0; abortflag = 0; return 1; } return(0);}int main(int argc, char **argv) { seed = time(0); newgame();#ifdef BOTH int i = 1; if (Fl::args(argc, argv, i, arg) < argc) { fprintf(stderr," -t : use VT100 display\n", Fl::help); exit(1); } if (!getenv("DISPLAY")) terminal = 1; if (!terminal)#endif#ifdef FLTK return FLTKmain(argc,argv);#endif#ifdef VT100 return VT100main();#endif}//// End of "$Id: checkers.cxx,v 1.1.1.1 2003/08/07 21:18:42 jasonk Exp $".//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -