魔方游戏程序设计

魔方游戏是个经典的游戏,在当前AI人工智能发展的大好形势下,机器人还原魔方成为一个很好的课题。由我对游戏和编程的兴趣爱好,设计编制了此魔方游戏程序。

3591a7638eae41239eb1325af4748c25.png

 

魔方游戏程序设计几个方面的要点:

一、游戏界面设计
我是在手机上编制程序的,故游戏界面是手机界面。由于界面限制,只能将各个游戏功能紧凑在小界面上。

上部设置常用按钮:开始游戏,还原魔方,自动演示,退出程序,加 版本信息。
另加下拉菜单,可选六步解法,查看走步记录等。
中部设置魔方状态图,前右上三个面采用伪3D的图样,另加左后底三个面的平面图样。特别一点,图框下面加了六个面的一体图样。这样可使游戏者比较直观的看到魔方的状态。
下部设置操作按钮的功能块,设置了全部的12个操作按钮,和3个旋转翻转按钮。便于游戏的操作。

游戏的图形界面的是用简单的C语言编制的,全是用编译器绘图方法绘制的。一般的游戏图形都是方形和圆形为主,此魔方游戏图形是用伪3D的方法绘制的。此方法是用平面绘画方法画出许多菱形拼接成魔方的立体图像,给你的观感是立体的魔方。你可看到魔方的三个面,前面右面和上面。这样你能根据小方块的颜色来判断而操作魔方。一般人玩魔方都是左手拿魔方,右手做各种旋转动作。此设计就是左手拿手机,右手转魔方。游戏的视觉效果就这样。


二、游戏功能设置
游戏功能最主要的就是15个操作按钮的功能,我设计了一个比较直观的易于理解的算法。用一个数组存储六个面的54个小块的颜色值,一切的操作变换都是颜色的变换。我写了15个操作键的函数就能让魔方转起来。直接可以玩了,就这么简单。又写了判断完成的函数,这是游戏的基本的东西。
另外我做了隐藏按钮,在图框的右下角,可以查看4个重要的公式(助记),以及操作ABCD 公式。这些都是增加游戏可操控性。

4397efb05ba145da9849620e5201d10b.png

 

算法解释:
int  B[70] ;     //存储颜色值,值为1-6,预设置为:蓝红绿   黄橙白
左面:基色蓝,编码B11- B19,    前面:基色红,编码 B21 - B29,
右面:基色绿,编码B31- B39,    上面:基色黄,编码 B41 - B49,
后面:基色橙,编码B51- B59,    下面:基色白,编码 B61 - B69,

(附图)

f685dbc9604746e38e27135803856df3.png

c8ca842e1cb74bc4bb4c66d945a6e02b.png 

Frontright (){   //前右 F
     sw[1]=B[47];     sw[2]=B[48];     sw[3]=B[49];      //sw  = swap
     B[47]=B[19];     B[48]=B[16];    B[49]=B[13];
     B[19]=B[63];     B[16]=B[62];     B[13]=B[61];
     B[63]=B[31];     B[62]=B[34];     B[61]=B[37];
     B[31]=sw[1];     B[34]=sw[2];     B[37]=sw[3];
       sw[1]=B[21];    B[21]=B[27];        B[27]=B[29];     B[29]=B[23];    B[23]=sw[1];    
       sw[2]=B[22];     B[22]=B[24];     B[24]=B[28];     B[28]=B[26];    B[26]=sw[2];    
   ts=ts+1;      //走步计数
     drawbox ();      //画出
print "do>  F    Front right ";     //打印走步记录
}//Frontright()

这算法很简单,没什么深奥的理论。就是按规则转换颜色值,画出魔方。


