拉登游戏开发--C#实现过程

     关于这个游戏的创意和较为深入的研究来自于新浪博客大力水手。

     拉登游戏的游戏思路是:

     一个N*N的方格,每个格子的有两种颜色状态(黑色,黄色);初始时所有格子为同一种颜色(比如:黑色),通过点击其中的一个格子,该格子以及其上下左右的格子的颜色将变为相反的颜色(之前黑色,之后黄色;反之亦然)。

    如下面六张图可以看到整个游戏的玩法

 拉登游戏开发--C#实现过程_第1张图片 拉登游戏开发--C#实现过程_第2张图片 拉登游戏开发--C#实现过程_第3张图片 拉登游戏开发--C#实现过程_第4张图片

拉登游戏开发--C#实现过程_第5张图片 拉登游戏开发--C#实现过程_第6张图片

   游戏开发过程考虑的几个问题:

  1.生成的N*N格子的应该自适应Window

  2.点击格子四周的格子的边界问题处理

  3.格子的颜色变化设置

  4.判断所有格子颜色是否发生改变

  5.如何实现自动完成功能

   游戏开发的关键就在于这个自动完成的算法实现。

   算法:

      格子共有N*N个,共N行N列,自动完成基于第一行的实现,每一个格子的状态只有两种,设为0或1.

   1.第0行有N个格子,每个格子共有2中状态,全排列共有Pow(2, N)中情况。

   2.给每一种情况进行编号[0,Pow(2,N))

    如下图3*3的格子,第0行的格子的状态:

拉登游戏开发--C#实现过程_第7张图片

      分析:第0行的状态共有Pow(2,N)中,接下来对第1行至第N-1一行进行遍历,每一行有N个格子进行点击处理,这样时间复杂度上升为:Pow(2, N)*Pow(N, 2)。如果N为32的时候,就仅仅让计算机走完这个数,Java中Integer.MAX_VALUE尝试了一下没有等到这个数就给Stop了。

      具大力水手的说法,目前通过分布式计算,已经完成到了N=35。每一种贴下来的图都是一幅美丽的图片(这个得仔细想象加观察)

     下面贴一张图:

