欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

WPF实现2048小游戏

程序员文章站 2023-12-19 16:13:34
        前几天空闲的时候,实现了一个2048游戏。除了可以设置行数和列数之外,支持修...

        前几天空闲的时候,实现了一个2048游戏。除了可以设置行数和列数之外,支持修改显示名称,比如下面,改成神雕侠侣中的角色名称:

WPF实现2048小游戏

        游戏逻辑比较简单,大家都应该玩过。

        这里主要实现了四个类:game、gameboard还有colorblock和boardgridline。

        game类主要用来实现游戏的控制,比如初始化、添加新的色块、移除色块、控制色块上下左右移动、改变积分,触发游戏结束等。

        gameboard继承自canvas,实现了色块的合并、检测每个格子的状态等,另外提供了game控制色块移动的接口。

        colorblock类继承自shape类,用于自定义色块的显示,包含xy坐标、颜色、显示文字等依赖属性,可以进行动画,另外还实现了具体的上下左右移动的方法。最初几个颜色是手动设置,等到色块越来越多,就随机生成一种颜色。

        boardgridline也继承自shape类,用于绘制canvas底部的网格。

        另外,游戏使用一个简单的文本文件保存设置,包括行数与列数,以及显示文字及其对应颜色,具体操作在settings类中。

        最后,按键事件封装在keysnavigation中。

        图标使用expression design制作:

 WPF实现2048小游戏

游戏效果如下:

WPF实现2048小游戏WPF实现2048小游戏

game.cs

using system;
using system.collections.generic;
using system.linq;
using system.text;
using system.windows.documents;

namespace game2048
{
 public class game
 {
  public enum state
  { 
   idel,
   start,
   running,
  }

  colorblock[,] fillstate;
  private int score = 0;
  private int step = 0;


  public colorblock[,] fillstate
  { 
   get
   {
    return fillstate;
   }
  }

  gameboard board;

  public game(gameboard board)
  {
   this.board = board;
   fillstate = new colorblock[board.rowcount, board.columncount];
   for (int i = 0; i < board.rowcount; i++)
   {
    for (int j = 0; j < board.columncount; j++)
    {
     fillstate[i, j] = null;
    }
   }
  }

  public void init()
  {
   settings.load();
   colorblock block = new colorblock(board);
   colorblock block1 = new colorblock(board);
   //fillstate[block.xindex, block.yindex] = block;
   // fillstate[block1.xindex, block1.yindex] = block1;
   //blocklist.add(block);
   //blocklist.add(block1);
  }

  public void addnew()
  {
   if (board.hasnoplace())
   {
    gameover(false);
    return;
   }
   colorblock block = new colorblock(board);
   //fillstate[block.xindex, block.yindex] = block;
   //blocklist.add(block);
  }

  public void remove(int xindex,int yindex)
  {
   if (fillstate[yindex, xindex] != null)
   {
    board.children.remove(fillstate[yindex, xindex]);
    fillstate[yindex, xindex] = null;
   }
  }

  public void toleft()
  {
   bool add = false;
   for (int i = 0; i < board.columncount; i++)
   {
    for (int j = 0; j < board.rowcount; j++)
    {
     if (fillstate[j, i] != null)
     {
      add |= fillstate[j, i].moveleft();
     }
    }
   }
   if (add)
   {
    addnew();
    firesetpchanged();
   }
  }

  public void toright()
  {
   bool add = false;
   for (int i = board.columncount-1; i >=0 ; i--)
   {
    for (int j = 0; j < board.rowcount; j++)
    {
     if (fillstate[j, i] != null)
     {
      add |= fillstate[j, i].moveright();
     }
    }
   }
   if (add)
   {
    addnew();
    firesetpchanged();
   }
  }

  public void toup()
  {
   bool add = false;
   for (int i = 0; i < board.columncount; i++)
   {
    for (int j = 0; j < board.rowcount; j++)
    {
     if (fillstate[j, i] != null)
     {
      add |= fillstate[j, i].moveup();
     }
    }
   }
   if (add)
   {
    addnew();
    firesetpchanged();
   }
  }