三、AI 智能解魔方
演示套用说明书经典公式,即六步公式:上层四棱,上层四角,翻转,二层四棱,上层十字,顶面同色,六面同色。同时还提供操作记录,查看操作复盘。自动演示的记录就套用六步公式以供学习和研究用。我感觉用手机玩魔方的手感有种别样的味道。
上层四棱按基本操作完成,上层四角有3个公式来完成,二层四棱有2个公式来完成。接下来有易于记忆的ABCD 4个公式,上层十字用A 公式,顶面同色用B C  公式,六面同色用D公式。公式简单易于理解,不作解释了。用公式时如何调整状态,代码里有解释。此方法公式量少,完成魔方要140-200步。演示解魔方用时也就70到100秒。

 

f3c0860c36714455b79aac14125fc2d3.png

 1064c8515d0943608374ee5090f7780e.png

 

手机魔方游戏我见过国外编的仿3D动画式的游戏,用手指滑动旋转操作,蛮酷的。我这个游戏是很小巧的,它的优点是简单和有趣,希望大家喜欢。

四、魔方游戏设计前瞻
现在大家在玩用程序来解魔方,还有机器人解魔方。
输入打乱的魔方的颜色图,由程序来解,输出解法步骤。此程序扩展一下就行。
至于机器人解魔方,此程序就能输出解法步,开一个数组存储解法步,如:
 String  A[300]  =  ( R1, U,  R,  U, R, U, R1, U, ............),
传导给机器人程序,由它来解释操作。程序中打印记录抽出操作步就可以。
机器手设计,魔方翻转较难,那么就在第一步上层四棱和第二步上层四角操作倒着做,改为底层十字底层四角直接操作倒下面。后面的操作时底部白色中心和上面的黄色中心块是不变的。这样设计机器操作就简单了。
至于机器的速度,我手机操作用时70-100秒,大多时间是画出图样,我估计机器动作也就10秒吧。网上看到机器手解魔方视频,有兴趣的小伙伴可试验下。

本程序用的C语言是MySpringC v.2.7是目前的完善版本。
下面的游戏代码就是用它在安卓手机上编写的,可制作成安卓手机桌面app应用程序。此样例可复制黏贴到编译器直接使用,亦可用 VB6 ,C++ ,  java  改写。

95ae3d5bd7b64ae4b85c318277a89cbb.png

 

以下是源码:
//  最简单的 C 语言编程
//  myspringc  v2.7  可编译安卓本机 app 应用
//  此样例可复制黏贴到 myspringc  编译
//  此文档可用 VB,VC  ,  java 改写
//***********************
//   魔方  Magic Cube 
//   [email protected]
//   2024-07-15   修订
//***********************
Canvas cs ;
string sBarDes[10];
int nBarId[10];
string sMenu[50];
int nMenu[50];
float pi=3.1415926535;
float src[4];  //ClearDraw (cls) clear screen
string s,s1,s2,s3,s4,s5,s6,s7,s8,ss1,ss2,ss3;
float sx,sy,dx,dy;
float px,py;
FileInput filebox;
string fname;  //filename
int i,j,n,t,k,ts;    //t = times
int context,obj,id,event;   //canvasProc
int bx,by;   //button x y position 
int bn;        //button id number
int B[70]; //1 left 2 front 3 right 4 up 5 back 6 down
  int cr1,cg1,cb1;    //set color rgb
 int scolor;              // switch cube color
 int sw[9];               //switch B color
 int donum;            //calculate do step number
 int kn,cando;
 double Rn;            //random number
 int tim[3];              //get Time
 int hh,mm,ss;
 int oldhh,oldmm,oldss;
 int newhh,newmm,newss;
 int mms;               //show using time
 string hhts,mmts,ssts, tim$;
string fs1,fs2,fs3,fs4,fs5,fs6;    //show formula
string fma,fmb,fmc,fmd, fmd1;           //formula
 int ms, uf;      //using formula

