当前位置: 移动技术网 > IT编程>开发语言>c# > WPF实现2048小游戏

WPF实现2048小游戏

2019年07月18日  | 移动技术网IT编程  | 我要评论

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

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

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

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

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

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

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

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

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

        图标使用expression design制作:

 

游戏效果如下:

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;
  }
 }
}

源码下载地址:

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网