  public void todown()
  {
   bool add = false;
   for (int i = 0; i < board.columncount; i++)
   {
    for (int j = board.rowcount-1; j >=0; j--)
    {
     if (fillstate[j, i] != null)
     {
      add |= fillstate[j, i].movedown();
     }
    }
   }
   if (add)
   {
    addnew();
    firesetpchanged();
   }
  }

  public delegate void onscorechange(int score);
  public event onscorechange onscorechangehandler;
  public delegate void onstepchange(int step);
  public event onstepchange onstepchangehandler;
  public delegate void ongameover(bool success);
  public event ongameover ongameoverhandler;

  public void firesetpchanged()
  {
   step++;
   if (onstepchangehandler != null)
    onstepchangehandler(step);
  }

  /// <summary>
  /// 增加积分
  /// </summary>
  /// <param name="offset"></param>
  public void incscore(int offset)
  {
   score += offset;
   if (onscorechangehandler != null)
   {
    onscorechangehandler(score);
   }
  }

  public void gameover(bool success)
  {
   if (ongameoverhandler != null)
   {
    ongameoverhandler(success);
   }
  }

  public void reset()
  {
   score = 0;
   step = 0;
   if (onstepchangehandler != null)
    onstepchangehandler(step);
   if (onscorechangehandler != null)
    onscorechangehandler(score);
   for (int i = 0; i < board.rowcount; i++)
   {
    for (int j = 0; j < board.columncount; j++)
    {
     remove(i, j);
    }
   }
  }
 }
}

gameboard.cs

using system;
using system.collections.generic;
using system.linq;
using system.text;
using system.windows.controls;
using system.diagnostics;

namespace game2048
{
 public class gameboard : canvas, icontrolable
 {
  private int rowcount = 4;
  
  public int rowcount
  {
   get
   {
    return rowcount;
   }
   set
   {
    rowcount = value;
   }
  }

  private int columncount = 4;
  public int columncount 
  {
   get
   {
    return columncount;
   }
   set
   {
    columncount = value;
   }
  }

  game game = null;

  public gameboard()
  {
   this.focusable = true;
   this.focus();
   this.reset();
  }

  public void reset()
  {
   settings.load();
   rowcount = settings.rowcount;
   columncount = settings.columncount;
  }

  public void init(game game)
  {
   this.game = game;
   game.init();
  }

  public void toleft()
  {
   game.toleft();
   debug.writeline("left");
  }

  public void toright()
  {
   game.toright();
   debug.writeline("right");
  }

  public void toup()
  {
   game.toup();
   debug.writeline("up");
  }

  public void todown()
  {
   game.todown();
   debug.writeline("down");
  }

  //合并,是否继续
  public bool union(int xindex, int yindex, direction dirct)
  {
   switch (dirct)
   {
    case direction.left:
     game.remove(xindex - 1, yindex);
     break;
    case direction.right:
     game.remove(xindex + 1, yindex);
     break;
    case direction.up:
     game.remove(xindex, yindex - 1);
     break;
    case direction.down:
     game.remove(xindex, yindex + 1);
     break;
    default:
     break;
   }
   bool ret = game.fillstate[yindex, xindex].changetext();
   if (ret)
   {
    game.gameover(true);
    return false;
   }
   game.incscore(game.fillstate[yindex, xindex].textindex);
   return true;
  }

  public int getstate(int xindex, int yindex)
  {
   if (xindex < 0 || xindex > columncount - 1)
    return 0;
   if (yindex < 0 || yindex > rowcount - 1)
    return 0;
   if (game.fillstate[yindex,xindex] == null)
    return 0;
   return game.fillstate[yindex, xindex].textindex;
  }

  public bool hasnoplace()
  {
   return this.children.count == this.rowcount * this.columncount+1;
  }

  public bool islocationfilled(int xindex,int yindex)
  {
   if (xindex < 0 || xindex > columncount-1)
    return true;
   if (yindex < 0 || yindex > rowcount-1)
    return true;
   if (game.fillstate[yindex, xindex] == null)
    return false;
   return game.fillstate[yindex, xindex].textindex>0;
  }

  public void setstate(int xindex,int yindex,colorblock block)
  {
   game.fillstate[yindex, xindex] = block;
  }
 }
}

源码下载地址:2048小游戏

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

上一篇:

下一篇: