Skip to content

Instantly share code, notes, and snippets.

@alphaKAI
Last active October 17, 2015 10:15
Show Gist options
  • Save alphaKAI/1ca0e57599f2208985b6 to your computer and use it in GitHub Desktop.
Save alphaKAI/1ca0e57599f2208985b6 to your computer and use it in GitHub Desktop.
The 2048 written in D.

#D2048 The 2048 written in D.

##How to use

  1. Place file as follow:
d2048Root/
  |-source/
  | \- d2048/
  |    |- core.d
  |    \- game.d
  \- app.d
  1. Execute dub init at d2048Root
  2. Execute dub
import std.stdio;
import std.string;
import d2048.game;
void main(){
D2048Game d2048 = new D2048Game;
d2048.startGame;
}
module d2048.core;
import std.stdio,
std.typecons,
std.algorithm.iteration,
std.random,
std.range;
class D2048Core{
alias Position = Tuple!(int, "x", int, "y");
static defaultWorldSize = Position(4, 4);
private int worldX,
worldY;
private int[][] world;
public int score;
this(){
this(defaultWorldSize);
}
this(Position worldSize){
worldX = worldSize.x;
worldY = worldSize.y;
world.length = worldY;
init;
}
void init(){
foreach(ref row; world){
row.length = worldX;
}
}
bool check(int[] array){
int prev = -1;
if(array.filter!(e => e != 0).array == null){
return false;
}
if(array[0] != 0){
if(array[1..$].filter!(e => e != 0).array == null)
return false;
}
foreach(i, n; array){
if(prev == 0)
return true;
else if(n == prev)
return true;
prev = n;
}
return false;
}
bool checkLeft(){
foreach(row; world)
if(check(row))
return true;
return false;
}
bool checkRight(){
foreach(row; world)
if(check(arrayReverse(row)))
return true;
return false;
}
bool checkDown(){
foreach(i; worldX.iota){
int[] col = worldY.iota.map!(j => world[j][i]).array;
if(check(arrayReverse(col)))
return true;
}
return false;
}
bool checkUp(){
foreach(i; worldX.iota){
int[] col = worldY.iota.map!(j => world[j][i]).array;
if(check(col))
return true;
}
return false;
}
int[] deleteZero(int[] row){
int[] zeros;
zeros.length = row.filter!"a == 0".array.length;
row = row.filter!"a != 0".array ~ zeros;
return row;
}
int[] move(int[] row){
int prev = -1;
row = deleteZero(row);
foreach(i, n; row){
if(n == prev){
row[i] *= 2;
row[i-1] = 0;
row = deleteZero(row);
prev = n * 2;
score += row[i];//Add Score
} else {
prev = n;
}
}
return row;
}
void moveLeft(){
foreach(ref row; world)
row = move(row);
}
void moveRight(){
foreach(ref row; world)
row = arrayReverse(row);
moveLeft;
foreach(ref row; world)
row = arrayReverse(row);
}
void moveUp(){
int[][] cols = worldX.iota.map!(x => worldY.iota.map!(y => world[y][x]).array).array;
foreach(ref col; cols)
col = move(col);
int[][] ws = worldY.iota.map!(y => worldX.iota.map!(x => cols[x][y]).array).array;
world = ws;
}
void moveDown(){
world = arrayReverse(world);
moveUp;
world = arrayReverse(world);
}
bool gameOver(){
if(!checkLeft
&& !checkRight
&& !checkUp
&& !checkDown)
return true;
else
return false;
}
void printWorld(){
foreach(row; world)
writeln(row);
}
void spawnNewBlock(){
Position[] positions;
Mt19937 gen;
foreach(y; worldY.iota)
foreach(x; worldX.iota){
if(world[y][x] == 0)
positions ~= Position(x,y);
}
gen.seed(unpredictableSeed);
ulong idx = gen.front % positions.length;
Position newPosition = positions[idx];
gen.seed(unpredictableSeed);
ulong N = gen.front % 100 + 1;
int newPoint = 1 <= N && N < 75 ? 2 : 4;
world[newPosition.y][newPosition.x] = newPoint;
}
T[] arrayReverse(T)(T[] base){
T[] rV;
foreach_reverse(e; base)
rV ~= e;
return rV;
}
}
module d2048.game;
import std.stdio,
std.string;
import d2048.core;
class D2048Game : D2048Core{
private ulong moves;
this(){
score = 0;
spawnNewBlock;
spawnNewBlock;
}
void startGame(){
writeln("====================");
writeln("D 2048");
writeln("[inputs]");
writeln("l: left");
writeln("r: right");
writeln("u: up");
writeln("d: down");
writeln("====================");
while(!gameOver){
bool noTouch;
printWorld;
writeln("--------------------");
writeln("moves:", moves);
writeln("score:", score);
write("[input]=> ");
string input = readln.chomp;
switch(input){
case "l":
moveLeft;
break;
case "r":
moveRight;
break;
case "u":
moveUp;
break;
case "d":
moveDown;
break;
default:
noTouch = true;
break;
}
if(!noTouch){
spawnNewBlock;
moves++;
}
}
writeln("GAME OVER");
writeln("moves:", moves);
writeln("score:", score);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment