無敵井字遊戲

看板Programming作者時間18年前 (2007/05/12 13:01), 編輯推噓3(301)
留言4則, 4人參與, 最新討論串1/1
無敵井字遊戲 http://delphi.ktop.com.tw/board.php?cid=168&fid=919&tid=20420 無敵井字遊戲 資料來源:http://neuron.et.ntust.edu.tw/homework/89/PL/89homework%231/A8902123/C++.htm //--------------------------------------------------------------------------- // 程式名稱:無敵井字遊戲(目前為止) // 開發環境:Borland C++ Builder 4.0 (Professional) // 作業系統:Windows 95,98,2000,NT40 // 設 計 者:蘇坤明 (Allen or Su Kwan-Ming.) // 伊 媚 兒:allen@xsun.com.tw // 網站位址:http://www.xsun.com.tw // // 我是很支持OpenSource的作法,所以我寫的程式都會儘量公開原始程式 // 2000/8月份,我的第三套遊戲【超級比一比~絕色經典】預計上市 // 同時也會公開原始程式、工具軟體及出版此遊戲的製作說明書 // 歡迎對遊戲程式設計有興趣的玩家,踴躍上網訂購(預計8月初開放)(粉便宜哦!^-^) // 請多多上我的網站,陸續會有很多好東西公開哦!! // 願與大家一同成長! Allen. 2000/05/22. //--------------------------------------------------------------------------- #include #include #pragma hdrstop #include "Unit1.h" //--------------------------------------------------------------------------- // //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; const int CCBox[48]={// -|\/連線,其餘二格的座標位移 -2, 0,-1, 0,-1, 0, 1, 0, 1, 0, 2, 0, 0,-1, 0,-2, 0,-1, 0, 1, 0, 1, 0, 2, 1, 1, 2, 2,-1,-1, 1, 1,-1,-1,-2,-2, 1,-1, 2,-2,-1, 1, 1,-1,-1, 1,-2, 2}; //--------------------------------------------------------------------------- // 建構者 //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { //初始亂數 srand(GetTickCount()); while( int(GetTickCount()%5) != int(random(100)%5) ); } //--------------------------------------------------------------------------- // 建立時 //--------------------------------------------------------------------------- void __fastcall TForm1::FormCreate(TObject *Sender) { //建立9格按鈕 for(int y=0;y<3;y++) for(int x=0;x<3;x++) { SB[y*3+x]=new TSpeedButton(Panel1); SB[y*3+x]->Parent=Panel1; SB[y*3+x]->Left=x*64+8; SB[y*3+x]->Top =y*64+8; SB[y*3+x]->Width =56; SB[y*3+x]->Height=56; SB[y*3+x]->forbidden=SBClick; } //初始分數 iHumanScore=0; iComputerScore=0; iSameScore=0; //建立新局 SpeedButton1Click( SpeedButton1 ); } //--------------------------------------------------------------------------- // 移除時 //--------------------------------------------------------------------------- void __fastcall TForm1::FormDestroy(TObject *Sender) { for(int i=0; i<9; i++) delete SB[i]; } //--------------------------------------------------------------------------- // 玩家下棋動作 //--------------------------------------------------------------------------- void __fastcall TForm1::SBClick(TObject *Sender) { //本局已結束 if( iGameState==2 ) { MessageBox(Handle,"本局已結束,請重開新局!","提示!",MB_OK|MB_ICONINFORMATION); return; } //若不是空位 if( ((TSpeedButton *)Sender)->Caption!="" ) { MessageBox(Handle,"此位不是空位!","提示!",MB_OK|MB_ICONINFORMATION); return; } //空位則玩家可下 ((TSpeedButton *)Sender)->Caption="O"; ((TSpeedButton *)Sender)->Refresh(); if( CheckResult() ) return;//已有結果,電腦不必下,返回 ComputerAI(); if( CheckResult()==false ) //若未有結果,請玩家下 Panel2->Caption="請人類下"; } //--------------------------------------------------------------------------- // 重開新局 //--------------------------------------------------------------------------- void __fastcall TForm1::SpeedButton1Click(TObject *Sender) { for(int i=0; i<9; i++) SB[i]->Caption=""; iGameState=random(100)%2;//以亂數決定誰先下 ShowInfo(); if( iGameState==1 )//電腦先下 { ComputerAI(); Panel2->Caption="請人類下"; } } //--------------------------------------------------------------------------- // 電腦人工智慧 //--------------------------------------------------------------------------- void __fastcall TForm1::ComputerAI(void) { int i,j,x,y,max; int ccvalue[9]; int sameidx[9],samecount; AnsiString s; //電腦思考中 Panel2->Caption="電腦思考中"; for(i=0;i<10;i++) { Panel2->Caption=Panel2->Caption+"."; Sleep(60); Panel2->Refresh(); } //特殊情形,依經驗法則來下 s=""; for(i=0;i<9;i++) s+=( SB[i]->Caption=="" ) ? AnsiString(".") : SB[i]->Caption; if( s=="O...X...O" || s=="..O.X.O.." ) { i=random(4)*2+1; SB[i]->Caption="X"; SB[i]->Refresh(); return; } //權值歸0 for(i=0; i<9; i++) ccvalue[i]=0; //計算各空位的權值 for(i=0; i<9; i++) if( SB[i]->Caption=="" )//若是空位則計算 { x=i%3; y=i/3; for(j=0; j<12; j++) ccvalue[i]+=WhatValueIs(x+CCBox[j*4+0],y+CCBox[j*4+1],x+CCBox[j*4+2],y+CCBox[j*4+3]); } //找出最高權值 max=-1; for(i=0; i<9; i++) if( ccvalue[i]>max ) max=ccvalue[i]; //找出所有最高的權值 samecount=0; for(i=0; i<9; i++) if( ccvalue[i]==max ) { sameidx[ samecount ]=i;//記錄位置 samecount++;//個數加1 } //從最高權值位置,以亂數決定下於何處 i=random(samecount); SB[ sameidx[i] ]->Caption="X"; SB[ sameidx[i] ]->Refresh(); } //--------------------------------------------------------------------------- // 檢查並顯示結果,若為false代表結果未定 //--------------------------------------------------------------------------- bool __fastcall TForm1::CheckResult(void) { AnsiString tmp;//可連接的8條線所形成的字串 tmp[0]=SB[0]->Caption+SB[1]->Caption+SB[2]->Caption; tmp[1]=SB[3]->Caption+SB[4]->Caption+SB[5]->Caption; tmp[2]=SB[6]->Caption+SB[7]->Caption+SB->Caption; tmp[3]=SB[0]->Caption+SB[3]->Caption+SB[6]->Caption; tmp[4]=SB[1]->Caption+SB[4]->Caption+SB[7]->Caption; tmp[5]=SB[2]->Caption+SB[5]->Caption+SB->Caption; tmp[6]=SB[0]->Caption+SB[4]->Caption+SB->Caption; tmp[7]=SB[2]->Caption+SB[4]->Caption+SB[6]->Caption; //檢查電腦或人類是否勝利 for(int i=0; i<8; i++) { if(tmp[i]=="OOO")//人類勝利 { FlashMsg("真厲害,您贏了","●真厲害,您贏了●"); iHumanScore++; iGameState=2; ShowInfo(); return true; } if(tmp[i]=="XXX")//電腦勝利 { FlashMsg("電腦勝利!萬歲!","●電腦勝利!萬歲!●"); iComputerScore++; iGameState=2; ShowInfo(); return true; } } //還有空位可下,表示還可玩,結果未定 for(int i=0; i<9; i++) if( SB[i]->Caption=="" ) return false; //若無空位,表示平手 FlashMsg("合局平手!","●合局平手!●"); iSameScore++; iGameState=2; ShowInfo(); return true; } //--------------------------------------------------------------------------- // 計算直線中,其餘2格的權值 //--------------------------------------------------------------------------- int __fastcall TForm1::WhatValueIs(int x1,int y1,int x2,int y2) { //超出棋盤外,無權值 if( x1<0 || y1<0 || x2<0 || y2<0 || x1>2 || y1>2 || x2>2 || y2>2 ) return 0; //其餘2格,所形成的字串為何 AnsiString s=SB[y1*3+x1]->Caption + SB[y2*3+x2]->Caption; //依重要性傳回權值 if( s=="XX" ) return 56; else if( s=="OO" ) return 32; else if( s=="X" ) return 4; else if( s=="O" ) return 3; else if( s=="" ) return 2; else return 1; } //--------------------------------------------------------------------------- // 畫出遊戲資訊 //--------------------------------------------------------------------------- void __fastcall TForm1::ShowInfo(void) { LabelHuman->Caption=iHumanScore; LabelComputer->Caption=iComputerScore; LabelSame->Caption=iSameScore; if( iGameState==0 ) {LabelWho->Caption="人類"; Panel2->Caption="請人類下";} else if( iGameState==1 ) {LabelWho->Caption="電腦"; Panel2->Caption="";} else {LabelWho->Caption="結束"; Panel2->Caption="本局結束";} Refresh(); } //--------------------------------------------------------------------------- // 閃爍Panel2訊息 //--------------------------------------------------------------------------- void __fastcall TForm1::FlashMsg(AnsiString s1,AnsiString s2) { for(int i=0; i<20; i++) { Panel2->Caption=(i&1)?s1:s2; Panel2->Refresh(); Sleep(100); } ListBox1->Items->Add( "第 "+AnsiString(ListBox1->Items->Count+1)+" 次:"+s1 ); ListBox1->ItemIndex=ListBox1->Items->Count-1; } //--------------------------------------------------------------------------- // End //--------------------------------------------------------------------------- -- ◎(bbs.mgt.ncu.edu.tw) ◎[brucetsao]From: 59-115-92-61.dynamic.hinet.net

05/12 14:17, , 1F
並不是什麼都公開就有open source的意義
05/12 14:17, 1F

05/12 17:10, , 2F
井字遊戲不是永遠平手嗎!何來無敵
05/12 17:10, 2F

05/12 20:05, , 3F
沒輸就算贏一半...是匠子嗎?
05/12 20:05, 3F

05/12 21:19, , 4F
怎麼五年前的文章還在轉
05/12 21:19, 4F
文章代碼(AID): #16HKeH00 (Programming)
文章代碼(AID): #16HKeH00 (Programming)