拉登游戏开发--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#版的部分代码程序较为简单,主要立足解决分布式问题。
游戏算是成功的开发完了,而且这个游戏是没有终结点的。因为任何人在每一步都走对的情况下都没法通过鼠标点击走到N=32的情况去,甚至更小。这算是一个探讨分布式计算的一个非常好的实例。
本文出自 “野马红尘” 博客,谢绝转载!
拉登游戏的游戏思路是:
一个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的情况去,甚至更小。这算是一个探讨分布式计算的一个非常好的实例。
本文出自 “野马红尘” 博客,谢绝转载!
相关文章推荐
- Silverlight C# 游戏开发:方向键的组合,八方向实现
- C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(四)实现2D人物动画①
- C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(八) 完美实现A*寻径动态动画
- C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(十一)地图遮罩层的实现
- ArcGIS C#插件式开发总结1——编辑过程自动保存插件(Button实现)
- C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(八) 完美实现A*寻径动态动画
- 【Unity游戏开发】用C#和Lua实现Unity中的事件分发机制EventDispatcher
- C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(四)实现2D人物动画①
- 数独游戏设计与实现之第三篇——项目开发的过程
- C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(四)实现2D人物动画①
- C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(十一)地图遮罩层的实现
- C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(十一)地图遮罩层的实现
- 《游戏设计、原型与开发——基于Unity与C#从构思到实现》学习笔记一
- C#开发WPF/Silverlight动画及游戏系列教程(Game Course):(四)实现2D人物动画①
- C# 游戏开发中使用 Dictionary 实现消息分发
- C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(四)实现2D人物动画①
- C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(五)实现2D人物动画②
- C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(五)实现2D人物动画②
- C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(五)实现2D人物动画②
- Silverlight C# 游戏开发:方向键的组合,八方向实现