65.9K
CodeProject 正在变化。 阅读更多。
Home

Windows Mobile 版 Reversi

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.86/5 (4投票s)

2009 年 5 月 13 日

CPOL

3分钟阅读

viewsIcon

28913

downloadIcon

565

使用 Compact Framework 开发的 Windows Mobile 版黑白棋游戏。

引言

我们将使用 C# 和 .NET Compact Framework 3.5 为 Windows Mobile 创建一个黑白棋游戏克隆。Compact Framework 是 .NET Framework 的一个子集,用于运行 Windows CE 的设备。使用 Compact Framework 开发应用程序与开发普通 Windows 应用程序的方式非常相似。 使用 CF,整个应用程序在几个小时内就完成了编写。

背景

黑白棋是一个古老的游戏,由 Lewis Waterman 于 1883 年创建。游戏在 8x8 的棋盘上进行,棋盘上有 64 个棋子,一面是黑色,一面是白色。游戏开始时,棋盘中心有 4 个棋子,两个黑色和两个白色。每个玩家轮流将棋子放在棋盘上。只有当移动有效时,玩家才能将棋子放在棋盘上。要使移动有效,必须有一个相邻的敌方棋子,并且在它后面有一条直线上的另一个玩家棋子。该线上的所有敌方棋子都会被翻转,并属于进行移动的玩家。下图显示了所有可能的黑色移动和受影响的棋子。

ReversiGame/ReversiMoves2.jpg

如果棋盘上没有有效的移动,则可以跳过玩家。游戏一直进行到棋盘被填满或双方玩家都没有有效的移动为止。棋盘上棋子最多的玩家获胜。您可以从这个 Wikipedia 页面了解更多关于黑白棋的信息:http://en.wikipedia.org/wiki/Reversi

游戏代码

正如您所看到的,黑白棋是一个非常简单的游戏。游戏代码由几个文件组成,大部分操作都在 Game.cs 中。游戏棋盘是一个简单的二维字节数组。数组中的每个字节代表占据该位置的玩家。下面是用于在游戏中移动的方法。该方法采用位置和正在移动的玩家。如果移动成功,则返回 true。如果移动有效,我们将更新棋盘上的位置并设置玩家。

public bool Move(Point position, Player player)
{
    // Not the current players move so ignore.
    if (_currentPlayer != player)
    {
        return false;
    }
    // The move is outside the board.
    if (position.X >= _board.BoardWidth || 
        position.Y >= _board.BoardHeight)
    {
        return false;
    }
    // Already a player in that position.
    if (_board[position.X, position.Y].Player != Player.NotSet)
    {
        return false;
    }
    
    bool validMove = false;

    validMove |= UpdateDirection(position, Direction.East, player);
    validMove |= UpdateDirection(position, Direction.North, player);
    validMove |= UpdateDirection(position, Direction.NorthEast, player);
    validMove |= UpdateDirection(position, Direction.NorthWest, player);
    validMove |= UpdateDirection(position, Direction.South, player);
    validMove |= UpdateDirection(position, Direction.SouthEast, player);
    validMove |= UpdateDirection(position, Direction.SouthWest, player);
    validMove |= UpdateDirection(position, Direction.West, player);
    if (validMove)
    {
        _board[position.X, position.Y] = new Position(player);
        TogglePlayer();
    }
    return validMove;
}

下面是 UpdateDirectionCheckDirection 方法。 UpdateDirection 检查当前移动是否会影响指定方向上的任何单元格。 endpoint 输出参数将具有最后一个受影响单元格的坐标。 UpdateDirection 方法调用 CheckDirection,并将更新从移动位置到 endpoint 位置的直线上的所有单元格。 这三个方法构成了大部分游戏逻辑。

private bool UpdateDirection(Point position, Direction direction, Player player)
{
    IEnumerable<Point> modifiedPositions;
    Point endPoint;

    if (CheckDirection(position, direction, player, out endPoint))
    {
        modifiedPositions = GetPositions(position, endPoint);
        foreach (Point p in modifiedPositions)
        {
            _board[p.X, p.Y] = new Position(player, 0);
        }
        return true;
    }
    return false;
}