拉登游戏开发--C#实现过程_第8张图片

   下面是C#版的部分代码程序较为简单,主要立足解决分布式问题。

 
  
  
  
  
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.ComponentModel;  
  4. using System.Data;  
  5. using System.Drawing;  
  6. using System.Text;  
  7. using System.Windows.Forms;  
  8. using System.Threading;  
  9.  
  10. namespace OkLight  
  11. {  
  12.     public partial class FormMain : Form  
  13.     {  
  14.         Button[] btns = new Button[25];  
  15.         //设置两个全局的数组变量  
  16.         static int[] states;  
  17.         static int[] operaters;  
  18.         //设置一个全局变量用来计算点击的次数  
  19.         static int count = 0;  
  20.  
  21.         //构造方法初始化组件  
  22.         public FormMain()  
  23.         {  
  24.             InitializeComponent();  
  25.         }  
  26.  
  27.         //初始化下拉菜单的选项值  
  28.         private void FormMainLoad(object sender, EventArgs e)  
  29.         {    
  30.               
  31.             int min = panelMain.Height;  
  32.             if (min > panelMain.Width)  
  33.             {  
  34.                 min = panelMain.Width;  
  35.             }  
  36.             int maxNumber = min / 40;  
  37.             for (int i = 1; i < maxNumber + 1; i++)  
  38.             {  
  39.                 comboBoxIndex.Items.Add(i);  
  40.             }  
  41.             comboBoxIndex.SelectedIndex = 4;  
  42.             InitalButton((int)comboBoxIndex.SelectedItem);  
  43.         }  
  44.  
  45.         //初始按钮  
  46.         private void InitalButton(int number)  
  47.         {  
  48.             panelMain.Controls.Clear();  
  49.              //获得面板的大小  
  50.             int x = (panelMain.Width - number*40) / 2;  
  51.             int y = (panelMain.Height - number * 40) / 2;  
  52.             btns = new Button[number * number];  
  53.  
  54.             //实例化按钮并且添加到面板中去  
  55.             for (int i = 0; i < number*number; i++)  
  56.             {  
  57.                 btns[i] = new Button();  
  58.                 btns[i].Width = 40;  
  59.                 btns[i].Height = 40;  
  60.                 //设置按钮的位置  
  61.                 btns[i].Left = x + (i % number) * 40;  
  62.                 btns[i].Top = y + (i / number) * 40;  
  63.                 //设置按钮表面的颜色  
  64.                 btns[i].BackColor = Color.Black;  
  65.                 //为每一个按钮注册单击处理  
  66.                 btns[i].Click += new EventHandler(FormMainClick);  
  67.                 panelMain.Controls.Add(btns[i]);  
  68.             }  
  69.  
  70.         }  
  71.  
  72.         //格子事件方法  
  73.         void FormMainClick(object sender, EventArgs e)  
  74.         {  
  75.             int number = (int)comboBoxIndex.SelectedItem;  
  76.             Button btn = sender as Button;  
  77.             //获得面板的大小  
  78.             int x = (panelMain.Width - 40*number) / 2;  
  79.             int y = (panelMain.Height - 40*number) / 2;  
  80.             //得到按钮的索引  
  81.             int i = (btn.Left - x) / 40;  
  82.             int j = (btn.Top - y) / 40;  
  83.             //得到当前单击的按钮的上下左右按钮的坐标  
  84.             int top = j - 1;  
  85.             int buttoom = j + 1;  
  86.             int left = i - 1;  
  87.             int right = i + 1;  
  88.             count++;  
  89.             ChangeButtonColor(btn);  
  90.             if (top >= 0)  
  91.             {  
  92.                 int index = i + number * top;  
  93.                 ChangeButtonColor(btns[index]);  
  94.             }  
  95.             if (buttoom < number)  
  96.             {  
  97.                 int index = i + number * buttoom;  
  98.                 ChangeButtonColor(btns[index]);  
  99.             }  
  100.             if(left>=0)  
  101.             {  
  102.                 int index = left + number * j;  
  103.                 ChangeButtonColor(btns[index]);  
  104.             }  
  105.             if (right < number)  
  106.             {  
  107.                 int index = right + number * j;  
  108.                 ChangeButtonColor(btns[index]);  
  109.             }  
  110.             showLabel.Text = "您当前已经点击次数为: " + count;  
  111.             if (IsSucceed(number))  
  112.             {  
  113.                DialogResult dr=MessageBox.Show("恭喜你,成功完成""消息");  
  114.             }  
  115.         }  
  116.  
  117.         //改变格子背景颜色  
  118.         private void ChangeButtonColor(Button btn)  
  119.         {  
  120.             if (btn.BackColor == Color.Black)  
  121.             {  
  122.                 btn.BackColor = Color.Yellow;  
  123.             }  
  124.             else 
  125.             {  
  126.                 btn.BackColor = Color.Black;  
  127.             }  
  128.             btn.Refresh();  
  129.  
  130.         }  
  131.  
  132.         //演示游戏  
  133.         private void GetShow(int number)  
  134.         {  
  135.             //设置方格的边的个数  
  136.             //计算格子的总个数  
  137.             int count = (int)Math.Pow(number, 2);  
  138.             //初始化数组的值  
  139.             //计算一共有多少种情况,number=5是32种情况  
  140.             //operaters数组中放的是每一种情况的每一个格子的操作取值  
  141.             //states数组中放的是每一种情况的每一个格子的状态取值  
  142.             //在计算过程中不一定将for语句运行完,当判断states[]的值全为1便可以终止  
  143.             for (int i = 0; i < (int)Math.Pow(2, number); i++)  
  144.             {  
  145.                 states = new int[count];  
  146.                 operaters = new int[count];  
  147.                 int x = i;//i表示第几种情况  
  148.                 int j = 0;  
  149.                 //进行第i种情况的operaters的赋值  
  150.                 while (true)  
  151.                 {  
  152.                     if (x == 0)  
  153.                     {  
  154.                         break;  
  155.                         //当x=0的时候跳出while循环  
  156.                     }  
  157.                     //将x转换为二进制数0 1  
  158.                     operaters[j] = x % 2;  
  159.                     x = x / 2;  
  160.                     j++;  
  161.                 }  
  162.                 //第i种情况的operaters[]设置完成之后进行操作  
  163.                 //这个操作只进行一行  
  164.                 for (int k = 0; k < number; k++)  
  165.                 {  
  166.                     //operaters[]值为1的时候表示操作  
  167.                     if (operaters[k] == 1)  
  168.                     {  
  169.                         ToClick(k, number);  
  170.                     }  
  171.                 }  
  172.  
  173.                 //对第i种情况下从第2行开始操作直到number行  
  174.                 for (int k = 1; k < number; k++)  
  175.                 {  
  176.                     //对第i种情况下从第k行的每一格格子开始操作  
  177.                     for (int m = 0; m < number; m++)  
  178.                     {  
  179.                         //判断k-1行第m格格子的状态  
  180.                         //在进行操作的时候,只点击上一行状态没有改变的格子对应下面的格子  
  181.                         //Console.Write(states[(k - 1) * number + m]);  
  182.                         if (states[(k - 1) * number + m] == 0)  
  183.                         {  
  184.                             //一旦将格子点击之后,它的操作状态就职位 1;  
  185.                             operaters[k * number + m] = 1;  
  186.                             ToClick(k * number + m, number);  
  187.                         }  
  188.  
  189.                     }  
  190.                 }  
  191.                 //通过计算可以判断是否已经完成操作  
  192.                 int statesCount = 0;  
  193.                 for (int k = 0; k < states.Length; k++)  
  194.                 {  
  195.                     if (states[k] == 1)  
  196.                     {  
  197.                         statesCount++;  
  198.                     }  
  199.                 }  
  200.                 //states[]的值和为count表明完成操作  
  201.                 if (statesCount == count)  
  202.                 {  
  203.                     break;  
  204.                 }  
  205.  
  206.             }  
  207.  
  208.         }  
  209.  
  210.         //判断游戏是否结束  
  211.         private bool IsSucceed(int number)  
  212.         {  
  213.             bool result = false;  
  214.             for (int i = 0, j = number * number; i < j; i++)  
  215.             {  
  216.                 if (btns[i].BackColor == Color.Black)  
  217.                 {  
  218.                     result = false;  
  219.                     break;  
  220.                 }  
  221.                 else 
  222.                 {  
  223.                     result = true;  
  224.                 }  
  225.             }  
  226.             return result;  
  227.         }  
  228.  
  229.         //下拉菜单改变信息  
  230.         private void SelectedIndexChanged(object sender, EventArgs e)  
  231.         {  
  232.             int number = (int)comboBoxIndex.SelectedItem;  
  233.             count = 0;  
  234.             showLabel.Text = "您当前已经点击次数为:";  
  235.             InitalButton(number);  
  236.         }  
  237.  
  238.         //点击格子事件  
  239.         private static void ToClick(int tag, int number)  
  240.         {  
  241.             //tag表示从操作中传递的值,它是格子从  [0-number*number)  的编号  
  242.             //计算行号  
  243.             int j = tag / number;  
  244.             //计算列号  
  245.             int i = tag % number;  
  246.             int left = i - 1;  
  247.             int right = i + 1;  
  248.             int top = j - 1;  
  249.             int buttom = j + 1;  
  250.             ChangeButtonStates(tag);  
  251.             if (left >= 0)  
  252.             {  
  253.                 ChangeButtonStates(left + number * j);  
  254.             }  
  255.             if (right < number)  
  256.             {  
  257.                 ChangeButtonStates(right + number * j);  
  258.             }  
  259.             if (top >= 0)  
  260.             {  
  261.                 ChangeButtonStates(i + number * top);  
  262.             }  
  263.             if (buttom < number)  
  264.             {  
  265.                 ChangeButtonStates(i + number * buttom);  
  266.             }  
  267.         }  
  268.  
  269.         //设置格子状态  
  270.         private static void ChangeButtonStates(int index)  
  271.         {  
  272.             if (states[index] == 0)  
  273.             {  
  274.                 states[index] = 1;  
  275.             }  
  276.             else 
  277.             {  
  278.                 states[index] = 0;  
  279.             }  
  280.         }  
  281.  
  282.         //游戏演示按钮事件  
  283.         private void BtnShowClick(object sender, EventArgs e)  
  284.         {  
  285.             int number = (int)comboBoxIndex.SelectedItem;  
  286.             GetShow(number);  
  287.             for(int i = 0; i < operaters.Length;i++)  
  288.             {  
  289.                if(operaters[i]==1)  
  290.                {  
  291.                    btns[i].PerformClick();  
  292.                    Thread.Sleep(1000);  
  293.                }  
  294.             }  
  295.         }  
  296.     }  
  297.       

      游戏算是成功的开发完了,而且这个游戏是没有终结点的。因为任何人在每一步都走对的情况下都没法通过鼠标点击走到N=32的情况去,甚至更小。这算是一个探讨分布式计算的一个非常好的实例。

本文出自 “野马红尘” 博客,谢绝转载!

你可能感兴趣的:(C#,游戏开发,算法实现)