一、核心架构设计
推箱子游戏的核心模块包括游戏界面 、地图管理 、玩家控制 、碰撞检测 和胜利条件判断。以下是基于C# WinForms的实现框架:
二、关键代码实现
1. 游戏界面与地图初始化
csharp
using System;
using System.Drawing;
using System.Windows.Forms;
public class GameForm : Form
{
private PictureBox[,] mapTiles; // 地图元素
private PictureBox player; // 玩家控件
private int[,] levelData = { // 示例地图(0=空地,1=墙,2=箱子,3=目标点)
{1,1,1,1,1},
{1,0,0,2,1},
{1,0,3,0,1},
{1,0,0,0,1},
{1,1,1,1,1}
};
public GameForm()
{
this.ClientSize = new Size(400, 400);
InitializeMap();
InitializePlayer();
}
private void InitializeMap()
{
mapTiles = new PictureBox[levelData.GetLength(0), levelData.GetLength(1)];
for (int i = 0; i < levelData.GetLength(0); i++)
{
for (int j = 0; j < levelData.GetLength(1); j++)
{
mapTiles[i, j] = new PictureBox();
mapTiles[i, j].Width = 40;
mapTiles[i, j].Height = 40;
mapTiles[i, j].BorderStyle = BorderStyle.FixedSingle;
mapTiles[i, j].Location = new Point(j * 40, i * 40);
UpdateTileAppearance(i, j);
this.Controls.Add(mapTiles[i, j]);
}
}
}
private void UpdateTileAppearance(int x, int y)
{
Color color = Color.White;
if (levelData[x, y] == 1) color = Color.Gray; // 墙
else if (levelData[x, y] == 2) color = Color.Blue; // 箱子
else if (levelData[x, y] == 3) color = Color.Yellow; // 目标点
mapTiles[x, y].BackColor = color;
}
}
2. 玩家控制与移动逻辑
csharp
private PictureBox player;
private int playerX = 1, playerY = 1; // 初始位置
private void InitializePlayer()
{
player = new PictureBox();
player.Width = 30;
player.Height = 30;
player.BackColor = Color.Red;
player.Location = new Point(playerY * 40 + 5, playerX * 40 + 5);
this.Controls.Add(player);
}
protected override void OnKeyDown(KeyEventArgs e)
{
int newX = playerX, newY = playerY;
switch (e.KeyCode)
{
case Keys.Up: newY--; break;
case Keys.Down: newY++; break;
case Keys.Left: newX--; break;
case Keys.Right: newX++; break;
}
if (CheckMove(newX, newY))
{
UpdatePlayerPosition(newX, newY);
CheckWinCondition();
}
}
private bool CheckMove(int newX, int newY)
{
// 边界检测
if (newX < 0 || newX >= levelData.GetLength(1) || newY < 0 || newY >= levelData.GetLength(0))
return false;
int targetTile = levelData[newY, newX];
if (targetTile == 1) return false; // 撞墙
// 箱子推动检测
if (targetTile == 2)
{
int boxNewX = newX + (newX - playerX);
int boxNewY = newY + (newY - playerY);
if (levelData[boxNewY, boxNewX] == 0) // 箱子前方为空地
{
levelData[boxNewY, boxNewX] = 2; // 移动箱子
levelData[newY, newX] = 0; // 清空原位置
}
else return false; // 箱子被堵住
}
// 更新玩家位置
levelData[playerY, playerX] = 0;
playerX = newX;
playerY = newY;
levelData[playerY, playerX] = 3; // 玩家位置标记为目标点
return true;
}
3. 胜利条件判断
csharp
private void CheckWinCondition()
{
bool win = true;
for (int i = 0; i < levelData.GetLength(0); i++)
{
for (int j = 0; j < levelData.GetLength(1); j++)
{
if (levelData[i, j] == 2) // 存在未被推到目标点的箱子
{
win = false;
break;
}
}
if (!win) break;
}
if (win)
{
MessageBox.Show("恭喜通关!");
this.Close();
}
}
三、功能扩展与优化
1. 多关卡支持
- 地图数据存储 :使用外部文件(如JSON)存储关卡布局,通过
File.ReadAllText加载。 - 关卡切换 :在
CheckWinCondition中触发下一关加载逻辑。
2. 动画与音效
- 平滑移动 :通过
Timer控件实现逐帧动画,替代直接坐标跳转。 - 音效反馈 :在玩家移动和推动箱子时播放声音文件(如
System.Media.SoundPlayer)。
3. 状态保存
- 玩家进度 :使用
PlayerPrefs或序列化保存当前关卡、移动步数等数据。
四、完整项目结构
bash
SokobanGame/
├── GameForm.cs // 主窗体与界面逻辑
├── LevelLoader.cs // 关卡加载与解析
├── PlayerController.cs // 玩家移动与碰撞检测
└── Resources/ // 图片、音效资源
参考代码 C#做的一个推箱子的小游戏 www.youwenfan.com/contentcsq/59125.html
五、调试与优化建议
- 碰撞检测优化:通过预计算所有可移动区域,减少实时计算量。
- 内存管理:及时释放未使用的PictureBox控件,避免内存泄漏。
- 输入防抖 :添加
KeyPreview属性和KeyPress事件过滤重复输入。
六、扩展功能示例(多箱子支持)
csharp
// 修改CheckMove方法以支持多个箱子
private bool CheckMove(int newX, int newY)
{
// ...原有边界检测代码...
if (targetTile == 2) // 箱子
{
int boxNewX = newX + (newX - playerX);
int boxNewY = newY + (newY - playerY);
if (levelData[boxNewY, boxNewX] == 0 || levelData[boxNewY, boxNewX] == 3)
{
// 推动箱子到空地或目标点
SwapTiles(playerX, playerY, newX, newY);
SwapTiles(newX, newY, boxNewX, boxNewY);
return true;
}
return false;
}
// ...其他逻辑...
}
private void SwapTiles(int x1, int y1, int x2, int y2)
{
int temp = levelData[y1, x1];
levelData[y1, x1] = levelData[y2, x2];
levelData[y2, x2] = temp;
}
七、运行效果
- 基础操作:使用方向键控制红色玩家移动,推动蓝色箱子至黄色目标点。
- 胜利判定:所有箱子到达目标点后弹出通关提示。