main(){
  setDisplay(1);
  cs.Active();
  cs.SetProc (context, mycanvasProc); //getProc
   sBarDes[0]="开始游戏";
   nBarId[0]=100;
   sBarDes[1]="还原魔方";
   nBarId[1]=101;
   sBarDes[2]="自动演示";
   nBarId[2]=102;
   sBarDes[3]="显示图板";
   nBarId[3]=103;
   sBarDes[4]="退出程序";
   nBarId[4]=104;
   sBarDes[5]="V.";
   nBarId[5]=105;
   setToolBarHeight(6);
   setButtonTextSize(13);
   setButtonColor(255,0,0,250);
   setButtonTextColor(255,255,255,0);
setToolBar(100,myToolBarProc,sBarDes,nBarId,6);

   sMenu[0]="开始游戏";
   nMenu[0]=200;
   sMenu[1]="第一步:上层四棱";
   nMenu[1]=201;
   sMenu[2]="第二步:上层四角";
   nMenu[2]=202;
   sMenu[3]="第三步:二层四棱";
   nMenu[3]=203;
   sMenu[4]="第四步:顶层十字";
   nMenu[4]=204;
   sMenu[5]="第五步:顶面同色";
   nMenu[5]=205;
   sMenu[6]="第六步:六面同色";
   nMenu[6]=206;
   sMenu[7]="自动演示";
   nMenu[7]=207;
   sMenu[8]="查看走步记录";
   nMenu[8]=208;
   sMenu[9]="显示游戏图板";
   nMenu[9]=209;
   sMenu[10]="退出";
   nMenu[10]=210;
   setMenu(200,myMenuProc,sMenu,nMenu,11);
  setTitle("魔方 Magic Cube ");
//*****************************
      getTime (tim);
      oldhh=tim[0];
      oldmm=tim[1];
      oldss=tim[2];
    kn=2;
   drawcover ();
while (){}   
  }//main ()  

