看板Programming
标 题无敌井字游戏
发信站中央资管龙猫资讯天地 (Fri May 11 00:03:40 2007)
转信站ptt!ctu-reader!ctu-gate!news.nctu!news.ncu!news.mgt.ncu!bbs
无敌井字游戏
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.)
// 伊 媚 儿:
[email protected]
// 网站位址:
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
1F:推 ephesians:并不是什麽都公开就有open source的意义 61.231.67.235 05/12 14:17
2F:推 final01:井字游戏不是永远平手吗!何来无敌140.134.110.252 05/12 17:10
3F:推 OrzOGC:没输就算赢一半...是匠子吗? 125.231.194.34 05/12 20:05
4F:→ iscu:怎麽五年前的文章还在转 220.132.88.22 05/12 21:19