让我出去-一个简单的棋盘游戏(译文)
By robot-v1.0
本文链接 https://www.kyfws.com/games/let-me-out-a-simple-board-game-zh/
版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
- 7 分钟阅读 - 3146 个词 阅读量 0让我出去-一个简单的棋盘游戏(译文)
原文地址:https://www.codeproject.com/Articles/67570/Let-Me-Out-A-Simple-Board-Game
原文作者:Yangyong Qin
译文由本站 robot-v1.0 翻译
前言
A simple board game
一个简单的棋盘游戏
介绍(Introduction)
“让我出去"是一种棋盘游戏,其目标是将最大的洋红色块从顶部的中间移动到底部的中间.您需要移动其他块并为大个子腾出空间.游戏分为初学者,中级和专家3级.您可以从菜单中更改级别.(“Let Me Out” is a board game with the goal to move the magenta block, the biggest one, from the middle of the top to the middle of the bottom. You need to move other blocks and make room for the big guy. The game has 3 levels, beginner, intermediate, and expert. You can change the levels from the menu.)
该软件的神奇之处在于它只有2个主要类别,(The amazing thing about this software is that it only has 2 main classes,) Block
和(and) Board
.而且代码很简单.因此,我认为对于初学者来说学习面向对象编程是一件好事.或者,希望可以爱上游戏开发. :)关于它的另一件有趣的事情是UI设计.我看到了很多棋盘游戏,用户需要拖放或使用几个步骤来移动项目.这是因为要让一件物品移动,用户需要告知它要移动以及要移动到哪里.该游戏使用箭头显示块移动的方向,该方向随鼠标移动而变化.由于用户已经有了指示,因此她/他只需要单击一下即可.(. And the code is very simple. So, I think it is good for beginners to learn Object-Oriented programming. Or, hopefully fall in love with game developing. :) Another interesting thing about it is the UI design. I saw a lot of board games in which the user needs to either drag-and-drop or use several steps to move an item. That’s because to let an item move, the user needs to tell it to move and where to move. This game uses an arrow to show the direction that a block will be moved, which changes with the mouse movement. Since the user already has the direction, all she/he needs to do is just one click.)
在继续阅读之前,我建议您玩游戏并玩得开心.您可能需要将级别更改为"初学者"以熟悉用户界面.(Before you continue reading, I suggest that you play the game and have fun. You may want to change the level to Beginner to get familiar with the user interface.)
背景(Background)
这是具有一千多年历史的中文游戏.这是一场伟大的战斗.输掉这场战斗的那个家伙竭尽全力逃脱,这几乎是不可能的.但是他做到了. 2x2正方形(洋红色)代表试图逃离的人.如果您玩过游戏,您将理解为什么它"几乎不可能”.(This is a Chinese game with a thousand years of history. It’s about a great battle. The guy who lost the battle tried his best to escape, which was almost impossible. But he did it. The 2x2 square, the magenta one, represents the guy who tried to escape. If you have played the game, you will understand why it is “almost impossible”.)
使用代码(Using the Code)
Block
类继承自(class inherits from) Button
类,以便可以单击它.它的样式已更改为平面,因此看起来更像是块.由于我们将在代码中添加块到板上,因此我们使用属性装饰类(class, so that it can be clicked. Its style is changed to flat, so that it looks more like a block. Since we will add blocks to board in code, we decorate the class with the attribute) ToolboxItem(false)
,这使其无法显示在Visual Studio工具箱窗口中.(, which prevents it from showing in the Visual Studio Toolbox window.)
[ToolboxItem(false)]
public class Block : Button {
...
}
Block
课程负责记住其大小和位置.当鼠标悬停在其上方时,将显示一个箭头.并且箭头将随着鼠标移动而改变方向.我们将在" UI设计"部分中详细讨论这一点.(class is responsible for remembering its size and position. When mouse is over it, an arrow will be shown. And the arrow will change direction with the mouse movement. We will talk more about this in UI Design section.)
木板分为4 x 5正方形,如下所示:(Board is divided to 4 x 5 squares as shown below:)
Board
课堂负责记住方块的状态,方块的状态可以是占用的也可以是空闲的.它还负责移动块.要移动方块,(class is responsible for remembering the status of the squares, which can be either occupied or free. It is also responsible for moving blocks. To move a block, the) Board
类检查是否(class checks whether the) Block
可以移动.(can be moved.) Board
知道,因为它具有每个正方形的记录.通过询问(knows that because it has the record of each square. By asking) Block
类,它知道位置和大小(class, it knows the position, and size of the) Block
,以及直接移动的位置,以便它可以确定(, and the direct to move, so that it can decide whether the) Block
可以移动.如果是,则(can be moved. If yes, the) Block
更新其位置,然后(updates its position, and the) Board
更新其状态.以下是将块向左移动的代码.这是一种方法(updates its status. The following is the code to move a block to left. It’s a method in) Board
类:(class:)
void MoveLeft(Block block) {
int oldX = block.X;
if (oldX == 0) return;
int newX = oldX - 1;
//Check whether we can move the block
for (int i = block.Y; i < block.Y + block.YSpan; ++i) {
if (_occupied[newX, i]) return;
}
//Move it
block.MoveBlock(newX, block.Y);
//Change board status
for (int i = block.Y; i < block.Y + block.YSpan; ++i) {
_occupied[newX + block.XSpan, i] = false;
_occupied[newX, i] = true;
}
//Add step
_steps++;
}
前两行检查块是否已经在最左侧.如果是,则不能再向左移动,程序返回. “(The first 2 lines check whether block is already in the left most. If yes, it cannot be moved left further, and program returns. “) newX
“是块的x位置(如果已移动).要了解其后的代码,我们需要弄清楚该块的属性(” is the x position of the block if it has been moved. To understand the codes after, we need to make clear the properties of the) Block
类.让我们举个例子.在游戏开始时,大个子在(1,0).在这种情况下,(class. Let’s use an example. In the beginning of the game, the big guy is at (1, 0). In this case,) block.X = 1
,(,) block.Y=0
,(,) block.YSpan=2
,这是该块跨越多少行,以及(, which is how many rows the block spans, and) block.XSpan=2
,这是该块跨越多少列.(, which is how many columns the block spans.)
在第一(In the first) for
循环中,我们检查块左侧的正方形是否全部空闲.如果有任何正方形被占用,则该块将无法移动,程序将立即返回.对于大人物示例,如果我们想将其向左移动,则需要检查(0,0)和(1,0)的状态.(loop, we check whether the squares left to the block are all free. If any of the squares is occupied, the block cannot be moved, and the program returns immediately. For the big guy example, If we want to move it left, we need to check the status of (0,0) and (1,0).)
第二(The second) for
循环会更改板的状态.如果大个子从(1,0)移到(0,0),我们需要更改(0,0),(1,0)的状态,以及(2,0),(2, 1)免费.(loop changes the board status. If the big guy moved from (1,0) to (0,0), we need to change the status of (0,0), (1,0) to be occupied, and (2, 0), (2,1) to be free.)
UI设计(UI Design)
在此程序中,我们使用箭头显示方向并单击以触发移动来移动块.为了实现这一目标,我们将块划分为四个区域,如下所示:(In this program, we move the blocks by using an arrow to show directions and a click to trigger the movement. To achieve this, we divided the block into 4 regions, like the one below:)
当鼠标移到左侧区域时,该块的图像将更改为向左箭头.其他区域都具有对应的图像,并且行为相同.(When mouse is moved to the left region, the image for the block is changed to a Left arrow. Other regions all have corresponding images, and behave the same way.)
为了获得每个区域的功能,需要一些几何知识.基本上,您需要了解2行的功能.其中之一通过点(0,0)和(w,h),因此线为y =(h/w)* x.另一个通过(w,0)和(0,h),所以线是y =h-(h/w)* x.(*To get the functions for each region needs some knowledge of geometry. Basically, you need to know the functions for 2 lines. One of them passes the point (0,0) and (w, h), so the line is y=(h/w)*x. The other one passes (w, 0) and (0, h), so the line is y=h-(h/w)*x.*)
代码在下面,它在(*The code is below, it is in*) Block
类(*class, for*) MouseMove
事件:(*event:*)
void Block_MouseMove(object sender, MouseEventArgs e) {
int x = e.X;
int y = e.Y;
int h = this.Height;
int w = this.Width;
double k = (double)h / (double)w;
int newIndex = -2;
int kx = (int)(k * x + 0.5);
if (y < h - kx) {
if (y < kx) {
newIndex = Direction_Up;
} else if (y > kx) {
newIndex = Direction_Left;
}
} else if (y > h - kx) {
if (y < kx) {
newIndex = Direction_Right;
} else if (y > kx) {
newIndex = Direction_Down;
}
}
if (newIndex >= 0 && _direction != newIndex) {
this.Image = Button_Images[newIndex];
_direction = newIndex;
}
}
}
Button_Images
是一个(is a) static
4张图片的数组.图像来自项目资源.(array of 4 images. The images come from project resource.)
下一步是什么(What’s Next)
通过执行以下操作可以改进此程序:(This program can be improved by doing the following:)
- 保存/加载程序(Save/Load Program)
- 游戏解算器(Game Solver) 保存和加载可以通过将每个块的位置保存到XML文件中来完成.用户已移动的总步骤也应保存.不需要保存板的状态,因为在加载时,我们可以重新建立板的状态.(Save and load can be done by saving each block’s position into an XML file. The total steps that the user has moved should also be saved. Board’s status doesn’t need to be saved because when loading, we can re-establish the board status.) 之所以可以使用"游戏求解器”,是因为在每个游戏状态下,没有太多的可能动作.如果我发现有人喜欢这个游戏,我想写一个游戏求解器.(Game Solver is possible because in each game state, there are not many possible moves. I’d like to write a game solver if I find that people like this game.)
历史(History)
- 1.0版(2010年3月14日)(Version 1.0 on March 14, 2010)
- 在2010年3月21日添加了更多文档(Added more documents on March 21, 2010)
许可
本文以及所有相关的源代码和文件均已获得The Code Project Open License (CPOL)的许可。
C# C#3.0 .NET Windows Dev 新闻 翻译