mycanvasProc (int context,int obj,int id,int event,float x,float y){
        bn=0;       //init buttom
   if (event==0||event==2||event==10){ //get  touch
              kn=kn+1;
         if ((kn-kn/2*2)==0){   //触控防闪烁
              cando=1;  }else{cando=0; return;  }
//设置界面操作按钮 12 cmd + 3 转向
    if (x>20&&x<110){  //select button btn number 
        if (y>770&&y<840)bn=1;
        if (y>840&&y<910)bn=2;
        if (y>920&&y<980)bn=9;   }
    if (x>310&&x<400){  //select button btn number 
        if (y>760&&y<840)bn=3;
        if (y>840&&y<920)bn=4;
        if (y>920&&y<990)bn=10;   }
      if (x>120&&x<210&&y>750&&y<810)bn=5;
      if (x>210&&x<300&&y>750&&y<810)bn=6;
      if (x>120&&x<210&&y>815&&y<885)bn=7;
      if (x>210&&x<300&&y>815&&y<885)bn=8;
      if (x>120&&x<210&&y>890&&y<960)bn=11;
      if (x>210&&x<300&&y>890&&y<960)bn=12;
  //左旋转,右旋转,上翻转
      if (x>430&&x<555&&y>750&&y<840)bn=13;
      if (x>560&&x<690&&y>750&&y<840)bn=14;
      if (x>490&&x<620&&y>850&&y<950)bn=15;
//** 设置操作标记
      cs.SetFillMode (1);
      cs.SetTextSize (20);
      cs.SetColor(255,255,255,255); 
      //cs.DrawCircle (160,280,5);  //L
     // cs.DrawCircle (160,440,5);
      if (x>120&&x<200&&y>240&&y<320)bn=1;
      if (x>120&&x<200&&y>400&&y<480)bn=2;
      cs.DrawText ("L1",150,290);
      cs.DrawText ("L",150,450);

     // cs.DrawCircle (320,370,2);  //R
     // cs.DrawCircle (320,520,2);
      if (x>280&&x<360&&y>330&&y<410)bn=3;
      if (x>280&&x<360&&y>480&&y<560)bn=4;
      cs.DrawText ("R",310,370);
      cs.DrawText ("R1",305,530);

   // cs.DrawCircle (260,270,40);   //U
    //cs.DrawCircle (450,270,40);
      if (x>220&&x<300&&y>230&&y<310)bn=5;
      if (x>410&&x<490&&y>230&&y<310)bn=6;
      cs.DrawText ("U",270,270);
      cs.DrawText ("U1",430,270);

      //cs.DrawCircle (400,370,2);   //F
       //cs.DrawCircle (400,520,2);
      if (x>360&&x<440&&y>330&&y<410)bn=7;
      if (x>360&&x<440&&y>480&&y<560)bn=8;
      cs.DrawText ("F1",390,370);
      cs.DrawText ("F",395,530);

      //cs.DrawCircle (560,280,5);  //B
      //cs.DrawCircle (560,440,5);
      if (x>520&&x<600&&y>240&&y<320)bn=10;
      if (x>520&&x<600&&y>400&&y<480)bn=9;
      cs.DrawText ("B",550,290);
      cs.DrawText ("B1",550,450);

     //  cs.DrawCircle (230,490,4);   //D
      // cs.DrawCircle (480,490,4);
      if (x>190&&x<270&&y>450&&y<530)bn=11;
      if (x>440&&x<520&&y>450&&y<530)bn=12;
      cs.DrawText ("D1",230,490);
      cs.DrawText ("D",470,490);

       cs.SetColor (255,0,0,250) ;
       cs.DrawCircle (648,700, 21) ;
       cs.DrawCircle (660,700, 21) ;
       cs.SetColor (255,250,250,0) ;
       cs.DrawText ("Fm", 640, 705 ) ;

//公式解法:
//顶层十字:至多三次即可
//公式 A:R1  U1  F1    U  F  R 
// 顶面同色,顶面十字四角无色块,下角色块置左; 
// 有一块,田置左下; 有二块,黄色置前左
 //公式 B:R  U  R1  U  R  U U  R1
//顶面同色:调整角块,两角块同色置前
//公式 C:R  B1  R  FF  R1  B  R  FF  RR
//六面同色:顶棱同色置后B,
//公式 D:R  U1  R  U  R  U  R  U1  R1  U1  RR

         fma="A =  R1  U1  F1    U  F  R ";
         fmb="B =  R  U  R1  U  R   U U   R1 ";
         fmc="C =  R B1  R FF  R1 B  R FF  RR ";
         fmd="D =  R  U1  R  U  R  U  R  U1 ";
         fmd1="        R1  U1  RR";   
     if (x>640&&x<720&&y>650&&y<720){
         uf=uf+1;    }
         if (uf>1) uf=0;   
        cs.SetColor (255,80,80,80) ;    //clear text
        cs.DrawRect (485, 525, 710, 625) ;    
        cs.DrawRect (667, 210, 685, 325) ;    
        cs.DrawRect (667, 380, 685, 520) ;    
    if (uf==1) {
         cs.SetColor (255,250,250,250) ;
         cs.SetTextSize (16);
         cs.DrawText (fma,490,540);
         cs.DrawText (fmb,490,560);
         cs.DrawText (fmc,490,580);
         cs.DrawText (fmd,490,600);    
         cs.DrawText (fmd1,490,620);      }  

      cs.DrawCircle (675,220,5);   //A
      cs.DrawCircle (675,300,5);   //B
      cs.DrawCircle (675,400,5);   //C
      cs.DrawCircle (675,480,5);   //D
      cs.DrawText ("A",670,245);
      cs.DrawText ("B",670,325);   
      cs.DrawText ("C",670,425);
      cs.DrawText ("D",670,505);

    if (x>660&&x<720&&y>180&&y<260){
           ms=41;  Formula ();  }    //A
     if (x>660&&x<720&&y>260&&y<340){
           ms=51;  Formula ();  }    //B
     if (x>660&&x<720&&y>380&&y<460){
           ms=53;  Formula ();  }    //C
      if (x>660&&x<720&&y>460&&y<540){
           ms=61;  Formula ();  }    //D

  cs.SetFillMode (1);
cs.Update ();
 //********* get button position x y 
          bx=(int)(x);    
          by=(int)(y);  
      if (bn==1){
            s3="走步: 左上 L '  ";
             Leftup ();        } 
      if (bn==2){
            s3="走步: 左下 L  ";
             Leftdown ();       }
       if (bn==3){
            s3="走步: 右上 R  ";
             Rightup ();          }
      if (bn==4){
            s3="走步: 右下 R '  ";
             Rightdown ();       }
      if (bn==5){
            s3="走步: 上左 U ";
             Upleft ();            }
      if (bn==6){
            s3="走步: 上右 U '  ";
             Upright ();           }
      if (bn==7){
            s3="走步: 前左 F '  ";
             Frontleft ();          }
      if (bn==8){
            s3="走步: 前右 F  ";
             Frontright ();        }
     if (bn==9){
            s3="走步: 后左 B '  ";
             Backleft ();          }
      if (bn==10){
            s3="走步: 后右 B   ";
             Backright ();        }
      if (bn==11){
            s3="走步: 下左 D ' ";
             Downleft ();          }
      if (bn==12){
            s3="走步: 下右 D  ";
             Downright ();        }
       if (bn==13){
            s3="走步: 左旋转  ";
             Turnleft ();        }
       if (bn==14){
            s3="走步: 右旋转  ";
             Turnright ();        }
       if (bn==15){
            s3="走步: 翻转  ";
             Turnup ();        }
 }  //screen touch and select button ********

           cs.SetFillMode (1);
    cs.SetColor(255,240,240,240); 
    cs.DrawRect (0,3,700,30);  // clear print x y
    s=intToString(bn);
         s4="按钮(bn) > "+s;
    s=intToString(bx);
         s1="X= "+s;
    s=intToString(by);
         s2="Y= "+s;    
   cs.SetColor (255,50,20,120);
      cs.SetTextSize (26);
     // cs.DrawText (s1,25,25);
     // cs.DrawText (s2,120,25);
     // cs.DrawText (s4,220,25);
      cs.DrawText (s3,445,25);
      cs.Update ();
      checkfinished ();
}//mycanvasProc ()
 //***************************************