public bool CheckDirection(Point point, Direction direction, 
                           Player player, out Point endPoint)
{
    Point directionMod = GetDirectionModifier(direction);
    int xMod = directionMod.X, yMod = directionMod.Y;
    int x = point.X + xMod, y = point.Y + yMod;

    Player otherPlayer = player == Player.PlayerOne ? 
           Player.PlayerTwo : Player.PlayerOne;
    Player currentPlayer;
    bool hasOther = false;

    while (x > -1 && x < _board.BoardWidth &&
            y > -1 && y < _board.BoardHeight)
    {
        // Get the current player.
        currentPlayer = _board[x, y].Player;

        // Got to the end and no match.
        if ( currentPlayer == Player.NotSet )
        {
            break;
        }
        else if ( currentPlayer == otherPlayer )
        {
            hasOther = true;
        }
        else if ( currentPlayer == player )
        {
            if (hasOther)
            {
                endPoint = new Point(x-=xMod, y-=yMod);
                return true;
            }
            endPoint = Point.Empty;
            return false;
        }

        // Move to next position.
        x += xMod;
        y += yMod;
    }
    endPoint = Point.Empty;
    return false;
}

渲染代码

我们使用 GDI 来渲染游戏棋盘。 为了绘制棋盘,我们只需遍历所有棋盘位置,绘制一个正方形,然后如果在当前位置有玩家,则绘制一个黑色或白色圆圈。 我们在后备缓冲区图像上绘制游戏棋盘,然后将该图像绘制到屏幕上。

const float circleReduce = .2F;
// Get the positions and board width,height
Position[] positions = _game.Board.Data;
int boardWidth = _game.Board.BoardWidth, 
    boardHeight = _game.Board.BoardHeight;
Rectangle positionRectangle;
int x = 0, y = 0;

// Draw the background.
TransparentControl.PaintBackground(graphics, _renderArea);

Player player;
for (int i = 0; i < positions.Length; i++)
{
    // Get the position rectangle.
    positionRectangle = new Rectangle(
            x, y,
            (int)(_positionSize.Width),
            (int)(_positionSize.Height));

    // Draw the grid.
    graphics.DrawRectangle(new Pen(Color.Black, 2),
                           positionRectangle);

    // Get the player.
    player = positions[i].Player;
    Rectangle playerPosition = positionRectangle;

    // Render any circles for any positions that are occupied.
    if (player != Player.NotSet)
    {
        playerPosition.Inflate(-(int)(positionRectangle.Width * circleReduce), 
                               -(int)(positionRectangle.Height * circleReduce));
        graphics.FillEllipse(
            new SolidBrush(player == Player.PlayerOne ? Color.Black : Color.White),
            playerPosition
            );
    }

    // Move to next position.
    if (i != 0 && ((i + 1) % boardWidth) == 0)
    {
        x = 0;
        y += (int)_positionSize.Height;
    }
    else
    {
        x += (int)_positionSize.Width;
    }
}

对于输入,我们订阅宿主控件的 OnClick 事件。 然后我们将屏幕坐标转换为棋盘坐标,并在游戏实例上调用 Move 方法。

Point translatedPoint = TranslatePoint(
      _renderArea.PointToClient(Control.MousePosition));

private Point TranslatePoint(Point point)
{
    int x = (int)((point.X) / _positionSize.Width),
        y = (int)((point.Y) / _positionSize.Height);
    return new Point(x, y);
    
}

我没有太多时间来开发 AI。 目前,计算机将进行第一次可用的移动。 以后,也许会实现一些更好的东西。

最新版本的 CF 包含 SoundPlayer 类。 我们使用此类来播放游戏声音。 有四种游戏声音:游戏开始声音、移动声音、无效移动声音和跳过回合声音。 此游戏的声音是使用 sfxr 生成的。 它是一个用于生成视频游戏声音的免费软件应用程序。 如果您需要一些游戏开发的快速声音,我建议您查看一下:http://www.cyd.liu.se/~tompe573/hp/project_sfxr.html

© . All rights reserved.