WPF实现2048小游戏
程序员文章站
2023-12-19 16:13:34
前几天空闲的时候,实现了一个2048游戏。除了可以设置行数和列数之外,支持修...
前几天空闲的时候,实现了一个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; } } }
源码下载地址:2048小游戏
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。