您的位置:首页 > 编程语言 > C#

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

2012-11-28 18:41 537 查看
关于这个游戏的创意和较为深入的研究来自于新浪博客大力水手。

拉登游戏的游戏思路是:

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

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

















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

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行的格子的状态:





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

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

下面贴一张图:





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

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace OkLight
{
public partial class FormMain : Form
{
Button[] btns = new Button[25];
//设置两个全局的数组变量
static int[] states;
static int[] operaters;
//设置一个全局变量用来计算点击的次数
static int count = 0;

//构造方法初始化组件
public FormMain()
{
InitializeComponent();
}

//初始化下拉菜单的选项值
private void FormMainLoad(object sender, EventArgs e)
{

int min = panelMain.Height;
if (min > panelMain.Width)
{
min = panelMain.Width;
}
int maxNumber = min / 40;
for (int i = 1; i < maxNumber + 1; i++)
{
comboBoxIndex.Items.Add(i);
}
comboBoxIndex.SelectedIndex = 4;
InitalButton((int)comboBoxIndex.SelectedItem);
}

//初始按钮
private void InitalButton(int number)
{
panelMain.Controls.Clear();
//获得面板的大小
int x = (panelMain.Width - number*40) / 2;
int y = (panelMain.Height - number * 40) / 2;
btns = new Button[number * number];

//实例化按钮并且添加到面板中去
for (int i = 0; i < number*number; i++)
{
btns[i] = new Button();
btns[i].Width = 40;
btns[i].Height = 40;
//设置按钮的位置
btns[i].Left = x + (i % number) * 40;
btns[i].Top = y + (i / number) * 40;
//设置按钮表面的颜色
btns[i].BackColor = Color.Black;
//为每一个按钮注册单击处理
btns[i].Click += new EventHandler(FormMainClick);
panelMain.Controls.Add(btns[i]);
}

}

//格子事件方法
void FormMainClick(object sender, EventArgs e)
{
int number = (int)comboBoxIndex.SelectedItem;
Button btn = sender as Button;
//获得面板的大小
int x = (panelMain.Width - 40*number) / 2;
int y = (panelMain.Height - 40*number) / 2;
//得到按钮的索引
int i = (btn.Left - x) / 40;
int j = (btn.Top - y) / 40;
//得到当前单击的按钮的上下左右按钮的坐标
int top = j - 1;
int buttoom = j + 1;
int left = i - 1;
int right = i + 1;
count++;
ChangeButtonColor(btn);
if (top >= 0)
{
int index = i + number * top;
ChangeButtonColor(btns[index]);
}
if (buttoom < number)
{
int index = i + number * buttoom;
ChangeButtonColor(btns[index]);
}
if(left>=0)
{
int index = left + number * j;
ChangeButtonColor(btns[index]);
}
if (right < number)
{
int index = right + number * j;
ChangeButtonColor(btns[index]);
}
showLabel.Text = "您当前已经点击次数为: " + count;
if (IsSucceed(number))
{
DialogResult dr=MessageBox.Show("恭喜你,成功完成", "消息");
}
}

//改变格子背景颜色
private void ChangeButtonColor(Button btn)
{
if (btn.BackColor == Color.Black)
{
btn.BackColor = Color.Yellow;
}
else
{
btn.BackColor = Color.Black;
}
btn.Refresh();

}

//演示游戏
private void GetShow(int number)
{
//设置方格的边的个数
//计算格子的总个数
int count = (int)Math.Pow(number, 2);
//初始化数组的值
//计算一共有多少种情况,number=5是32种情况
//operaters数组中放的是每一种情况的每一个格子的操作取值
//states数组中放的是每一种情况的每一个格子的状态取值
//在计算过程中不一定将for语句运行完,当判断states[]的值全为1便可以终止
for (int i = 0; i < (int)Math.Pow(2, number); i++)
{
states = new int[count];
operaters = new int[count];
int x = i;//i表示第几种情况
int j = 0;
//进行第i种情况的operaters的赋值
while (true)
{
if (x == 0)
{
break;
//当x=0的时候跳出while循环
}
//将x转换为二进制数0 1
operaters[j] = x % 2;
x = x / 2;
j++;
}
//第i种情况的operaters[]设置完成之后进行操作
//这个操作只进行一行
for (int k = 0; k < number; k++)
{
//operaters[]值为1的时候表示操作
if (operaters[k] == 1)
{
ToClick(k, number);
}
}

//对第i种情况下从第2行开始操作直到number行
for (int k = 1; k < number; k++)
{
//对第i种情况下从第k行的每一格格子开始操作
for (int m = 0; m < number; m++)
{
//判断k-1行第m格格子的状态
//在进行操作的时候,只点击上一行状态没有改变的格子对应下面的格子
//Console.Write(states[(k - 1) * number + m]);
if (states[(k - 1) * number + m] == 0)
{
//一旦将格子点击之后,它的操作状态就职位 1;
operaters[k * number + m] = 1;
ToClick(k * number + m, number);
}

}
}
//通过计算可以判断是否已经完成操作
int statesCount = 0;
for (int k = 0; k < states.Length; k++)
{
if (states[k] == 1)
{
statesCount++;
}
}
//states[]的值和为count表明完成操作
if (statesCount == count)
{
break;
}

}

}

//判断游戏是否结束
private bool IsSucceed(int number)
{
bool result = false;
for (int i = 0, j = number * number; i < j; i++)
{
if (btns[i].BackColor == Color.Black)
{
result = false;
break;
}
else
{
result = true;
}
}
return result;
}

//下拉菜单改变信息
private void SelectedIndexChanged(object sender, EventArgs e)
{
int number = (int)comboBoxIndex.SelectedItem;
count = 0;
showLabel.Text = "您当前已经点击次数为:";
InitalButton(number);
}

//点击格子事件
private static void ToClick(int tag, int number)
{
//tag表示从操作中传递的值,它是格子从  [0-number*number)  的编号
//计算行号
int j = tag / number;
//计算列号
int i = tag % number;
int left = i - 1;
int right = i + 1;
int top = j - 1;
int buttom = j + 1;
ChangeButtonStates(tag);
if (left >= 0)
{
ChangeButtonStates(left + number * j);
}
if (right < number)
{
ChangeButtonStates(right + number * j);
}
if (top >= 0)
{
ChangeButtonStates(i + number * top);
}
if (buttom < number)
{
ChangeButtonStates(i + number * buttom);
}
}

//设置格子状态
private static void ChangeButtonStates(int index)
{
if (states[index] == 0)
{
states[index] = 1;
}
else
{
states[index] = 0;
}
}

//游戏演示按钮事件
private void BtnShowClick(object sender, EventArgs e)
{
int number = (int)comboBoxIndex.SelectedItem;
GetShow(number);
for(int i = 0; i < operaters.Length;i++)
{
if(operaters[i]==1)
{
btns[i].PerformClick();
Thread.Sleep(1000);
}
}
}
}

}

游戏算是成功的开发完了,而且这个游戏是没有终结点的。因为任何人在每一步都走对的情况下都没法通过鼠标点击走到N=32的情况去,甚至更小。这算是一个探讨分布式计算的一个非常好的实例。
本文出自 “野马红尘” 博客,谢绝转载!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