用C++Builder5.0设计九宫排字游戏
摘要:
九宫排字问题(又称八数码问题)是人工智能当中有名的难题之一。问题是在3×3方格盘上,放有八个数码,剩下第九个为空,每一空格其上下左右的数码可移至空格。问题给定初始位置和目标位置,要求通过一系列的数码移动,将初始位置转化为目标位置。本文介绍用C++Builder5.0编写九宫排字问题游戏。游戏规则是,动态产生初始状态,由初始状态出发,不断地在空格上下左右的数码移至空格,若能排出目标状态,则成功。
引言:
九宫排字问题(又称八数码问题)是人工智能当中有名的难题之一。问题是在3×3方格盘上,放有八个数码,剩下第九个为空,每一空格其上下左右的数码可移至空格。问题给定初始位置和目标位置,要求通过一系列的数码移动,将初始位置转化为目标位置.
九宫排字问题不是任何情况下都是有解的,我们可以把一个状态,自左至右,自上而下地用一维数组表示成(a1,a2,a3,a4,a5,a6,a7,a8)(空格跳过),而相应的位置也按同样的顺序排列,那么,如果在位置iaj,则说存在一个逆序,若逆序总数为偶数,则称相应的状态为偶状态,逆序总数为奇数,则称相应的状态为奇状态。
很明显,空格横向移动时,逆序总数无变化,而空格纵向移动时,逆序总数改变-2、0或2,因此,在任何情况下,奇状态和偶状态不可能相互转换。
九宫排字问题的求解方法,就是从初始状态出发,不断地空格上下左右的数码移至空格,将一个状态转化成其它状态,直到产生目标状态。如图二。
本文用C++Builder5.0编写九宫排字问题游戏。游戏规则是,动态产生初始状态,由初始状态出发,不断地空格上下左右的数码移至空格,若能排出目标状态,则成功。
图二、九宫排字问题的状态图
编程实现:
【第一步】选用C++Builder的菜单项“FileNew Application”,创建一个工程。
【第二步】给项目加入九个Panel控件,一个MainMenu控件,两个Label控件,并各控件的安排如图三所示。
图三、各控件的安排
【第三步】按表一、二所示设置有些控件属性:
表一、控件及其属性
表二、菜单的设计
【第四步】Form1的OnCreate事件写入以下代码,其目的为:随机产生初始状态。图四为程序随机产生初始状态一览。
void __fastcall TForm1::FormCreate(TObject *Sender)
{
AnsiString my_RondomNum[9];
for(int i=0;i<9;i++)
{
REDO:
my_RondomNum[i]=IntToStr(random(9));
for(int j=0;j
{
if(my_RondomNum[i]==my_RondomNum[j])
{
goto REDO;
}
}
}
for(int i=0;i<9;i++)
{
if(my_RondomNum[i]=="0")
{
my_RondomNum[i]="";
break;
}
}
Panel1->Caption=my_RondomNum[0];
Panel2->Caption=my_RondomNum[1];
Panel3->Caption=my_RondomNum[2];
Panel4->Caption=my_RondomNum[3];
Panel5->Caption=my_RondomNum[4];
Panel6->Caption=my_RondomNum[5];
Panel7->Caption=my_RondomNum[6];
Panel8->Caption=my_RondomNum[7];
Panel9->Caption=my_RondomNum[8];
my_Count=0;
Label1->Caption="0";
}
图四、程序随机产生初始状态一览
【第五步】Form1的OnKeyPress事件写入以下代码,其目的为:判断空格位置并相应的移动空格左右上下边的数码,w为上移、s为下移、a为左移、d为右移。同时判断是否达到目标状态,若是,则显示祝贺信息。
void __fastcall TForm1::FormKeyPress(TObject *Sender, char &Key)
{
if(Key=='s')//下移
{
if( Panel4->Caption=="")
{
Panel4->Caption=Panel1->Caption;
Panel1->Caption="";
my_Count++;
}
else if( Panel5->Caption=="")
{
Panel5->Caption=Panel2->Caption;
Panel2->Caption="";
my_Count++;
}
else if( Panel6->Caption=="")
{
Panel6->Caption=Panel3->Caption;
Panel3->Caption="";
my_Count++;
}
else if( Panel7->Caption=="")
{
Panel7->Caption=Panel4->Caption;
Panel4->Caption="";
my_Count++;
}
else if( Panel8->Caption=="")
{
Panel8->Caption=Panel5->Caption;
Panel5->Caption="";
my_Count++;
}
else if(Panel9->Caption=="")
{
Panel9->Caption=Panel6->Caption;
Panel6->Caption="";
my_Count++;
}
}
else if(Key=='w')//上移
{
if( Panel1->Caption=="")
{
Panel1->Caption=Panel4->Caption;
Panel4->Caption="";
my_Count++;
}
else if( Panel2->Caption=="")
{
Panel2->Caption=Panel5->Caption;
Panel5->Caption="";
my_Count++;
}
else if( Panel3->Caption=="")
{
Panel3->Caption=Panel6->Caption;
Panel6->Caption="";
my_Count++;
}
else if( Panel4->Caption=="")
{
Panel4->Caption=Panel7->Caption;
Panel7->Caption="";
my_Count++;
}
else if( Panel5->Caption=="")
{
Panel5->Caption=Panel8->Caption;
Panel8->Caption="";
my_Count++;
}
else if(Panel6->Caption=="")
{
Panel6->Caption=Panel9->Caption;
Panel9->Caption="";
my_Count++;
}
}
else if(Key=='d')//右移
{
if( Panel2->Caption=="")
{
Panel2->Caption=Panel1->Caption;
Panel1->Caption="";
my_Count++;
}
else if( Panel5->Caption=="")
{
Panel5->Caption=Panel4->Caption;
Panel4->Caption="";
my_Count++;
}
else if( Panel8->Caption=="")
{
Panel8->Caption=Panel7->Caption;
Panel7->Caption="";
my_Count++;
}
else if( Panel3->Caption=="")
{
Panel3->Caption=Panel2->Caption;
Panel2->Caption="";
my_Count++;
}
else if( Panel6->Caption=="")
{
Panel6->Caption=Panel5->Caption;
Panel5->Caption="";
my_Count++;
}
else if(Panel9->Caption=="")
{
Panel9->Caption=Panel8->Caption;
Panel8->Caption="";
my_Count++;
}
}
else if(Key=='a')//左移
{
if( Panel2->Caption=="")
{
Panel2->Caption=Panel3->Caption;
Panel3->Caption="";
my_Count++;
}
else if( Panel5->Caption=="")
{
Panel5->Caption=Panel6->Caption;
Panel6->Caption="";
my_Count++;
}
else if( Panel8->Caption=="")
{
Panel8->Caption=Panel9->Caption;
Panel9->Caption="";
my_Count++;
}
else if( Panel1->Caption=="")
{
Panel1->Caption=Panel2->Caption;
Panel2->Caption="";
my_Count++;
}
else if( Panel4->Caption=="")
{
Panel4->Caption=Panel5->Caption;
Panel5->Caption="";
my_Count++;
}
else if(Panel7->Caption=="")
{
Panel7->Caption=Panel8->Caption;
Panel8->Caption="";
my_Count++;
}
}
Label1->Caption=IntToStr(my_Count);
//判断是否达到目标状态,若是,显示祝贺信息
if(Panel1->Caption=="1"&&Panel2->Caption=="2"&&Panel3->Caption=="3"&&Panel4->Caption=="8"&&Panel5->Caption==""&&Panel6->Caption=="4"&&Panel7->Caption=="7"&&Panel8->Caption=="6"&&Panel9->Caption=="5")
{
Beep();
ShowMessage("祝贺您!");
}
}
【第六步】新游戏菜单项的OnClick事件写入以下代码,其目的为:随机产生初始状态。
void __fastcall TForm1::NewGameClick(TObject *Sender)
{
Panel1->Color=clHighlight;
Panel2->Color=clHighlight;
Panel3->Color=clHighlight;
Panel4->Color=clHighlight;
Panel5->Color=clHighlight;
Panel6->Color=clHighlight;
Panel7->Color=clHighlight;
Panel8->Color=clHighlight;
Panel9->Color=clHighlight;
AnsiString my_RondomNum[9];
for(int i=0;i<9;i++)
{
REDO:
my_RondomNum[i]=IntToStr(random(9));
for(int j=0;j
{
if(my_RondomNum[i]==my_RondomNum[j])
{
goto REDO;
}
}
}
for(int i=0;i<9;i++)
{
if(my_RondomNum[i]=="0")
{
my_RondomNum[i]="";
break;
}
}
Panel1->Caption=my_RondomNum[0];
Panel2->Caption=my_RondomNum[1];
Panel3->Caption=my_RondomNum[2];
Panel4->Caption=my_RondomNum[3];
Panel5->Caption=my_RondomNum[4];
Panel6->Caption=my_RondomNum[5];
Panel7->Caption=my_RondomNum[6];
Panel8->Caption=my_RondomNum[7];
Panel9->Caption=my_RondomNum[8];
my_Count=0;
Label1->Caption="0";
}
【第七步】答案菜单项的OnClick事件写入以下代码,其目的为:显示目标状态。图五为程序目标状态一览。
void __fastcall TForm1::AnswerClick(TObject *Sender)
{
Panel1->Color=clSilver;
Panel2->Color=clSilver;
Panel3->Color=clSilver;
Panel4->Color=clSilver;
Panel5->Color=clSilver;
Panel6->Color=clSilver;
Panel7->Color=clSilver;
Panel8->Color=clSilver;
Panel9->Color=clSilver;
Panel1->Caption="1";
Panel2->Caption="2";
Panel3->Caption="3";
Panel4->Caption="8";
Panel5->Caption="";
Panel6->Caption="4";
Panel7->Caption="7";
Panel8->Caption="6";
Panel9->Caption="5";
}
图五、程序目标状态一览
【第八步】How To菜单项的OnClick事件写入以下代码,其目的为:显示帮助主体。
void __fastcall TForm1::HowtoClick(TObject *Sender)
{
ShowMessage("上移 --- w下移 --- s左移 --- a右移 --- d");
}
【第九步】关于菜单项的OnClick事件写入以下代码,其目的为:显示开发者信息。
void __fastcall TForm1::AboutClick(TObject *Sender)
{
ShowMessage("新疆大学信息科学与工程学院 木合塔尔");
}
【第十步】退出菜单项的OnClick事件写入以下代码,其目的为:退出应用程序。
void __fastcall TForm1::ExitClick(TObject *Sender)
{
Close();
}
Tags:
作者:佚名评论内容只代表网友观点,与本站立场无关!
评论摘要(共 0 条,得分 0 分,平均 0 分)
查看完整评论