Autoplay (){
      clearOutput ();
      print "User select >>>   自动演示";
      newgame ();
      Astep1 ();    //上层四棱
      //sleep (1000);
      Astep2 ();    //上层四角
      //sleep (1000);
          Turnup ();  Turnup ();
      //sleep (1000);
      Astep3 ();    //二层四棱
      //sleep (1000);
      Astep4 ();    //顶层十字
      //sleep (1000);
      Astep5 ();    //顶面同色
      //sleep (1000);
      Astep6 ();    //六面同色
 }//Autoplay ()

Formula (){
  //界面设置四公式操作,可直接使用公式
      if (ms==41){ goto ms41;  }   //公式 A
      if (ms==51){ goto ms51;  }   //公式 B
      if (ms==53){ goto ms53;  }   //公式 C
      if (ms==61){ goto ms61;  }   //公式 D

 ms41:   //顶层十字
     //fma= A:R1  U1  F1    U  F  R 
          print "公式 A ";
          Rightdown ();   Upright ();   Frontleft ();  
          Upleft ();   Frontright ();   Rightup ();
           return;     //************

ms51:   //顶面同色:同色
    //fmb= B:R  U  R1  U  R   U U   R1
           print "公式 B ";
           Rightup ();  Upleft ();  Rightdown ();
           Upleft ();  Rightup ();
           Upleft ();  Upleft ();  Rightdown ();
            return;     //************

ms53:   //顶面同色:调整角块
    //fmc= C:R  B1  R  FF  R1  B  R  FF   RR 
          print "公式 C";
          Rightup ();  Backleft ();        //R  B1
          Rightup ();  Frontright ();  Frontright ();  //R  FF
          Rightdown ();  Backright ();     //R1  B
          Rightup ();  Frontright ();  Frontright ();  //R  FF
          Rightup ();   Rightup ();        //RR
          return;   //顶面同色 ************* 

ms61:       //六面同色:完成
  //fmd= D:R  U1  R  U  R  U  R  U1  R1  U1  RR
           print "公式 D "

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值